From 611f57c5ac44f2f337dc26e8c6c2398538ac61bf Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 18 Feb 2023 14:52:10 +0100 Subject: [PATCH 001/676] Reset search logs --- lib/models/applied_filters.dart | 4 +-- lib/providers/logs_provider.dart | 14 ++++---- lib/screens/home/top_items.dart | 8 ++--- lib/screens/logs/logs.dart | 26 +++++++------- lib/screens/logs/logs_filters_modal.dart | 44 +++++++----------------- lib/screens/top_items/top_items.dart | 8 ++--- 6 files changed, 43 insertions(+), 61 deletions(-) diff --git a/lib/models/applied_filters.dart b/lib/models/applied_filters.dart index b281b42..2b60e71 100644 --- a/lib/models/applied_filters.dart +++ b/lib/models/applied_filters.dart @@ -1,11 +1,11 @@ class AppliedFiters { String selectedResultStatus = 'all'; - String? domainText; + String? searchText; List? clients; AppliedFiters({ required this.selectedResultStatus, - required this.domainText, + required this.searchText, required this.clients }); } \ No newline at end of file diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index 7c2411b..db2619c 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -12,7 +12,7 @@ class LogsProvider with ChangeNotifier { DateTime? _logsOlderThan; String _selectedResultStatus = 'all'; - String? _domainText; + String? _searchText; List? _selectedClients; int _logsQuantity = 100; @@ -20,7 +20,7 @@ class LogsProvider with ChangeNotifier { AppliedFiters _appliedFilters = AppliedFiters( selectedResultStatus: 'all', - domainText: null, + searchText: null, clients: null ); @@ -44,8 +44,8 @@ class LogsProvider with ChangeNotifier { return _selectedResultStatus; } - String? get domainText { - return _domainText; + String? get searchText { + return _searchText; } int get logsQuantity { @@ -98,7 +98,7 @@ class LogsProvider with ChangeNotifier { _logsOlderThan = null; _offset = 0; _selectedResultStatus = 'all'; - _domainText = null; + _searchText = null; notifyListeners(); } @@ -116,8 +116,8 @@ class LogsProvider with ChangeNotifier { notifyListeners(); } - void setDomainText(String? value) { - _domainText = value; + void setSearchText(String? value) { + _searchText = value; notifyListeners(); } diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 52ffeaf..5883523 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -140,24 +140,24 @@ class TopItems extends StatelessWidget { child: InkWell( onTap: () { if (type == 'topQueriedDomains' || type == 'topBlockedDomains') { - logsProvider.setDomainText(item.keys.toList()[0]); + logsProvider.setSearchText(item.keys.toList()[0]); logsProvider.setSelectedClients(null); logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: 'all', - domainText: item.keys.toList()[0], + searchText: item.keys.toList()[0], clients: null ) ); appConfigProvider.setSelectedScreen(2); } else if (type == 'topClients') { - logsProvider.setDomainText(null); + logsProvider.setSearchText(null); logsProvider.setSelectedClients([item.keys.toList()[0]]); logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: 'all', - domainText: null, + searchText: null, clients: [item.keys.toList()[0]] ) ); diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 3165010..f57460e 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -31,7 +31,7 @@ class Logs extends StatelessWidget { appConfigProvider: appConfigProvider, logsProvider: logsProvider, selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - domainText: logsProvider.appliedFilters.domainText, + searchText: logsProvider.appliedFilters.searchText, ); } } @@ -41,7 +41,7 @@ class LogsWidget extends StatefulWidget { final AppConfigProvider appConfigProvider; final LogsProvider logsProvider; final String selectedResultStatus; - final String? domainText; + final String? searchText; const LogsWidget({ Key? key, @@ -49,7 +49,7 @@ class LogsWidget extends StatefulWidget { required this.appConfigProvider, required this.logsProvider, required this.selectedResultStatus, - required this.domainText, + required this.searchText, }) : super(key: key); @override @@ -67,12 +67,12 @@ class _LogsWidgetState extends State { int? inOffset, bool? loadingMore, String? responseStatus, - String? domainText, + String? searchText, }) async { int offst = inOffset ?? widget.logsProvider.offset; String resStatus = responseStatus ?? widget.selectedResultStatus; - String? search = domainText ?? widget.domainText; + String? search = searchText ?? widget.searchText; if (loadingMore != null && loadingMore == true) { setState(() => isLoadingMore = true); @@ -402,7 +402,7 @@ class _LogsWidgetState extends State { ), const SizedBox(width: 5), ], - bottom: logsProvider.appliedFilters.domainText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null ? PreferredSize( preferredSize: const Size(double.maxFinite, 50), child: Container( @@ -421,7 +421,7 @@ class _LogsWidgetState extends State { child: ListView( scrollDirection: Axis.horizontal, children: [ - if (logsProvider.appliedFilters.domainText != null) ...[ + if (logsProvider.appliedFilters.searchText != null) ...[ const SizedBox(width: 15), Chip( avatar: const Icon( @@ -430,7 +430,7 @@ class _LogsWidgetState extends State { label: Row( children: [ Text( - logsProvider.appliedFilters.domainText!, + logsProvider.appliedFilters.searchText!, ), ], ), @@ -442,14 +442,14 @@ class _LogsWidgetState extends State { logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - domainText: null, + searchText: null, clients: logsProvider.appliedFilters.clients ) ); - logsProvider.setDomainText(null); + logsProvider.setSearchText(null); fetchLogs( inOffset: 0, - domainText: '' + searchText: '' ); }, ), @@ -475,7 +475,7 @@ class _LogsWidgetState extends State { logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: 'all', - domainText: logsProvider.appliedFilters.domainText, + searchText: logsProvider.appliedFilters.searchText, clients: logsProvider.appliedFilters.clients ) ); @@ -510,7 +510,7 @@ class _LogsWidgetState extends State { logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - domainText: logsProvider.appliedFilters.domainText, + searchText: logsProvider.appliedFilters.searchText, clients: null ) ); diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/logs_filters_modal.dart index 9f6dc7f..073cdea 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/logs_filters_modal.dart @@ -41,13 +41,11 @@ class LogsFiltersModalWidget extends StatefulWidget { } class _LogsFiltersModalWidgetState extends State { - TextEditingController domainController = TextEditingController(); - String? domainError; + TextEditingController searchController = TextEditingController(); @override void initState() { - domainController.text = widget.logsProvider.domainText ?? ''; - domainError = null; + searchController.text = widget.logsProvider.searchText ?? ''; super.initState(); } @@ -70,7 +68,7 @@ class _LogsFiltersModalWidgetState extends State { void resetFilters() async { setState(() { - domainController.text = ''; + searchController.text = ''; }); logsProvider.setLoadStatus(0); @@ -85,7 +83,7 @@ class _LogsFiltersModalWidgetState extends State { logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: 'all', - domainText: null, + searchText: null, clients: null ) ); @@ -134,13 +132,13 @@ class _LogsFiltersModalWidgetState extends State { count: logsProvider.logsQuantity, olderThan: logsProvider.logsOlderThan, responseStatus: logsProvider.selectedResultStatus, - search: logsProvider.domainText, + search: logsProvider.searchText, ); logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: logsProvider.selectedResultStatus, - domainText: logsProvider.domainText, + searchText: logsProvider.searchText, clients: logsProvider.selectedClients ) ); @@ -208,39 +206,25 @@ class _LogsFiltersModalWidgetState extends State { children: [ Expanded( child: TextFormField( - controller: domainController, - onChanged: (value) { - logsProvider.setDomainText(value); - RegExp domain = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); - if (value == '' || domain.hasMatch(value) == true) { - setState(() { - domainError = null; - }); - } - else { - setState(() { - domainError = AppLocalizations.of(context)!.invalidDomain; - }); - } - }, + controller: searchController, + onChanged: logsProvider.setSearchText, decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), + prefixIcon: const Icon(Icons.search_rounded), border: const OutlineInputBorder( borderRadius: BorderRadius.all( Radius.circular(10) ) ), - labelText: AppLocalizations.of(context)!.domain, + labelText: AppLocalizations.of(context)!.search, suffixIcon: IconButton( onPressed: () { setState(() { - domainController.text = ''; + searchController.text = ''; }); - logsProvider.setDomainText(null); + logsProvider.setSearchText(null); }, icon: const Icon(Icons.clear) ), - errorText: domainError ), ), ) @@ -294,9 +278,7 @@ class _LogsFiltersModalWidgetState extends State { child: Text(AppLocalizations.of(context)!.resetFilters) ), TextButton( - onPressed: domainError == null - ? () => filterLogs() - : null, + onPressed: () => filterLogs(), child: Text(AppLocalizations.of(context)!.apply) ), ], diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 1ddf272..efee2af 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -200,12 +200,12 @@ class _TopItemsScreenState extends State { return CustomListTile( onTap: () { if (widget.type == 'topQueriedDomains' || widget.type == 'topBlockedDomains') { - logsProvider.setDomainText(screenData[index].keys.toList()[0]); + logsProvider.setSearchText(screenData[index].keys.toList()[0]); logsProvider.setSelectedClients(null); logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: 'all', - domainText: screenData[index].keys.toList()[0], + searchText: screenData[index].keys.toList()[0], clients: null ) ); @@ -213,12 +213,12 @@ class _TopItemsScreenState extends State { Navigator.pop(context); } else if (widget.type == 'topClients') { - logsProvider.setDomainText(null); + logsProvider.setSearchText(null); logsProvider.setSelectedClients([screenData[index].keys.toList()[0]]); logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: 'all', - domainText: null, + searchText: null, clients: [screenData[index].keys.toList()[0]] ) ); From 252026319d1192dcddb18457827693d022633145 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 18 Feb 2023 15:03:17 +0100 Subject: [PATCH 002/676] Tap on active client to see logs --- lib/screens/clients/clients_list.dart | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index ee371f3..f56c731 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -1,9 +1,13 @@ +import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/providers/logs_provider.dart'; class ClientsList extends StatelessWidget { final ScrollController scrollController; @@ -21,6 +25,9 @@ class ClientsList extends StatelessWidget { @override Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + final logsProvider = Provider.of(context); + switch (loadStatus) { case 0: return SizedBox( @@ -62,6 +69,18 @@ class ClientsList extends StatelessWidget { color: Theme.of(context).colorScheme.onSurface ), ), + onTap: () { + logsProvider.setSearchText(null); + logsProvider.setSelectedClients([data[index].ip]); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: null, + clients: [data[index].ip] + ) + ); + appConfigProvider.setSelectedScreen(2); + }, ) ); } From 0c23ed942ac2291c2777feb1e01208cf3869fbc9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Feb 2023 18:57:17 +0100 Subject: [PATCH 003/676] Bug fixes --- lib/screens/filters/add_custom_rule.dart | 77 +--------------------- lib/widgets/servers_list/servers_list.dart | 4 +- 2 files changed, 3 insertions(+), 78 deletions(-) diff --git a/lib/screens/filters/add_custom_rule.dart b/lib/screens/filters/add_custom_rule.dart index 82b6bb9..a0941c1 100644 --- a/lib/screens/filters/add_custom_rule.dart +++ b/lib/screens/filters/add_custom_rule.dart @@ -91,47 +91,6 @@ class _AddCustomRuleState extends State { @override Widget build(BuildContext context) { - final appConfigProvider = Provider.of(context); - - Map presets = { - 0: Text( - AppLocalizations.of(context)!.block, - style: TextStyle( - color: appConfigProvider.useDynamicColor == true - ? Theme.of(context).floatingActionButtonTheme.foregroundColor! - : preset == 0 - ? Colors.white - : Theme.of(context).colorScheme.primary, - fontSize: 14, - fontWeight: FontWeight.w500 - ), - ), - 1: Text( - AppLocalizations.of(context)!.unblock, - style: TextStyle( - color: appConfigProvider.useDynamicColor == true - ? Theme.of(context).floatingActionButtonTheme.foregroundColor! - : preset == 1 - ? Colors.white - : Theme.of(context).colorScheme.primary, - fontSize: 14, - fontWeight: FontWeight.w500 - ), - ), - 2: Text( - AppLocalizations.of(context)!.custom, - style: TextStyle( - color: appConfigProvider.useDynamicColor == true - ? Theme.of(context).floatingActionButtonTheme.foregroundColor! - : preset == 2 - ? Colors.white - : Theme.of(context).colorScheme.primary, - fontSize: 14, - fontWeight: FontWeight.w500 - ), - ), - }; - return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.addCustomRule), @@ -403,38 +362,4 @@ class _AddCustomRuleState extends State { ), ); } -} - // Padding( - // padding: const EdgeInsets.only( - // left: 28, - // right: 28, - // top: 20, - // bottom: 28 - // ), - // child: Row( - // mainAxisAlignment: MainAxisAlignment.end, - // children: [ - // TextButton( - // onPressed: () => Navigator.pop(context), - // child: Text(AppLocalizations.of(context)!.cancel) - // ), - // const SizedBox(width: 20), - // TextButton( - // onPressed: checkValidValues() == true - // ? () { - // Navigator.pop(context); - // widget.onConfirm(buildRule()); - // } - // : null, - // child: Text( - // AppLocalizations.of(context)!.confirm, - // style: TextStyle( - // color: checkValidValues() == true - // ? Theme.of(context).colorScheme.primary - // : Colors.grey - // ), - // ) - // ), - // ], - // ), - // ) \ No newline at end of file +} \ No newline at end of file diff --git a/lib/widgets/servers_list/servers_list.dart b/lib/widgets/servers_list/servers_list.dart index 1d6123c..ea0fc35 100644 --- a/lib/widgets/servers_list/servers_list.dart +++ b/lib/widgets/servers_list/servers_list.dart @@ -187,12 +187,12 @@ class _ServersListState extends State with SingleTickerProviderStat Container( padding: const EdgeInsets.all(1), decoration: BoxDecoration( - color: Theme.of(context).floatingActionButtonTheme.backgroundColor, + color: Theme.of(context).colorScheme.primaryContainer, borderRadius: BorderRadius.circular(20) ), child: Icon( Icons.star, - color: Theme.of(context).floatingActionButtonTheme.foregroundColor, + color: Theme.of(context).colorScheme.onPrimaryContainer, size: 10, ), ), From 156b6a12e352b1e33d04c71a63f2e46ac2309c4d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Feb 2023 19:02:15 +0100 Subject: [PATCH 004/676] Updated app & dart version --- pubspec.lock | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 4225038..fd32536 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -651,5 +651,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.18.1 <4.0.0" + dart: ">=2.18.1 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index 5e2acf3..22bdcb9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.11.0+45 +version: 1.12.0+46 environment: sdk: '>=2.18.1 <3.0.0' From a736516e7bc3f751b8c730726cb42cfec69e6cdd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 16 Mar 2023 23:29:18 +0100 Subject: [PATCH 005/676] Ui improvements and iOS improvements --- ios/Runner.xcodeproj/project.pbxproj | 4 +- lib/screens/clients/clients.dart | 1 + lib/screens/clients/tags_modal.dart | 58 +++++++--- lib/screens/filters/add_list_modal.dart | 9 +- ...cren.dart => blocked_services_screen.dart} | 7 +- lib/screens/filters/filters.dart | 3 +- lib/screens/filters/list_details_screen.dart | 4 +- .../filters/update_interval_lists_modal.dart | 7 +- lib/screens/home/management_modal.dart | 9 +- lib/screens/logs/clients_modal.dart | 26 +++-- lib/screens/logs/filter_status_modal.dart | 9 +- lib/screens/logs/logs.dart | 1 + lib/screens/logs/logs_config_modal.dart | 102 ++++++++++-------- lib/screens/logs/logs_filters_modal.dart | 5 +- lib/screens/servers/servers.dart | 5 +- .../access_settings/access_settings.dart | 69 ++++++------ .../access_settings/add_client_modal.dart | 9 +- .../access_settings/clients_list.dart | 6 +- lib/screens/settings/advanced_setings.dart | 1 + .../settings/customization/customization.dart | 1 + lib/screens/settings/dhcp/dhcp.dart | 1 + .../settings/dhcp/select_interface_modal.dart | 47 ++++---- .../dns_rewrites/add_dns_rewrite_modal.dart | 9 +- .../settings/dns_rewrites/dns_rewrites.dart | 1 + .../settings/encryption/encryption.dart | 1 + lib/screens/settings/general_settings.dart | 3 +- .../settings/server_info/server_info.dart | 1 + lib/screens/settings/settings.dart | 5 +- lib/widgets/custom_list_tile.dart | 2 +- 29 files changed, 245 insertions(+), 161 deletions(-) rename lib/screens/filters/{blocked_services_scren.dart => blocked_services_screen.dart} (97%) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 972c5ab..1ffa568 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -217,6 +217,7 @@ }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -231,6 +232,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index f411da9..f64f3fd 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -104,6 +104,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM title: Text(AppLocalizations.of(context)!.clients), pinned: true, floating: true, + centerTitle: false, forceElevated: innerBoxIsScrolled, actions: [ if (serversProvider.clients.loadStatus == 1) ...[ diff --git a/lib/screens/clients/tags_modal.dart b/lib/screens/clients/tags_modal.dart index b8d0afe..42843b1 100644 --- a/lib/screens/clients/tags_modal.dart +++ b/lib/screens/clients/tags_modal.dart @@ -68,20 +68,54 @@ class _TagsModalState extends State { child: ListView.builder( shrinkWrap: true, itemCount: widget.tags.length, - itemBuilder: (context, index) => CheckboxListTile( - title: Text( - widget.tags[index], - style: TextStyle( - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface + itemBuilder: (context, index) => Material( + color: Colors.transparent, + child: InkWell( + onTap: () => checkUncheckTag(!selectedTags.contains(widget.tags[index]), widget.tags[index]), + child: Container( + padding: const EdgeInsets.only( + left: 24, + top: 8, + bottom: 8, + right: 12 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.tags[index], + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + Checkbox( + value: selectedTags.contains(widget.tags[index]), + onChanged: (value) => checkUncheckTag(value!, widget.tags[index]), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + ) + ], + ), ), ), - value: selectedTags.contains(widget.tags[index]), - checkboxShape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5) - ), - onChanged: (value) => checkUncheckTag(value!, widget.tags[index]) - ) + ), + // itemBuilder: (context, index) => CheckboxListTile( + // title: Text( + // widget.tags[index], + // style: TextStyle( + // fontWeight: FontWeight.normal, + // color: Theme.of(context).colorScheme.onSurface + // ), + // ), + // value: selectedTags.contains(widget.tags[index]), + // checkboxShape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(5) + // ), + // onChanged: (value) => checkUncheckTag(value!, widget.tags[index]) + // ) ), ), actions: [ diff --git a/lib/screens/filters/add_list_modal.dart b/lib/screens/filters/add_list_modal.dart index d76d55b..196cda1 100644 --- a/lib/screens/filters/add_list_modal.dart +++ b/lib/screens/filters/add_list_modal.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -69,7 +71,7 @@ class _AddListModalState extends State { return Padding( padding: MediaQuery.of(context).viewInsets, child: Container( - height: 370, + height: Platform.isIOS ? 386 : 370, decoration: BoxDecoration( borderRadius: const BorderRadius.only( topLeft: Radius.circular(28), @@ -81,7 +83,7 @@ class _AddListModalState extends State { children: [ Expanded( child: ListView( - physics: 410 < MediaQuery.of(context).size.height + physics: (Platform.isIOS ? 426 : 410) < MediaQuery.of(context).size.height ? const NeverScrollableScrollPhysics() : null, children: [ @@ -192,7 +194,8 @@ class _AddListModalState extends State { ), ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ), ), diff --git a/lib/screens/filters/blocked_services_scren.dart b/lib/screens/filters/blocked_services_screen.dart similarity index 97% rename from lib/screens/filters/blocked_services_scren.dart rename to lib/screens/filters/blocked_services_screen.dart index 710a714..fba09d2 100644 --- a/lib/screens/filters/blocked_services_scren.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -146,7 +146,12 @@ class _BlockedServicesScreenStateWidget extends State with TickerProviderStateM pinned: true, floating: true, forceElevated: innerBoxIsScrolled, + centerTitle: false, actions: serversProvider.filtering.loadStatus == 1 ? [ IconButton( onPressed: enableDisableFiltering, diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index eccb130..ebf6aca 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; @@ -301,7 +303,7 @@ class _ListDetailsScreenState extends State { curve: Curves.easeInOut, bottom: fabVisible ? appConfigProvider.showingSnackbar - ? 70 : 20 + ? 70 : (Platform.isIOS ? 40 : 20) : -70, right: 20, child: FloatingActionButton( diff --git a/lib/screens/filters/update_interval_lists_modal.dart b/lib/screens/filters/update_interval_lists_modal.dart index c471c96..1779bf9 100644 --- a/lib/screens/filters/update_interval_lists_modal.dart +++ b/lib/screens/filters/update_interval_lists_modal.dart @@ -42,7 +42,7 @@ class _UpdateIntervalListsModalState extends State { return Padding( padding: mediaQueryData.viewInsets, child: Container( - height: 390, + height: Platform.isIOS ? 406 : 390, decoration: BoxDecoration( color: Theme.of(context).dialogBackgroundColor, borderRadius: const BorderRadius.only( @@ -55,7 +55,7 @@ class _UpdateIntervalListsModalState extends State { children: [ Expanded( child: ListView( - physics: 410 < MediaQuery.of(context).size.height + physics: (Platform.isIOS ? 426 : 410) < MediaQuery.of(context).size.height ? const NeverScrollableScrollPhysics() : null, children: [ @@ -298,7 +298,8 @@ class _UpdateIntervalListsModalState extends State { ), ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ), ), diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 3852e0e..15664c5 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -123,7 +125,7 @@ class ManagementModal extends StatelessWidget { return Container( width: double.maxFinite, - height: 540, + height: Platform.isIOS ? 556 : 540, decoration: BoxDecoration( color: Theme.of(context).dialogBackgroundColor, borderRadius: const BorderRadius.only( @@ -135,7 +137,7 @@ class ManagementModal extends StatelessWidget { children: [ Expanded( child: ListView( - physics: 540 < MediaQuery.of(context).size.height + physics: (Platform.isIOS ? 556 : 540) < MediaQuery.of(context).size.height ? const NeverScrollableScrollPhysics() : null, children: [ @@ -202,7 +204,8 @@ class ManagementModal extends StatelessWidget { ), ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ), ); diff --git a/lib/screens/logs/clients_modal.dart b/lib/screens/logs/clients_modal.dart index c8c157d..f9b9099 100644 --- a/lib/screens/logs/clients_modal.dart +++ b/lib/screens/logs/clients_modal.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -48,15 +50,22 @@ class _ClientsModalState extends State { child: InkWell( onTap: () => onChanged(), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), + padding: const EdgeInsets.only( + left: 24, + top: 8, + right: 12, + bottom: 8 + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - label, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface + Flexible( + child: Text( + label, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), ), ), Checkbox( @@ -88,7 +97,7 @@ class _ClientsModalState extends State { return Container( height: height >= (logsProvider.clients!.length*64) == true ? logsProvider.clients!.length*64 - : height-25, + : height-50, decoration: BoxDecoration( borderRadius: const BorderRadius.only( topLeft: Radius.circular(28), @@ -164,7 +173,8 @@ class _ClientsModalState extends State { ) ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ), ); diff --git a/lib/screens/logs/filter_status_modal.dart b/lib/screens/logs/filter_status_modal.dart index 371f3ab..16d9c5c 100644 --- a/lib/screens/logs/filter_status_modal.dart +++ b/lib/screens/logs/filter_status_modal.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -82,8 +84,8 @@ class _FilterStatusModalState extends State { } return Container( - height: height >= 720 == true - ? 720 + height: height >= (Platform.isIOS ? 736 : 720) == true + ? (Platform.isIOS ? 736 : 720) : height-25, decoration: BoxDecoration( borderRadius: const BorderRadius.only( @@ -183,7 +185,8 @@ class _FilterStatusModalState extends State { ) ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ), ); diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index f57460e..a70abfa 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -379,6 +379,7 @@ class _LogsWidgetState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.logs), + centerTitle: false, actions: [ logsProvider.loadStatus == 1 ? IconButton( diff --git a/lib/screens/logs/logs_config_modal.dart b/lib/screens/logs/logs_config_modal.dart index 7fd4a67..9a33dbf 100644 --- a/lib/screens/logs/logs_config_modal.dart +++ b/lib/screens/logs/logs_config_modal.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -122,7 +124,7 @@ class _LogsConfigModalWidgetState extends State { children: [ Expanded( child: ListView( - physics: 420 < MediaQuery.of(context).size.height + physics: (Platform.isIOS ? 436 : 420) < MediaQuery.of(context).size.height ? const NeverScrollableScrollPhysics() : null, children: [ @@ -178,54 +180,61 @@ class _LogsConfigModalWidgetState extends State { ), ), const SizedBox(height: 16), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => setState(() => anonymizeClientIp = !anonymizeClientIp), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 30), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.anonymizeClientIp, - style: const TextStyle( - fontSize: 16 + Padding( + padding: const EdgeInsets.symmetric(horizontal: 14), + child: Column( + children: [ + Material( + color: Colors.transparent, + child: InkWell( + onTap: () => setState(() => anonymizeClientIp = !anonymizeClientIp), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.anonymizeClientIp, + style: const TextStyle( + fontSize: 16 + ), + ), + Switch( + value: anonymizeClientIp, + onChanged: (value) => setState(() => anonymizeClientIp = value), + activeColor: Theme.of(context).colorScheme.primary, + ) + ], ), ), - Switch( - value: anonymizeClientIp, - onChanged: (value) => setState(() => anonymizeClientIp = value), - activeColor: Theme.of(context).colorScheme.primary, - ) - ], + ), ), - ), - ), - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: DropdownButtonFormField( - items: retentionItems.map>((Map item) { - return DropdownMenuItem( - value: item['value'].toString(), - child: Text(item['label']), - ); - }).toList(), - value: retentionTime, - onChanged: (value) => setState(() => retentionTime = value), - decoration: InputDecoration( - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: DropdownButtonFormField( + items: retentionItems.map>((Map item) { + return DropdownMenuItem( + value: item['value'].toString(), + child: Text(item['label']), + ); + }).toList(), + value: retentionTime, + onChanged: (value) => setState(() => retentionTime = value), + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + label: Text(AppLocalizations.of(context)!.retentionTime) + ), + borderRadius: BorderRadius.circular(20), + ), ), - label: Text(AppLocalizations.of(context)!.retentionTime) - ), - borderRadius: BorderRadius.circular(20), + ], ), - ), + ) ], ), ), @@ -272,7 +281,8 @@ class _LogsConfigModalWidgetState extends State { ) ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ); @@ -310,7 +320,7 @@ class _LogsConfigModalWidgetState extends State { } return Container( - height: 420, + height: Platform.isIOS ? 436 : 420, decoration: BoxDecoration( borderRadius: const BorderRadius.only( topLeft: Radius.circular(28), diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/logs_filters_modal.dart index 073cdea..ecc23c7 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/logs_filters_modal.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -283,7 +285,8 @@ class _LogsFiltersModalWidgetState extends State { ), ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ), ), diff --git a/lib/screens/servers/servers.dart b/lib/screens/servers/servers.dart index a8423b3..9e98e29 100644 --- a/lib/screens/servers/servers.dart +++ b/lib/screens/servers/servers.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/rendering.dart'; @@ -69,6 +71,7 @@ class _ServersState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.servers), + centerTitle: false, ), body: Stack( children: [ @@ -83,7 +86,7 @@ class _ServersState extends State { curve: Curves.easeInOut, bottom: isVisible ? appConfigProvider.showingSnackbar - ? 70 : 20 + ? 70 : (Platform.isIOS ? 40 : 20) : -70, right: 20, child: FloatingActionButton( diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index f6db465..08f96a2 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -87,6 +87,7 @@ class _AccessSettingsWidgetState extends State with Ticker title: Text(AppLocalizations.of(context)!.accessSettings), pinned: true, floating: true, + centerTitle: false, forceElevated: innerBoxIsScrolled, bottom: TabBar( controller: tabController, @@ -112,45 +113,35 @@ class _AccessSettingsWidgetState extends State with Ticker ) ]; }), - body: Container( - decoration: BoxDecoration( - color: Theme.of(context).scaffoldBackgroundColor, - border: Border( - top: BorderSide( - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.1) - ) - ) - ), - child: TabBarView( - controller: tabController, - children: [ - ClientsList( - type: 'allowed', - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == 1 - ? serversProvider.clients.data!.clientsAllowedBlocked!.allowedClients : [], - fetchClients: fetchClients - ), - ClientsList( - type: 'disallowed', - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == 1 - ? serversProvider.clients.data!.clientsAllowedBlocked!.disallowedClients : [], - fetchClients: fetchClients - ), - ClientsList( - type: 'domains', - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == 1 - ? serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts : [], - fetchClients: fetchClients - ), - ] - ) - ), + body: TabBarView( + controller: tabController, + children: [ + ClientsList( + type: 'allowed', + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == 1 + ? serversProvider.clients.data!.clientsAllowedBlocked!.allowedClients : [], + fetchClients: fetchClients + ), + ClientsList( + type: 'disallowed', + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == 1 + ? serversProvider.clients.data!.clientsAllowedBlocked!.disallowedClients : [], + fetchClients: fetchClients + ), + ClientsList( + type: 'domains', + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == 1 + ? serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts : [], + fetchClients: fetchClients + ), + ] + ) ) ), ); diff --git a/lib/screens/settings/access_settings/add_client_modal.dart b/lib/screens/settings/access_settings/add_client_modal.dart index 2aa91e6..385409b 100644 --- a/lib/screens/settings/access_settings/add_client_modal.dart +++ b/lib/screens/settings/access_settings/add_client_modal.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -66,7 +68,7 @@ class _AddClientModalState extends State { return Padding( padding: MediaQuery.of(context).viewInsets, child: Container( - height: 305, + height: Platform.isIOS ? 321 : 305, padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Theme.of(context).dialogBackgroundColor, @@ -79,7 +81,7 @@ class _AddClientModalState extends State { children: [ Expanded( child: ListView( - physics: 322 < MediaQuery.of(context).size.height + physics: (Platform.isIOS ? 338 : 322) < MediaQuery.of(context).size.height ? const NeverScrollableScrollPhysics() : null, children: [ @@ -146,7 +148,8 @@ class _AddClientModalState extends State { ), ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ), ), diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 9efcaa7..2d6f787 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; @@ -317,7 +319,7 @@ class _ClientsListState extends State { curve: Curves.easeInOut, bottom: isVisible ? appConfigProvider.showingSnackbar - ? 70 : 20 + ? 70 : (Platform.isIOS ? 40 : 20) : -70, right: 20, child: FloatingActionButton( @@ -341,7 +343,7 @@ class _ClientsListState extends State { case 2: return SizedBox( width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, + height: MediaQuery.of(context).size.height-101, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index b0cbc5a..f1da7f5 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -39,6 +39,7 @@ class AdvancedSettings extends StatelessWidget { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.advancedSettings), + centerTitle: false, ), body: ListView( children: [ diff --git a/lib/screens/settings/customization/customization.dart b/lib/screens/settings/customization/customization.dart index 9f6abe2..e955323 100644 --- a/lib/screens/settings/customization/customization.dart +++ b/lib/screens/settings/customization/customization.dart @@ -59,6 +59,7 @@ class _CustomizationWidgetState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.customization), + centerTitle: false, ), body: ListView( children: [ diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 8c4bb94..3ba3b68 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -765,6 +765,7 @@ class _DhcpWidgetState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.dhcpSettings), + centerTitle: false, actions: selectedInterface != null ? [ IconButton( onPressed: checkDataValid() == true diff --git a/lib/screens/settings/dhcp/select_interface_modal.dart b/lib/screens/settings/dhcp/select_interface_modal.dart index 49b5957..202281c 100644 --- a/lib/screens/settings/dhcp/select_interface_modal.dart +++ b/lib/screens/settings/dhcp/select_interface_modal.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -137,20 +139,15 @@ class SelectInterfaceModal extends StatelessWidget { if (interfaces[index].ipv4Addresses.isNotEmpty) ...[ Row( children: [ - Text( - "${AppLocalizations.of(context)!.ipv4addresses}: ", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant + Flexible( + child: Text( + "${AppLocalizations.of(context)!.ipv4addresses}: ${interfaces[index].ipv4Addresses.join(', ')}", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), ), - ), - Text( - interfaces[index].ipv4Addresses.join(', '), - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), + ) ], ), const SizedBox(height: 5), @@ -158,20 +155,15 @@ class SelectInterfaceModal extends StatelessWidget { if (interfaces[index].ipv6Addresses.isNotEmpty) ...[ Row( children: [ - Text( - "${AppLocalizations.of(context)!.ipv4addresses}: ", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant + Flexible( + child: Text( + "${AppLocalizations.of(context)!.ipv6addresses}: ${interfaces[index].ipv6Addresses.join(', ')}", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), ), - ), - Text( - interfaces[index].ipv6Addresses.join(', '), - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), + ) ], ), ] @@ -195,7 +187,8 @@ class SelectInterfaceModal extends StatelessWidget { ) ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ), ); diff --git a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart index 3009553..53bc3b2 100644 --- a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -51,7 +53,7 @@ class _AddDnsRewriteModalState extends State { return Padding( padding: MediaQuery.of(context).viewInsets, child: Container( - height: 400, + height: Platform.isIOS ? 416 : 400, decoration: BoxDecoration( borderRadius: const BorderRadius.only( topLeft: Radius.circular(28), @@ -63,7 +65,7 @@ class _AddDnsRewriteModalState extends State { children: [ Expanded( child: ListView( - physics: 410 < MediaQuery.of(context).size.height + physics: (Platform.isIOS ? 426 : 410) < MediaQuery.of(context).size.height ? const NeverScrollableScrollPhysics() : null, children: [ @@ -155,7 +157,8 @@ class _AddDnsRewriteModalState extends State { ), ], ), - ) + ), + if (Platform.isIOS) const SizedBox(height: 16) ], ), ), diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 05407bf..119da4c 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -283,6 +283,7 @@ class _DnsRewritesWidgetState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.dnsRewrites), + centerTitle: false, ), body: generateBody(), floatingActionButton: FloatingActionButton( diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 2c136fe..120dab3 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -630,6 +630,7 @@ class _EncryptionSettingsWidgetState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.encryptionSettings), + centerTitle: false, actions: [ IconButton( onPressed: certKeyValidApi == 2 && validDataError != null diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index cf27e34..afad45e 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -57,7 +57,8 @@ class GeneralSettings extends StatelessWidget { return Scaffold( appBar: AppBar( - title: Text(AppLocalizations.of(context)!.generalSettings) , + title: Text(AppLocalizations.of(context)!.generalSettings), + centerTitle: false, ), body: ListView( children: [ diff --git a/lib/screens/settings/server_info/server_info.dart b/lib/screens/settings/server_info/server_info.dart index 35abb52..607e822 100644 --- a/lib/screens/settings/server_info/server_info.dart +++ b/lib/screens/settings/server_info/server_info.dart @@ -179,6 +179,7 @@ class _ServerInformationWidgetState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.serverInformation), + centerTitle: false, ), body: generateBody() ); diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 0031768..21dff92 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -57,7 +57,10 @@ class Settings extends StatelessWidget { } return Scaffold( - appBar: const SettingsAppBar(), + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.settings), + centerTitle: false, + ), body: ListView( children: [ if (serversProvider.selectedServer != null) ...[ diff --git a/lib/widgets/custom_list_tile.dart b/lib/widgets/custom_list_tile.dart index 629d7a7..34a7c80 100644 --- a/lib/widgets/custom_list_tile.dart +++ b/lib/widgets/custom_list_tile.dart @@ -85,7 +85,7 @@ class CustomListTile extends StatelessWidget { ), ), if (trailing != null) ...[ - const SizedBox(width: 10), + const SizedBox(width: 16), trailing! ] ], From cfd111986412690ce8a14698b7eda998d55cf43b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 16 Mar 2023 23:36:41 +0100 Subject: [PATCH 006/676] More improvements --- lib/screens/logs/logs_filters_modal.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/logs_filters_modal.dart index ecc23c7..e9a6052 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/logs_filters_modal.dart @@ -164,7 +164,7 @@ class _LogsFiltersModalWidgetState extends State { return Padding( padding: MediaQuery.of(context).viewInsets, child: Container( - height: 455, + height: Platform.isIOS ? 446 : 430, decoration: BoxDecoration( color: Theme.of(context).dialogBackgroundColor, borderRadius: const BorderRadius.only( @@ -176,7 +176,7 @@ class _LogsFiltersModalWidgetState extends State { children: [ Expanded( child: ListView( - physics: 400 < MediaQuery.of(context).size.height + physics: (Platform.isIOS ? 416 : 400) < MediaQuery.of(context).size.height ? const NeverScrollableScrollPhysics() : null, children: [ From 602bec77c2e231b1798df47f2816350d372bc81f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 16 Mar 2023 23:40:19 +0100 Subject: [PATCH 007/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 22bdcb9..d15fa9c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.12.0+46 +version: 1.12.1+47 environment: sdk: '>=2.18.1 <3.0.0' From df6af8a29a1ae2d9c71c0f038438a397bc804da3 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo <47545344+JGeek00@users.noreply.github.com> Date: Mon, 20 Mar 2023 04:29:50 +0100 Subject: [PATCH 008/676] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aabbe0f..c4df27d 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,9 @@ AdGuard Home Manager does not collect any personal user data. All data stored in ## Disclaimer This is an unofficial application. The AdGuard Home team and the development of the AdGuard Home software is not related in any way with this application. +## Recommended configuration and lists +On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a recommended configuration for AdGuard Home and some lists. Thanks to [JuanRodenas](https://github.com/JuanRodenas). + ## Third party libraries - [provider](https://pub.dev/packages/provider) - [sqflite](https://pub.dev/packages/sqflite) @@ -60,4 +63,4 @@ This is an unofficial application. The AdGuard Home team and the development of
-##### Created by JGeek00 \ No newline at end of file +##### Created by JGeek00 From 9cf505e27a2996995151b005f3144cd3eeef608b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Mar 2023 21:17:48 +0100 Subject: [PATCH 009/676] Connect with no authentication --- lib/models/server.dart | 12 +++--- lib/services/http_requests.dart | 8 +++- lib/widgets/add_server_modal.dart | 62 ++++++++----------------------- 3 files changed, 27 insertions(+), 55 deletions(-) diff --git a/lib/models/server.dart b/lib/models/server.dart index 162cef7..6c50164 100644 --- a/lib/models/server.dart +++ b/lib/models/server.dart @@ -5,10 +5,10 @@ class Server { String domain; String? path; int? port; - String user; - String password; + String? user; + String? password; bool defaultServer; - String authToken; + String? authToken; bool runningOnHa; Server({ @@ -18,10 +18,10 @@ class Server { required this.domain, this.path, this.port, - required this.user, - required this.password, + this.user, + this.password, required this.defaultServer, - required this.authToken, + this.authToken, required this.runningOnHa, }); } \ No newline at end of file diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 5e249e9..1647526 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -35,7 +35,9 @@ Future> apiRequest({ HttpClient httpClient = HttpClient(); if (method == 'get') { HttpClientRequest request = await httpClient.getUrl(Uri.parse(connectionString)); - request.headers.set('Authorization', 'Basic ${server.authToken}'); + if (server.authToken != null) { + request.headers.set('Authorization', 'Basic ${server.authToken}'); + } HttpClientResponse response = overrideTimeout == true ? await request.close() : await request.close().timeout(const Duration(seconds: 10)); @@ -60,7 +62,9 @@ Future> apiRequest({ } else if (method == 'post') { HttpClientRequest request = await httpClient.postUrl(Uri.parse(connectionString)); - request.headers.set('Authorization', 'Basic ${server.authToken}'); + if (server.authToken != null) { + request.headers.set('Authorization', 'Basic ${server.authToken}'); + } request.headers.set('content-type', 'application/json'); request.add(utf8.encode(json.encode(body))); HttpClientResponse response = overrideTimeout == true diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index e6a7c75..9c81da4 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -44,10 +44,8 @@ class _AddServerModalState extends State { String? portError; final TextEditingController userController = TextEditingController(); - String? userError; final TextEditingController passwordController = TextEditingController(); - String? passwordError; bool defaultServer = false; @@ -114,9 +112,7 @@ class _AddServerModalState extends State { ipDomainController.text != '' && ipDomainError == null && pathError == null && - portError == null && - userController.text != '' && - passwordController.text != '' + portError == null ) { setState(() { allDataValid = true; @@ -196,34 +192,6 @@ class _AddServerModalState extends State { checkDataValid(); } - void validateUser(String? value) { - if (value != null && value != '') { - setState(() { - userError = null; - }); - } - else { - setState(() { - userError = AppLocalizations.of(context)!.userNotEmpty; - }); - } - checkDataValid(); - } - - void validatePassword(String? value) { - if (value != null && value != '') { - setState(() { - passwordError = null; - }); - } - else { - setState(() { - passwordError = AppLocalizations.of(context)!.passwordNotEmpty; - }); - } - checkDataValid(); - } - @override void initState() { if (widget.server != null) { @@ -232,8 +200,8 @@ class _AddServerModalState extends State { ipDomainController.text = widget.server!.domain; pathController.text = widget.server!.path ?? ''; portController.text = widget.server!.port != null ? widget.server!.port.toString() : ""; - userController.text = widget.server!.user; - passwordController.text = widget.server!.password; + userController.text = widget.server!.user ?? ""; + passwordController.text = widget.server!.password ?? ""; defaultServer = widget.server!.defaultServer; homeAssistant = widget.server!.runningOnHa; } @@ -255,12 +223,12 @@ class _AddServerModalState extends State { connectionMethod: connectionType.name, domain: ipDomainController.text, port: portController.text != '' ? int.parse(portController.text) : null, - user: userController.text, - password: passwordController.text, + user: userController.text != "" ? userController.text : null, + password: passwordController.text != "" ? passwordController.text : null, defaultServer: defaultServer, authToken: homeAssistant == true ? encodeBase64UserPass(userController.text, passwordController.text) - : '', + : null, runningOnHa: homeAssistant ); setState(() => isConnecting = true); @@ -272,7 +240,9 @@ class _AddServerModalState extends State { setState(() => isConnecting = false); if (result['result'] == 'success') { - serverObj.authToken = encodeBase64UserPass(serverObj.user, serverObj.password); + if (serverObj.user != null && serverObj.password != null) { + serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); + } final serverCreated = await serversProvider.createServer(serverObj); if (serverCreated == null) { serversProvider.setServerStatusLoad(0); @@ -366,12 +336,12 @@ class _AddServerModalState extends State { connectionMethod: connectionType.name, domain: ipDomainController.text, port: portController.text != '' ? int.parse(portController.text) : null, - user: userController.text, - password: passwordController.text, + user: userController.text != "" ? userController.text : null, + password: passwordController.text != "" ? passwordController.text : null, defaultServer: defaultServer, authToken: homeAssistant == true ? encodeBase64UserPass(userController.text, passwordController.text) - : '', + : null, runningOnHa: homeAssistant ); @@ -380,7 +350,9 @@ class _AddServerModalState extends State { : await login(serverObj); if (result['result'] == 'success') { - serverObj.authToken = encodeBase64UserPass(serverObj.user, serverObj.password); + if (serverObj.user != null && serverObj.password != null) { + serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); + } final serverSaved = await serversProvider.editServer(serverObj); if (serverSaved == null) { Navigator.pop(context); @@ -576,8 +548,6 @@ class _AddServerModalState extends State { label: AppLocalizations.of(context)!.username, controller: userController, icon: Icons.person_rounded, - onChanged: validateUser, - error: userError ), const SizedBox(height: 20), textField( @@ -585,8 +555,6 @@ class _AddServerModalState extends State { controller: passwordController, icon: Icons.lock_rounded, keyboardType: TextInputType.visiblePassword, - onChanged: validatePassword, - error: passwordError, obscureText: true ), sectionLabel(AppLocalizations.of(context)!.other), From be71e57efeb1523abedc530f29281a57cccd5fb2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Mar 2023 21:21:38 +0100 Subject: [PATCH 010/676] Allow domains without dot --- lib/widgets/add_server_modal.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 9c81da4..e67cf16 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -172,7 +172,7 @@ class _AddServerModalState extends State { void validateAddress(String? value) { if (value != null && value != '') { RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); - RegExp domain = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); + RegExp domain = RegExp(r'^(([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+)|((\w|-)+)$'); if (ipAddress.hasMatch(value) == true || domain.hasMatch(value) == true) { setState(() { ipDomainError = null; From c13ba9e725be52c83576ccf8aa597b6dfab83638 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Mar 2023 21:24:14 +0100 Subject: [PATCH 011/676] Fixed no custom rules message --- lib/screens/filters/custom_rules_list.dart | 8 ++++---- lib/screens/filters/filters_list.dart | 21 ++++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 3b90728..807dad6 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -194,15 +194,15 @@ class _CustomRulesListState extends State { ), ) ), - if (widget.data.isEmpty) SizedBox( + if (widget.data.isEmpty) Container( width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox( - width: MediaQuery.of(context).size.width-100, + Flexible( child: Text( - AppLocalizations.of(context)!.noBlackLists, + AppLocalizations.of(context)!.noCustomFilters, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: TextStyle( diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index 5cbb4ac..f73b130 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -120,19 +120,22 @@ class _FiltersListState extends State { onTap: () => openDetailsModal(widget.data[index]), ), ), - if (widget.data.isEmpty) if (widget.data.isEmpty) SizedBox( + if (widget.data.isEmpty) if (widget.data.isEmpty) Container( width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - widget.type == 'blacklist' - ? AppLocalizations.of(context)!.noBlackLists - : AppLocalizations.of(context)!.noWhiteLists, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, + Flexible( + child: Text( + widget.type == 'blacklist' + ? AppLocalizations.of(context)!.noBlackLists + : AppLocalizations.of(context)!.noWhiteLists, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ), const SizedBox(height: 30), From 759c9779757acae77b85c45664b86849cada9b67 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Mar 2023 21:48:34 +0100 Subject: [PATCH 012/676] Fixed issues encryption screen --- .../{encode_base64.dart => base64.dart} | 4 +++ lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- .../settings/encryption/encryption.dart | 22 +++++++++----- .../settings/encryption/error_message.dart | 30 +++++++++++++++++++ lib/widgets/add_server_modal.dart | 2 +- 6 files changed, 54 insertions(+), 10 deletions(-) rename lib/functions/{encode_base64.dart => base64.dart} (80%) create mode 100644 lib/screens/settings/encryption/error_message.dart diff --git a/lib/functions/encode_base64.dart b/lib/functions/base64.dart similarity index 80% rename from lib/functions/encode_base64.dart rename to lib/functions/base64.dart index 3ed3d59..cb34296 100644 --- a/lib/functions/encode_base64.dart +++ b/lib/functions/base64.dart @@ -9,4 +9,8 @@ String encodeBase64UserPass(String user, String pass) { String encodeBase64(String value) { Codec stringToBase64 = utf8.fuse(base64); return stringToBase64.encode(value); +} + +String decodeBase64(String value) { + return utf8.decode(base64.decode(value)); } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index b4463a7..aebf7da 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -584,5 +584,6 @@ "clientsSelected": "clients selected", "invalidDomain": "Invalid domain", "loadingBlockedServicesList": "Loading blocked services list...", - "blockedServicesListNotLoaded": "The blocked services list could not be loaded" + "blockedServicesListNotLoaded": "The blocked services list could not be loaded", + "error": "Error" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 95b7323..5f94cb5 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -584,5 +584,6 @@ "clientsSelected": "clientes seleccionados", "invalidDomain": "Dominio no válido", "loadingBlockedServicesList": "Cargando lista de servicios bloqueados...", - "blockedServicesListNotLoaded": "No se ha podido cargar la lista de servicios bloqueados" + "blockedServicesListNotLoaded": "No se ha podido cargar la lista de servicios bloqueados", + "error": "Error" } \ No newline at end of file diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 120dab3..e1f3686 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -11,9 +11,10 @@ import 'package:adguard_home_manager/screens/settings/encryption/status.dart'; import 'package:adguard_home_manager/screens/settings/encryption/custom_text_field.dart'; import 'package:adguard_home_manager/screens/settings/encryption/master_switch.dart'; import 'package:adguard_home_manager/screens/settings/encryption/encryption_functions.dart'; +import 'package:adguard_home_manager/screens/settings/encryption/error_message.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/functions/encode_base64.dart'; +import 'package:adguard_home_manager/functions/base64.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -112,7 +113,7 @@ class _EncryptionSettingsWidgetState extends State { dnsOverQuicPortController.text = result['data'].portDnsOverQuic != null ? result['data'].portDnsOverQuic.toString() : ''; if (result['data'].certificateChain != '') { certificateOption = 1; - certificateContentController.text = "-----BEGIN CERTIFICATE-----\n${result['data'].certificateChain}\n-----END CERTIFICATE-----"; + certificateContentController.text = decodeBase64(result['data'].certificateChain); } else { certificateOption = 0; @@ -244,8 +245,8 @@ class _EncryptionSettingsWidgetState extends State { "port_https": int.parse(httpsPortController.text), "port_dns_over_tls": int.parse(tlsPortController.text), "port_dns_over_quic": int.parse(dnsOverQuicPortController.text), - "certificate_chain": certificateContentController.text, - "private_key": pastePrivateKeyController.text, + "certificate_chain": encodeBase64(certificateContentController.text), + "private_key": encodeBase64(pastePrivateKeyController.text), "private_key_saved": usePreviouslySavedKey, "certificate_path": certificatePathController.text, "private_key_path": privateKeyPathController.text, @@ -270,6 +271,15 @@ class _EncryptionSettingsWidgetState extends State { label: AppLocalizations.of(context)!.encryptionConfigNotSaved, color: Colors.red ); + + if (result['log'].resBody != null) { + showDialog( + context: context, + builder: (context) => ErrorMessageEncryption( + errorMessage: result['log'].resBody + ) + ); + } } } @@ -644,9 +654,7 @@ class _EncryptionSettingsWidgetState extends State { tooltip: generateStatusString(context, localValidationValid, certKeyValidApi) ), IconButton( - onPressed: localValidationValid == true && certKeyValidApi == 1 - ? () => saveData() - : null, + onPressed: saveData, icon: const Icon(Icons.save), tooltip: AppLocalizations.of(context)!.save, ), diff --git a/lib/screens/settings/encryption/error_message.dart b/lib/screens/settings/encryption/error_message.dart new file mode 100644 index 0000000..be132d8 --- /dev/null +++ b/lib/screens/settings/encryption/error_message.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class ErrorMessageEncryption extends StatelessWidget { + final String errorMessage; + + const ErrorMessageEncryption({ + Key? key, + required this.errorMessage, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(AppLocalizations.of(context)!.error), + content: Text(errorMessage), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close) + ) + ], + ) + ], + ); + } +} \ No newline at end of file diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index e67cf16..758876b 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -6,7 +6,7 @@ import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/functions/encode_base64.dart'; +import 'package:adguard_home_manager/functions/base64.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; From a5f38915b4e1bd25acbfbe75d814298d8f4d518b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Mar 2023 22:03:08 +0100 Subject: [PATCH 013/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index d15fa9c..f5e0639 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.12.1+47 +version: 1.12.2+48 environment: sdk: '>=2.18.1 <3.0.0' From 1508c49536e10f7389c8e2d8f615562c7a3b987a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 6 Apr 2023 18:10:23 +0200 Subject: [PATCH 014/676] New tab list on clients --- lib/constants/enums.dart | 1 + lib/models/clients.dart | 3 +- lib/providers/servers_provider.dart | 5 +- lib/screens/clients/added_list.dart | 315 +++++++++--------- lib/screens/clients/clients.dart | 110 +++--- lib/screens/clients/clients_list.dart | 207 ++++++------ lib/screens/clients/fab.dart | 19 +- .../access_settings/access_settings.dart | 13 +- .../access_settings/clients_list.dart | 9 +- lib/widgets/tab_content_list.dart | 109 ++++++ 10 files changed, 440 insertions(+), 351 deletions(-) create mode 100644 lib/constants/enums.dart create mode 100644 lib/widgets/tab_content_list.dart diff --git a/lib/constants/enums.dart b/lib/constants/enums.dart new file mode 100644 index 0000000..58f5509 --- /dev/null +++ b/lib/constants/enums.dart @@ -0,0 +1 @@ +enum LoadStatus { loading, loaded, error } \ No newline at end of file diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 2be193c..9fc9b06 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -1,9 +1,10 @@ import 'dart:convert'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; class Clients { - int loadStatus; + LoadStatus loadStatus; ClientsData? data; Clients({ diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 5b8a1d1..ad6cde4 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; @@ -26,7 +27,7 @@ class ServersProvider with ChangeNotifier { List _protectionsManagementProcess = []; // protections that are currenty being enabled or disabled final Clients _clients = Clients( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error + loadStatus: LoadStatus.loading, data: null ); @@ -125,7 +126,7 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setClientsLoadStatus(int status, bool notify) { + void setClientsLoadStatus(LoadStatus status, bool notify) { _clients.loadStatus = status; if (notify == true) { notifyListeners(); diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 76d5a03..207ce9f 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -10,8 +10,10 @@ import 'package:adguard_home_manager/screens/clients/client_screen.dart'; import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/fab.dart'; import 'package:adguard_home_manager/screens/clients/options_modal.dart'; +import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/clients.dart'; @@ -20,7 +22,7 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; class AddedList extends StatefulWidget { final ScrollController scrollController; - final int loadStatus; + final LoadStatus loadStatus; final List data; final Future Function() fetchClients; @@ -169,180 +171,163 @@ class _AddedListState extends State { ); } - switch (widget.loadStatus) { - case 0: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingStatus, - textAlign: TextAlign.center, + return Stack( + children: [ + CustomTabContentList( + loadingGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + itemsCount: widget.data.length, + contentWidget: (index) => ListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + isThreeLine: true, + onLongPress: () => openOptionsModal(widget.data[index]), + onTap: () => openClientModal(widget.data[index]), + title: Padding( + padding: const EdgeInsets.only(bottom: 5), + child: Text( + widget.data[index].name, style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, + fontSize: 18, + fontWeight: FontWeight.normal, + color: Theme.of(context).colorScheme.onSurface ), - ) - ], - ), - ); - - case 1: - return Stack( - children: [ - if (widget.data.isNotEmpty) ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: widget.data.length, - itemBuilder: (context, index) => ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - isThreeLine: true, - onLongPress: () => openOptionsModal(widget.data[index]), - onTap: () => openClientModal(widget.data[index]), - title: Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Text( - widget.data[index].name, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface - ), + ), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.data[index].ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor ), ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, + const SizedBox(height: 7), + Row( children: [ - Text( - widget.data[index].ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor - ), + Icon( + Icons.filter_list_rounded, + size: 19, + color: widget.data[index].filteringEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, ), - const SizedBox(height: 7), - Row( - children: [ - Icon( - Icons.filter_list_rounded, - size: 19, - color: widget.data[index].filteringEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.vpn_lock_rounded, - size: 18, - color: widget.data[index].safebrowsingEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.block, - size: 18, - color: widget.data[index].parentalEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.search_rounded, - size: 19, - color: widget.data[index].safesearchEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ) - ], + const SizedBox(width: 10), + Icon( + Icons.vpn_lock_rounded, + size: 18, + color: widget.data[index].safebrowsingEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.block, + size: 18, + color: widget.data[index].parentalEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.search_rounded, + size: 19, + color: widget.data[index].safesearchEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, ) ], - ), - ) + ) + ], ), - if (widget.data.isEmpty) SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - AppLocalizations.of(context)!.noClientsList, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), + ), + noData: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + AppLocalizations.of(context)!.noClientsList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - const SizedBox(height: 30), - TextButton.icon( - onPressed: widget.fetchClients, - icon: const Icon(Icons.refresh_rounded), - label: Text(AppLocalizations.of(context)!.refresh), - ) - ], - ), - ), - AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: isVisible ? - appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, - right: 20, - child: const ClientsFab(tab: 1), - ) - ], - ); - - case 2: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.errorLoadServerStatus, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - + const SizedBox(height: 30), + TextButton.icon( + onPressed: widget.fetchClients, + icon: const Icon(Icons.refresh_rounded), + label: Text(AppLocalizations.of(context)!.refresh), + ) + ], + ), + ), + errorGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.errorLoadServerStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + loadStatus: widget.loadStatus, + onRefresh: widget.fetchClients + ), + ClientsFab( + isVisible: isVisible, + ) + ], + ); } } \ No newline at end of file diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index f64f3fd..549b242 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -9,6 +9,7 @@ import 'package:adguard_home_manager/screens/clients/added_list.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/server.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -33,7 +34,7 @@ class Clients extends StatelessWidget { class ClientsWidget extends StatefulWidget { final Server server; - final void Function(int, bool) setLoadingStatus; + final void Function(LoadStatus, bool) setLoadingStatus; final void Function(ClientsData) setClientsData; final void Function(int) setSelectedClientsTab; final void Function(AppLog) addLog; @@ -56,16 +57,16 @@ class _ClientsWidgetState extends State with TickerProviderStateM final ScrollController scrollController = ScrollController(); Future fetchClients() async { - widget.setLoadingStatus(0, false); + widget.setLoadingStatus(LoadStatus.loading, false); final result = await getClients(widget.server); if (mounted) { if (result['result'] == 'success') { widget.setClientsData(result['data']); - widget.setLoadingStatus(1, true); + widget.setLoadingStatus(LoadStatus.loaded, true); } else { widget.addLog(result['log']); - widget.setLoadingStatus(2, true); + widget.setLoadingStatus(LoadStatus.error, true); } } } @@ -98,43 +99,40 @@ class _ClientsWidgetState extends State with TickerProviderStateM return [ SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverSafeArea( - top: false, - sliver: SliverAppBar( - title: Text(AppLocalizations.of(context)!.clients), - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - actions: [ - if (serversProvider.clients.loadStatus == 1) ...[ - IconButton( - onPressed: () => { - Navigator.push(context, MaterialPageRoute( - builder: (context) => const SearchClients() - )) - }, - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.searchClients, - ), - const SizedBox(width: 10), - ] - ], - bottom: TabBar( - controller: tabController, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - icon: const Icon(Icons.devices), - text: AppLocalizations.of(context)!.activeClients, - ), - Tab( - icon: const Icon(Icons.add_rounded), - text: AppLocalizations.of(context)!.added, - ), - ] - ) - ), + sliver: SliverAppBar( + title: Text(AppLocalizations.of(context)!.clients), + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + actions: [ + if (serversProvider.clients.loadStatus == LoadStatus.loaded) ...[ + IconButton( + onPressed: () => { + Navigator.push(context, MaterialPageRoute( + builder: (context) => const SearchClients() + )) + }, + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.searchClients, + ), + const SizedBox(width: 10), + ] + ], + bottom: TabBar( + controller: tabController, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + icon: const Icon(Icons.devices), + text: AppLocalizations.of(context)!.activeClients, + ), + Tab( + icon: const Icon(Icons.add_rounded), + text: AppLocalizations.of(context)!.added, + ), + ] + ) ), ) ]; @@ -151,25 +149,19 @@ class _ClientsWidgetState extends State with TickerProviderStateM child: TabBarView( controller: tabController, children: [ - RefreshIndicator( - onRefresh: fetchClients, - child: ClientsList( - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == 1 - ? serversProvider.clients.data!.autoClientsData : [], - fetchClients: fetchClients, - ), + ClientsList( + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == LoadStatus.loaded + ? serversProvider.clients.data!.autoClientsData : [], + fetchClients: fetchClients, ), - RefreshIndicator( - onRefresh: fetchClients, - child: AddedList( - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == 1 - ? serversProvider.clients.data!.clients : [], - fetchClients: fetchClients, - ) + AddedList( + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == LoadStatus.loaded + ? serversProvider.clients.data!.clients : [], + fetchClients: fetchClients, ), ] ) diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index f56c731..af1ee86 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -1,17 +1,19 @@ -import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; class ClientsList extends StatelessWidget { final ScrollController scrollController; - final int loadStatus; + final LoadStatus loadStatus; final List data; final Future Function() fetchClients; @@ -28,115 +30,102 @@ class ClientsList extends StatelessWidget { final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); - switch (loadStatus) { - case 0: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingStatus, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case 1: - if (data.isNotEmpty) { - return ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: data.length, - itemBuilder: (context, index) => CustomListTile( - title: data[index].name != '' - ? data[index].name! - : data[index].ip, - subtitle: data[index].name != '' - ? data[index].ip - : null, - trailing: Text( - data[index].source, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), + return CustomTabContentList( + loadingGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - onTap: () { - logsProvider.setSearchText(null); - logsProvider.setSelectedClients([data[index].ip]); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: null, - clients: [data[index].ip] - ) - ); - appConfigProvider.setSelectedScreen(2); - }, + ) + ], + ), + ), + itemsCount: data.length, + contentWidget: (index) => CustomListTile( + title: data[index].name != '' + ? data[index].name! + : data[index].ip, + subtitle: data[index].name != '' + ? data[index].ip + : null, + trailing: Text( + data[index].source, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + onTap: () { + logsProvider.setSearchText(null); + logsProvider.setSelectedClients([data[index].ip]); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: null, + clients: [data[index].ip] ) ); - } - else { - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - AppLocalizations.of(context)!.noClientsList, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 30), - TextButton.icon( - onPressed: fetchClients, - icon: const Icon(Icons.refresh_rounded), - label: Text(AppLocalizations.of(context)!.refresh) - ) - ], - ), - ); - } - - case 2: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, + appConfigProvider.setSelectedScreen(2); + }, + ), + noData: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + AppLocalizations.of(context)!.noClientsList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.errorLoadServerStatus, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } + ), + const SizedBox(height: 30), + TextButton.icon( + onPressed: fetchClients, + icon: const Icon(Icons.refresh_rounded), + label: Text(AppLocalizations.of(context)!.refresh) + ) + ], + ), + ), + errorGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.errorLoadServerStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + loadStatus: loadStatus, + onRefresh: fetchClients + ); } } \ No newline at end of file diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 74477af..59d9d43 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -14,11 +14,11 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class ClientsFab extends StatelessWidget { - final int tab; + final bool isVisible; const ClientsFab({ Key? key, - required this.tab, + required this.isVisible }) : super(key: key); @override @@ -67,9 +67,18 @@ class ClientsFab extends StatelessWidget { )); } - return FloatingActionButton( - onPressed: () => openAddClient(), - child: const Icon(Icons.add), + return AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: isVisible ? + appConfigProvider.showingSnackbar + ? 70 : 20 + : -70, + right: 20, + child: FloatingActionButton( + onPressed: openAddClient, + child: const Icon(Icons.add), + ) ); } } \ No newline at end of file diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index 08f96a2..a452857 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -42,16 +43,16 @@ class _AccessSettingsWidgetState extends State with Ticker late TabController tabController; Future fetchClients() async { - widget.serversProvider.setClientsLoadStatus(0, false); + widget.serversProvider.setClientsLoadStatus(LoadStatus.loading, false); final result = await getClients(widget.serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { widget.serversProvider.setClientsData(result['data']); - widget.serversProvider.setClientsLoadStatus(1, true); + widget.serversProvider.setClientsLoadStatus(LoadStatus.loaded, true); } else { widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setClientsLoadStatus(2, true); + widget.serversProvider.setClientsLoadStatus(LoadStatus.error, true); } } } @@ -120,7 +121,7 @@ class _AccessSettingsWidgetState extends State with Ticker type: 'allowed', scrollController: scrollController, loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == 1 + data: serversProvider.clients.loadStatus == LoadStatus.loaded ? serversProvider.clients.data!.clientsAllowedBlocked!.allowedClients : [], fetchClients: fetchClients ), @@ -128,7 +129,7 @@ class _AccessSettingsWidgetState extends State with Ticker type: 'disallowed', scrollController: scrollController, loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == 1 + data: serversProvider.clients.loadStatus == LoadStatus.loaded ? serversProvider.clients.data!.clientsAllowedBlocked!.disallowedClients : [], fetchClients: fetchClients ), @@ -136,7 +137,7 @@ class _AccessSettingsWidgetState extends State with Ticker type: 'domains', scrollController: scrollController, loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == 1 + data: serversProvider.clients.loadStatus == LoadStatus.loaded ? serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts : [], fetchClients: fetchClients ), diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 2d6f787..10ae3df 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -2,6 +2,7 @@ import 'dart:io'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; @@ -20,7 +21,7 @@ import 'package:adguard_home_manager/classes/process_modal.dart'; class ClientsList extends StatefulWidget { final String type; final ScrollController scrollController; - final int loadStatus; + final LoadStatus loadStatus; final List data; final Future Function() fetchClients; @@ -209,7 +210,7 @@ class _ClientsListState extends State { } switch (widget.loadStatus) { - case 0: + case LoadStatus.loading: return SizedBox( width: double.maxFinite, height: MediaQuery.of(context).size.height-171, @@ -231,7 +232,7 @@ class _ClientsListState extends State { ), ); - case 1: + case LoadStatus.loaded: return Stack( children: [ RefreshIndicator( @@ -340,7 +341,7 @@ class _ClientsListState extends State { ] ); - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, height: MediaQuery.of(context).size.height-101, diff --git a/lib/widgets/tab_content_list.dart b/lib/widgets/tab_content_list.dart new file mode 100644 index 0000000..866d000 --- /dev/null +++ b/lib/widgets/tab_content_list.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; + +class CustomTabContentList extends StatelessWidget { + final Widget Function() loadingGenerator; + final int itemsCount; + final Widget Function(int index) contentWidget; + final Widget noData; + final Widget Function() errorGenerator; + final LoadStatus loadStatus; + final Future Function() onRefresh; + + const CustomTabContentList({ + Key? key, + required this.loadingGenerator, + required this.itemsCount, + required this.contentWidget, + required this.noData, + required this.errorGenerator, + required this.loadStatus, + required this.onRefresh, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + switch (loadStatus) { + case LoadStatus.loading: + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (BuildContext context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverFillRemaining( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: loadingGenerator() + ), + ) + ], + ), + ) + ); + + + case LoadStatus.loaded: + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (BuildContext context) { + return RefreshIndicator( + onRefresh: onRefresh, + edgeOffset: 95, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (itemsCount > 0) SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) => contentWidget(index), + childCount: itemsCount + ), + ), + if (itemsCount == 0) SliverFillRemaining( + child: noData, + ) + ], + ), + ); + }, + ), + ); + + case LoadStatus.error: + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (BuildContext context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverFillRemaining( + child: Padding( + padding: const EdgeInsets.only( + top: 95, + left: 16, + right: 16 + ), + child: errorGenerator() + ), + ) + ], + ), + ) + ); + + default: + return const SizedBox(); + } + } +} \ No newline at end of file From b599debb3c72c600c93803c49af1e03991603cf1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 6 Apr 2023 18:27:57 +0200 Subject: [PATCH 015/676] New tab list filters --- lib/models/filtering.dart | 4 +- lib/providers/servers_provider.dart | 4 +- lib/screens/filters/custom_rules_list.dart | 200 ++++++-------- lib/screens/filters/fab.dart | 6 +- lib/screens/filters/filters.dart | 273 +++++++++---------- lib/screens/filters/filters_list.dart | 204 +++++++------- lib/screens/filters/list_details_screen.dart | 13 +- lib/widgets/tab_content_list.dart | 74 +++-- 8 files changed, 376 insertions(+), 402 deletions(-) diff --git a/lib/models/filtering.dart b/lib/models/filtering.dart index 20ca948..74a4710 100644 --- a/lib/models/filtering.dart +++ b/lib/models/filtering.dart @@ -1,11 +1,13 @@ import 'dart:convert'; +import 'package:adguard_home_manager/constants/enums.dart'; + FilteringData filteringFromJson(String str) => FilteringData.fromJson(json.decode(str)); String filteringToJson(FilteringData data) => json.encode(data.toJson()); class Filtering { - int loadStatus = 0; + LoadStatus loadStatus = LoadStatus.loading; FilteringData? data; Filtering({ diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index ad6cde4..c35f3fa 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -32,7 +32,7 @@ class ServersProvider with ChangeNotifier { ); final Filtering _filtering = Filtering( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error + loadStatus: LoadStatus.loading, data: null ); @@ -153,7 +153,7 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setFilteringLoadStatus(int loadStatus, bool notify) { + void setFilteringLoadStatus(LoadStatus loadStatus, bool notify) { _filtering.loadStatus = loadStatus; if (notify == true) { notifyListeners(); diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 807dad6..41b1d0f 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -7,8 +7,10 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/fab.dart'; import 'package:adguard_home_manager/screens/filters/remove_custom_rule_modal.dart'; +import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -16,10 +18,10 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; class CustomRulesList extends StatefulWidget { - final int loadStatus; + final LoadStatus loadStatus; final ScrollController scrollController; final List data; - final void Function() fetchData; + final Future Function() fetchData; const CustomRulesList({ Key? key, @@ -149,120 +151,98 @@ class _CustomRulesListState extends State { } } - switch (widget.loadStatus) { - case 0: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingFilters, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case 1: - return Stack( + return CustomTabContentList( + loadingGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (widget.data.isNotEmpty) ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: widget.data.length, - itemBuilder: (context, index) => ListTile( - title: Text( - widget.data[index], - style: TextStyle( - color: checkIfComment(widget.data[index]) == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.6) - : Theme.of(context).colorScheme.onSurface, - fontWeight: FontWeight.normal, - ), - ), - subtitle: generateSubtitle(widget.data[index]), - trailing: IconButton( - onPressed: () => openRemoveCustomRuleModal(widget.data[index]), - icon: const Icon(Icons.delete) - ), - ) - ), - if (widget.data.isEmpty) Container( - width: double.maxFinite, - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Flexible( - child: Text( - AppLocalizations.of(context)!.noCustomFilters, - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - const SizedBox(height: 30), - TextButton.icon( - onPressed: widget.fetchData, - icon: const Icon(Icons.refresh_rounded), - label: Text(AppLocalizations.of(context)!.refresh), - ) - ], + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingFilters, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ), - AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: isVisible ? - appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, - right: 20, - child: const FiltersFab( - type: 'custom_rule', - ) ) ], - ); - - case 2: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.filtersNotLoaded, + ), + ), + itemsCount: widget.data.length, + contentWidget: (index) => ListTile( + title: Text( + widget.data[index], + style: TextStyle( + color: checkIfComment(widget.data[index]) == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.6) + : Theme.of(context).colorScheme.onSurface, + fontWeight: FontWeight.normal, + ), + ), + subtitle: generateSubtitle(widget.data[index]), + trailing: IconButton( + onPressed: () => openRemoveCustomRuleModal(widget.data[index]), + icon: const Icon(Icons.delete) + ), + ), + noData: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Text( + AppLocalizations.of(context)!.noCustomFilters, + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, style: TextStyle( - fontSize: 22, + fontSize: 24, color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - + ), + ), + const SizedBox(height: 30), + TextButton.icon( + onPressed: widget.fetchData, + icon: const Icon(Icons.refresh_rounded), + label: Text(AppLocalizations.of(context)!.refresh), + ) + ], + ), + ), + errorGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.filtersNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + loadStatus: widget.loadStatus, + onRefresh: widget.fetchData, + fab: const FiltersFab( + type: 'custom_rule', + ), + fabVisible: isVisible, + ); } } \ No newline at end of file diff --git a/lib/screens/filters/fab.dart b/lib/screens/filters/fab.dart index 911f54b..2a5d036 100644 --- a/lib/screens/filters/fab.dart +++ b/lib/screens/filters/fab.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:bottom_sheet/bottom_sheet.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_custom_rule.dart'; @@ -12,6 +11,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -91,11 +91,11 @@ class FiltersFab extends StatelessWidget { if (result2['result'] == 'success') { serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(1, true); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); } else { appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(2, true); + serversProvider.setFilteringLoadStatus(LoadStatus.error, true); } processModal.close(); diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 5ec487e..e69728c 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -13,6 +13,7 @@ import 'package:adguard_home_manager/screens/filters/update_interval_lists_modal import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -51,18 +52,18 @@ class _FiltersWidgetState extends State with TickerProviderStateM final ScrollController scrollController = ScrollController(); Future fetchFilters() async { - widget.serversProvider.setFilteringLoadStatus(0, false); + widget.serversProvider.setFilteringLoadStatus(LoadStatus.loading, false); final result = await getFiltering(server: widget.serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { widget.serversProvider.setFilteringData(result['data']); - widget.serversProvider.setFilteringLoadStatus(1, false); + widget.serversProvider.setFilteringLoadStatus(LoadStatus.loaded, false); } else { widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setFilteringLoadStatus(2, false); + widget.serversProvider.setFilteringLoadStatus(LoadStatus.error, false); } } } @@ -228,123 +229,120 @@ class _FiltersWidgetState extends State with TickerProviderStateM return [ SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverSafeArea( - top: false, - sliver: SliverAppBar( - title: Text(AppLocalizations.of(context)!.filters), - pinned: true, - floating: true, - forceElevated: innerBoxIsScrolled, - centerTitle: false, - actions: serversProvider.filtering.loadStatus == 1 ? [ - IconButton( - onPressed: enableDisableFiltering, - tooltip: serversProvider.filtering.data!.enabled == true - ? AppLocalizations.of(context)!.disableFiltering - : AppLocalizations.of(context)!.enableFiltering, - icon: Stack( - children: [ - const Icon(Icons.power_settings_new_rounded), - Positioned( - bottom: 0, - right: 0, - child: Stack( - children: [ - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - color: Colors.white - ), - child: Icon( - serversProvider.filtering.data!.enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - size: 12, - color: serversProvider.filtering.data!.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ), + sliver: SliverAppBar( + title: Text(AppLocalizations.of(context)!.filters), + pinned: true, + floating: true, + forceElevated: innerBoxIsScrolled, + centerTitle: false, + actions: serversProvider.filtering.loadStatus == LoadStatus.loaded ? [ + IconButton( + onPressed: enableDisableFiltering, + tooltip: serversProvider.filtering.data!.enabled == true + ? AppLocalizations.of(context)!.disableFiltering + : AppLocalizations.of(context)!.enableFiltering, + icon: Stack( + children: [ + const Icon(Icons.power_settings_new_rounded), + Positioned( + bottom: 0, + right: 0, + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Colors.white ), - ], - ), - ) - ], - ) - ), - IconButton( - onPressed: () { - showModalBottomSheet( - context: context, - builder: (context) => UpdateIntervalListsModal( - interval: serversProvider.filtering.data!.interval, - onChange: setUpdateFrequency + child: Icon( + serversProvider.filtering.data!.enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + size: 12, + color: serversProvider.filtering.data!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + ), + ], ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ); - }, - icon: const Icon(Icons.update_rounded) - ), - PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - onTap: fetchUpdateLists, - child: Row( - children: [ - const Icon(Icons.sync_rounded), - const SizedBox(width: 10), - Text(AppLocalizations.of(context)!.updateLists) - ], - ) + ) + ], + ) + ), + IconButton( + onPressed: () { + showModalBottomSheet( + context: context, + builder: (context) => UpdateIntervalListsModal( + interval: serversProvider.filtering.data!.interval, + onChange: setUpdateFrequency ), - PopupMenuItem( - onTap: openBlockedServicesModal, - child: Row( - children: [ - const Icon(Icons.block), - const SizedBox(width: 10), - Text(AppLocalizations.of(context)!.blockedServices) - ], - ) - ), - PopupMenuItem( - onTap: showCheckHostModal, - child: Row( - children: [ - const Icon(Icons.shield_rounded), - const SizedBox(width: 10), - Text(AppLocalizations.of(context)!.checkHostFiltered) - ], - ) - ), - ] - ), - const SizedBox(width: 5), - ] : [], - bottom: TabBar( - controller: tabController, - isScrollable: false, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - icon: const Icon(Icons.verified_user_rounded), - text: AppLocalizations.of(context)!.whitelists, + backgroundColor: Colors.transparent, + isScrollControlled: true + ); + }, + icon: const Icon(Icons.update_rounded) + ), + PopupMenuButton( + itemBuilder: (context) => [ + PopupMenuItem( + onTap: fetchUpdateLists, + child: Row( + children: [ + const Icon(Icons.sync_rounded), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.updateLists) + ], + ) ), - Tab( - icon: const Icon(Icons.gpp_bad_rounded), - text: AppLocalizations.of(context)!.blacklist, + PopupMenuItem( + onTap: openBlockedServicesModal, + child: Row( + children: [ + const Icon(Icons.block), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.blockedServices) + ], + ) ), - Tab( - icon: const Icon(Icons.shield_rounded), - text: AppLocalizations.of(context)!.customRules, + PopupMenuItem( + onTap: showCheckHostModal, + child: Row( + children: [ + const Icon(Icons.shield_rounded), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.checkHostFiltered) + ], + ) ), ] - ) - ), + ), + const SizedBox(width: 5), + ] : [], + bottom: TabBar( + controller: tabController, + isScrollable: false, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + icon: const Icon(Icons.verified_user_rounded), + text: AppLocalizations.of(context)!.whitelists, + ), + Tab( + icon: const Icon(Icons.gpp_bad_rounded), + text: AppLocalizations.of(context)!.blacklist, + ), + Tab( + icon: const Icon(Icons.shield_rounded), + text: AppLocalizations.of(context)!.customRules, + ), + ] + ) ), ) ]; @@ -352,37 +350,28 @@ class _FiltersWidgetState extends State with TickerProviderStateM body: TabBarView( controller: tabController, children: [ - RefreshIndicator( - onRefresh: fetchFilters, - child: FiltersList( - loadStatus: serversProvider.filtering.loadStatus, - scrollController: scrollController, - type: 'whitelist', - data: serversProvider.filtering.loadStatus == 1 - ? serversProvider.filtering.data!.whitelistFilters : [], - fetchData: fetchFilters, - ) + FiltersList( + loadStatus: serversProvider.filtering.loadStatus, + scrollController: scrollController, + type: 'whitelist', + data: serversProvider.filtering.loadStatus == LoadStatus.loaded + ? serversProvider.filtering.data!.whitelistFilters : [], + fetchData: fetchFilters, ), - RefreshIndicator( - onRefresh: fetchFilters, - child: FiltersList( - loadStatus: serversProvider.filtering.loadStatus, - scrollController: scrollController, - type: 'blacklist', - data: serversProvider.filtering.loadStatus == 1 - ? serversProvider.filtering.data!.filters : [], - fetchData: fetchFilters, - ) + FiltersList( + loadStatus: serversProvider.filtering.loadStatus, + scrollController: scrollController, + type: 'blacklist', + data: serversProvider.filtering.loadStatus == LoadStatus.loaded + ? serversProvider.filtering.data!.filters : [], + fetchData: fetchFilters, ), - RefreshIndicator( - onRefresh: fetchFilters, - child: CustomRulesList( - loadStatus: serversProvider.filtering.loadStatus, - scrollController: scrollController, - data: serversProvider.filtering.loadStatus == 1 - ? serversProvider.filtering.data!.userRules : [], - fetchData: fetchFilters, - ) + CustomRulesList( + loadStatus: serversProvider.filtering.loadStatus, + scrollController: scrollController, + data: serversProvider.filtering.loadStatus == LoadStatus.loaded + ? serversProvider.filtering.data!.userRules : [], + fetchData: fetchFilters, ), ] ) diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index f73b130..effe42d 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -10,16 +10,18 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/fab.dart'; import 'package:adguard_home_manager/screens/filters/list_details_screen.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/widgets/tab_content_list.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/models/filtering.dart'; class FiltersList extends StatefulWidget { - final int loadStatus; + final LoadStatus loadStatus; final ScrollController scrollController; final List data; - final void Function() fetchData; + final Future Function() fetchData; final String type; const FiltersList({ @@ -74,122 +76,100 @@ class _FiltersListState extends State { ); } - switch (widget.loadStatus) { - case 0: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingFilters, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case 1: - return Stack( + return CustomTabContentList( + loadingGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (widget.data.isNotEmpty) ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: widget.data.length, - itemBuilder: (context, index) => CustomListTile( - title: widget.data[index].name, - subtitle: "${intFormat(widget.data[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", - trailing: Icon( - widget.data[index].enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - color: widget.data[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ), - onTap: () => openDetailsModal(widget.data[index]), + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingFilters, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ), - if (widget.data.isEmpty) if (widget.data.isEmpty) Container( - width: double.maxFinite, - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Flexible( - child: Text( - widget.type == 'blacklist' - ? AppLocalizations.of(context)!.noBlackLists - : AppLocalizations.of(context)!.noWhiteLists, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - const SizedBox(height: 30), - TextButton.icon( - onPressed: widget.fetchData, - icon: const Icon(Icons.refresh_rounded), - label: Text(AppLocalizations.of(context)!.refresh), - ) - ], - ), - ), - AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: isVisible ? - appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, - right: 20, - child: FiltersFab( - type: widget.type - ) ) ], - ); - - case 2: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.filtersNotLoaded, + ), + ), + itemsCount: widget.data.length, + contentWidget: (index) => CustomListTile( + title: widget.data[index].name, + subtitle: "${intFormat(widget.data[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + widget.data[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: widget.data[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => openDetailsModal(widget.data[index]), + ), + noData: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Text( + widget.type == 'blacklist' + ? AppLocalizations.of(context)!.noBlackLists + : AppLocalizations.of(context)!.noWhiteLists, + textAlign: TextAlign.center, style: TextStyle( - fontSize: 22, + fontSize: 24, color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - + ), + ), + const SizedBox(height: 30), + TextButton.icon( + onPressed: widget.fetchData, + icon: const Icon(Icons.refresh_rounded), + label: Text(AppLocalizations.of(context)!.refresh), + ) + ], + ), + ), + errorGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.filtersNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + loadStatus: widget.loadStatus, + onRefresh: widget.fetchData, + fab: FiltersFab( + type: widget.type, + ), + fabVisible: isVisible, + ); } } \ No newline at end of file diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index ebf6aca..7d8cf53 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -13,6 +13,7 @@ import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -92,11 +93,11 @@ class _ListDetailsScreenState extends State { if (result2['result'] == 'success') { serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(1, true); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); } else { appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(2, true); + serversProvider.setFilteringLoadStatus(LoadStatus.error, true); } setState(() => enabled = newStatus); @@ -139,11 +140,11 @@ class _ListDetailsScreenState extends State { if (result2['result'] == 'success') { serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(1, true); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); } else { appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(2, true); + serversProvider.setFilteringLoadStatus(LoadStatus.error, true); } processModal.close(); @@ -184,11 +185,11 @@ class _ListDetailsScreenState extends State { if (result2['result'] == 'success') { serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(1, true); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); } else { appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(2, true); + serversProvider.setFilteringLoadStatus(LoadStatus.loading, true); } processModal.close(); diff --git a/lib/widgets/tab_content_list.dart b/lib/widgets/tab_content_list.dart index 866d000..633b5e2 100644 --- a/lib/widgets/tab_content_list.dart +++ b/lib/widgets/tab_content_list.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; class CustomTabContentList extends StatelessWidget { @@ -10,6 +12,8 @@ class CustomTabContentList extends StatelessWidget { final Widget Function() errorGenerator; final LoadStatus loadStatus; final Future Function() onRefresh; + final Widget? fab; + final bool? fabVisible; const CustomTabContentList({ Key? key, @@ -20,10 +24,14 @@ class CustomTabContentList extends StatelessWidget { required this.errorGenerator, required this.loadStatus, required this.onRefresh, + this.fab, + this.fabVisible }) : super(key: key); @override Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + switch (loadStatus) { case LoadStatus.loading: return SafeArea( @@ -48,33 +56,47 @@ class CustomTabContentList extends StatelessWidget { case LoadStatus.loaded: - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (BuildContext context) { - return RefreshIndicator( - onRefresh: onRefresh, - edgeOffset: 95, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + return Stack( + children: [ + SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (BuildContext context) { + return RefreshIndicator( + onRefresh: onRefresh, + edgeOffset: 95, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (itemsCount > 0) SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) => contentWidget(index), + childCount: itemsCount + ), + ), + if (itemsCount == 0) SliverFillRemaining( + child: noData, + ) + ], ), - if (itemsCount > 0) SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) => contentWidget(index), - childCount: itemsCount - ), - ), - if (itemsCount == 0) SliverFillRemaining( - child: noData, - ) - ], - ), - ); - }, - ), + ); + }, + ), + ), + if (fab != null) AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: fabVisible != null && fabVisible == true ? + appConfigProvider.showingSnackbar + ? 70 : 20 + : -70, + right: 20, + child: fab! + ), + ], ); case LoadStatus.error: From 6ebde52a7fb62e2b6ef2988fdec85c80a3203076 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 6 Apr 2023 18:29:46 +0200 Subject: [PATCH 016/676] Improvements added clients list --- lib/screens/clients/added_list.dart | 293 ++++++++++++++-------------- lib/screens/clients/fab.dart | 22 +-- 2 files changed, 148 insertions(+), 167 deletions(-) diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 207ce9f..b18dcf4 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -171,163 +171,158 @@ class _AddedListState extends State { ); } - return Stack( - children: [ - CustomTabContentList( - loadingGenerator: () => SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingStatus, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], + return CustomTabContentList( + loadingGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + itemsCount: widget.data.length, + contentWidget: (index) => ListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + isThreeLine: true, + onLongPress: () => openOptionsModal(widget.data[index]), + onTap: () => openClientModal(widget.data[index]), + title: Padding( + padding: const EdgeInsets.only(bottom: 5), + child: Text( + widget.data[index].name, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.normal, + color: Theme.of(context).colorScheme.onSurface ), - ), - itemsCount: widget.data.length, - contentWidget: (index) => ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - isThreeLine: true, - onLongPress: () => openOptionsModal(widget.data[index]), - onTap: () => openClientModal(widget.data[index]), - title: Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Text( - widget.data[index].name, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface - ), + ), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.data[index].ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor ), ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, + const SizedBox(height: 7), + Row( children: [ - Text( - widget.data[index].ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor - ), + Icon( + Icons.filter_list_rounded, + size: 19, + color: widget.data[index].filteringEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, ), - const SizedBox(height: 7), - Row( - children: [ - Icon( - Icons.filter_list_rounded, - size: 19, - color: widget.data[index].filteringEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.vpn_lock_rounded, - size: 18, - color: widget.data[index].safebrowsingEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.block, - size: 18, - color: widget.data[index].parentalEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.search_rounded, - size: 19, - color: widget.data[index].safesearchEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ) - ], + const SizedBox(width: 10), + Icon( + Icons.vpn_lock_rounded, + size: 18, + color: widget.data[index].safebrowsingEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.block, + size: 18, + color: widget.data[index].parentalEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.search_rounded, + size: 19, + color: widget.data[index].safesearchEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, ) ], - ), - ), - noData: SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - AppLocalizations.of(context)!.noClientsList, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 30), - TextButton.icon( - onPressed: widget.fetchClients, - icon: const Icon(Icons.refresh_rounded), - label: Text(AppLocalizations.of(context)!.refresh), - ) - ], - ), - ), - errorGenerator: () => SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.errorLoadServerStatus, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ), - loadStatus: widget.loadStatus, - onRefresh: widget.fetchClients + ) + ], ), - ClientsFab( - isVisible: isVisible, - ) - ], + ), + noData: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + AppLocalizations.of(context)!.noClientsList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 30), + TextButton.icon( + onPressed: widget.fetchClients, + icon: const Icon(Icons.refresh_rounded), + label: Text(AppLocalizations.of(context)!.refresh), + ) + ], + ), + ), + errorGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.errorLoadServerStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + loadStatus: widget.loadStatus, + onRefresh: widget.fetchClients, + fab: const ClientsFab(), + fabVisible: isVisible, ); } } \ No newline at end of file diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 59d9d43..d916486 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -14,12 +14,7 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class ClientsFab extends StatelessWidget { - final bool isVisible; - - const ClientsFab({ - Key? key, - required this.isVisible - }) : super(key: key); + const ClientsFab({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -67,18 +62,9 @@ class ClientsFab extends StatelessWidget { )); } - return AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: isVisible ? - appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, - right: 20, - child: FloatingActionButton( - onPressed: openAddClient, - child: const Icon(Icons.add), - ) + return FloatingActionButton( + onPressed: openAddClient, + child: const Icon(Icons.add), ); } } \ No newline at end of file From 4e65f80baf646d1826d63013816fbaa521d35657 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 6 Apr 2023 18:50:06 +0200 Subject: [PATCH 017/676] New tab list access clients --- .../access_settings/access_settings.dart | 4 +- .../access_settings/clients_list.dart | 325 +++++++++--------- lib/widgets/tab_content_list.dart | 4 +- 3 files changed, 170 insertions(+), 163 deletions(-) diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index a452857..5a59e2e 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -1,10 +1,10 @@ -import 'package:adguard_home_manager/constants/enums.dart'; 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/settings/access_settings/clients_list.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -72,7 +72,7 @@ class _AccessSettingsWidgetState extends State with Ticker @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); - +print(serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts.length); return Scaffold( body: DefaultTabController( length: 3, diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 10ae3df..6e561db 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -1,8 +1,5 @@ // ignore_for_file: use_build_context_synchronously -import 'dart:io'; - -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; @@ -10,11 +7,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/access_settings/add_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; +import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -209,167 +208,173 @@ class _ClientsListState extends State { } } - switch (widget.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingClients, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - return Stack( + return CustomTabContentList( + loadingGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-171, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - RefreshIndicator( - onRefresh: widget.fetchClients, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Padding( - padding: const EdgeInsets.all(10), - child: Card( - child: Padding( - padding: const EdgeInsets.all(20), - child: Row( - children: [ - Icon( - Icons.info_rounded, - color: Theme.of(context).listTileTheme.iconColor, - ), - const SizedBox(width: 20), - Flexible( - child: Text( - description(), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ) - ], - ), - ), - ), - ), - if (widget.data.isNotEmpty) Expanded( - child: ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: widget.data.length, - itemBuilder: (context, index) => ListTile( - title: Text( - widget.data[index], - style: TextStyle( - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface - ), - ), - trailing: IconButton( - onPressed: () => { - showDialog( - context: context, - builder: (context) => RemoveClientModal( - onConfirm: () => confirmRemoveItem(widget.data[index], widget.type), - ) - ) - }, - icon: const Icon(Icons.delete_rounded) - ), - ) - ), - ), - if (widget.data.isEmpty) Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - noItems(), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 30), - TextButton.icon( - onPressed: widget.fetchClients, - icon: const Icon(Icons.refresh_rounded), - label: Text(AppLocalizations.of(context)!.refresh), - ) - ], - ), - ), - ], - ), - ), - AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: isVisible ? - appConfigProvider.showingSnackbar - ? 70 : (Platform.isIOS ? 40 : 20) - : -70, - right: 20, - child: FloatingActionButton( - onPressed: () { - showModalBottomSheet( - context: context, - builder: (context) => AddClientModal( - type: widget.type, - onConfirm: confirmAddItem - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ); - }, - child: const Icon(Icons.add), + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingClients, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), ) - ] - ); - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - height: MediaQuery.of(context).size.height-101, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.clientsNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, + ], + ), + ), + itemsCount: widget.data.isNotEmpty + ? widget.data.length+1 + : 0, + contentWidget: (index) { + if (index == 0) { + return Padding( + padding: const EdgeInsets.all(10), + child: Card( + child: Padding( + padding: const EdgeInsets.all(20), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).listTileTheme.iconColor, + ), + const SizedBox(width: 20), + Flexible( + child: Text( + description(), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ) + ], ), - ) - ], + ), + ), + ); + } + else { + return ListTile( + title: Text( + widget.data[index-1], + style: TextStyle( + fontWeight: FontWeight.normal, + color: Theme.of(context).colorScheme.onSurface + ), + ), + trailing: IconButton( + onPressed: () => { + showDialog( + context: context, + builder: (context) => RemoveClientModal( + onConfirm: () => confirmRemoveItem(widget.data[index-1], widget.type), + ) + ) + }, + icon: const Icon(Icons.delete_rounded) + ), + ); + } + }, + noData: Column( + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: Card( + child: Padding( + padding: const EdgeInsets.all(20), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).listTileTheme.iconColor, + ), + const SizedBox(width: 20), + Flexible( + child: Text( + description(), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ) + ], + ), + ), + ), ), - ); - - default: - return const SizedBox(); - } - + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + noItems(), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 30), + TextButton.icon( + onPressed: widget.fetchClients, + icon: const Icon(Icons.refresh_rounded), + label: Text(AppLocalizations.of(context)!.refresh), + ) + ], + ), + ), + ], + ), + errorGenerator: () => SizedBox( + width: double.maxFinite, + height: MediaQuery.of(context).size.height-101, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.clientsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + loadStatus: widget.loadStatus, + onRefresh: widget.fetchClients, + refreshIndicatorOffset: 0, + fab: FloatingActionButton( + onPressed: () { + showModalBottomSheet( + context: context, + builder: (context) => AddClientModal( + type: widget.type, + onConfirm: confirmAddItem + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ); + }, + child: const Icon(Icons.add), + ), + fabVisible: isVisible, + ); } } \ No newline at end of file diff --git a/lib/widgets/tab_content_list.dart b/lib/widgets/tab_content_list.dart index 633b5e2..5171081 100644 --- a/lib/widgets/tab_content_list.dart +++ b/lib/widgets/tab_content_list.dart @@ -12,6 +12,7 @@ class CustomTabContentList extends StatelessWidget { final Widget Function() errorGenerator; final LoadStatus loadStatus; final Future Function() onRefresh; + final double? refreshIndicatorOffset; final Widget? fab; final bool? fabVisible; @@ -24,6 +25,7 @@ class CustomTabContentList extends StatelessWidget { required this.errorGenerator, required this.loadStatus, required this.onRefresh, + this.refreshIndicatorOffset, this.fab, this.fabVisible }) : super(key: key); @@ -65,7 +67,7 @@ class CustomTabContentList extends StatelessWidget { builder: (BuildContext context) { return RefreshIndicator( onRefresh: onRefresh, - edgeOffset: 95, + edgeOffset: refreshIndicatorOffset ?? 95, child: CustomScrollView( slivers: [ SliverOverlapInjector( From e02b598be99a0041f08880f986489ff694d40b9b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 6 Apr 2023 22:56:32 +0200 Subject: [PATCH 018/676] Added screen to update server --- lib/constants/urls.dart | 1 + lib/functions/compare_versions.dart | 47 ++++ lib/functions/open_url.dart | 17 ++ lib/l10n/app_en.arb | 13 +- lib/l10n/app_es.arb | 13 +- lib/models/update_available.dart | 55 +++++ lib/providers/servers_provider.dart | 62 ++++- lib/screens/settings/settings.dart | 51 ++-- lib/screens/settings/update.dart | 350 ++++++++++++++++++++++++++++ lib/services/http_requests.dart | 168 +++++++++++++ lib/widgets/bottom_nav_bar.dart | 32 ++- pubspec.lock | 40 +++- pubspec.yaml | 4 + 13 files changed, 819 insertions(+), 34 deletions(-) create mode 100644 lib/functions/compare_versions.dart create mode 100644 lib/functions/open_url.dart create mode 100644 lib/models/update_available.dart create mode 100644 lib/screens/settings/update.dart diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart index 5b60855..e37435d 100644 --- a/lib/constants/urls.dart +++ b/lib/constants/urls.dart @@ -3,4 +3,5 @@ class Urls { static const String gitHub = "https://github.com/JGeek00/adguard-home-manager"; static const String customRuleDocs = "https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters"; static const String checkLatestReleaseUrl = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases/latest"; + static const String adGuardHomeLatestRelease = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/latest"; } \ No newline at end of file diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart new file mode 100644 index 0000000..58c9542 --- /dev/null +++ b/lib/functions/compare_versions.dart @@ -0,0 +1,47 @@ +bool compareVersions({ + required String currentVersion, + required String newVersion +}) { + final currentSplit = currentVersion.split('.').map((e) => int.parse(e)).toList(); + final newSplit = newVersion.split('.').map((e) => int.parse(e)).toList(); + + if (newSplit[0] > currentSplit[0]) { + return true; + } + else if (newSplit[1] > currentSplit[1]) { + return true; + } + else if (newSplit[2] > currentSplit[2]) { + return true; + } + else { + return false; + } +} + +bool compareBetaVersions({ + required String currentVersion, + required String newVersion +}) { + final currentSplit = currentVersion.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + final newSplit = newVersion.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + + final currentBeta = int.parse(currentVersion.split('-')[1].replaceAll('b.', '')); + final newBeta = int.parse(newVersion.split('-')[1].replaceAll('b.', '')); + + if (newSplit[0] > currentSplit[0]) { + return true; + } + else if (newSplit[1] > currentSplit[1]) { + return true; + } + else if (newSplit[2] > currentSplit[2]) { + return true; + } + else if (newBeta > currentBeta) { + return true; + } + else { + return false; + } +} \ No newline at end of file diff --git a/lib/functions/open_url.dart b/lib/functions/open_url.dart new file mode 100644 index 0000000..b4d52d5 --- /dev/null +++ b/lib/functions/open_url.dart @@ -0,0 +1,17 @@ +import 'package:flutter_web_browser/flutter_web_browser.dart'; + +void openUrl(String url) { + FlutterWebBrowser.openWebPage( + url: url, + customTabsOptions: const CustomTabsOptions( + instantAppsEnabled: true, + showTitle: true, + urlBarHidingEnabled: false, + ), + safariVCOptions: const SafariViewControllerOptions( + barCollapsingEnabled: true, + dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, + modalPresentationCapturesStatusBarAppearance: true, + ) + ); +} \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index aebf7da..088a127 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -585,5 +585,16 @@ "invalidDomain": "Invalid domain", "loadingBlockedServicesList": "Loading blocked services list...", "blockedServicesListNotLoaded": "The blocked services list could not be loaded", - "error": "Error" + "error": "Error", + "updates": "Updates", + "updatesDescription": "Update the AdGuard Home server", + "updateNow": "Update now", + "currentVersion": "Current version", + "requestStartUpdateFailed": "Request to start update failed", + "requestStartUpdateSuccessful": "Request to start update successfull", + "serverUpdated": "Server is updated", + "unknownStatus": "Unknown status", + "checkingUpdates": "Checking updates...", + "checkUpdates": "Check updates", + "requestingUpdate": "Requesting update..." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 5f94cb5..026aade 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -585,5 +585,16 @@ "invalidDomain": "Dominio no válido", "loadingBlockedServicesList": "Cargando lista de servicios bloqueados...", "blockedServicesListNotLoaded": "No se ha podido cargar la lista de servicios bloqueados", - "error": "Error" + "error": "Error", + "updates": "Actualizaciones", + "updatesDescription": "Actualiza el servidor AdGuard Home", + "updateNow": "Actualizar ahora", + "currentVersion": "Versión actual", + "requestStartUpdateFailed": "Petición para iniciar la actualización fallida", + "requestStartUpdateSuccessful": "Petición para iniciar la actualización satisfactoria", + "serverUpdated": "Servidor actualizado", + "unknownStatus": "Estado desconocido", + "checkingUpdates": "Comprobando actualizaciones...", + "checkUpdates": "Comprobar actualizaciones", + "requestingUpdate": "Solicitando actualización..." } \ No newline at end of file diff --git a/lib/models/update_available.dart b/lib/models/update_available.dart new file mode 100644 index 0000000..2b2aca6 --- /dev/null +++ b/lib/models/update_available.dart @@ -0,0 +1,55 @@ +import 'package:adguard_home_manager/constants/enums.dart'; + +class UpdateAvailable { + LoadStatus loadStatus = LoadStatus.loading; + UpdateAvailableData? data; + + UpdateAvailable({ + required this.loadStatus, + required this.data + }); +} + +class UpdateAvailableData { + String currentVersion; + final String newVersion; + final String announcement; + final String announcementUrl; + final bool canAutoupdate; + final bool disabled; + String? changelog; + bool? updateAvailable; + + UpdateAvailableData({ + required this.currentVersion, + required this.newVersion, + required this.announcement, + required this.announcementUrl, + required this.canAutoupdate, + required this.disabled, + this.changelog, + this.updateAvailable + }); + + factory UpdateAvailableData.fromJson(Map json) => UpdateAvailableData( + currentVersion: json["current_version"], + newVersion: json["new_version"], + announcement: json["announcement"], + announcementUrl: json["announcement_url"], + canAutoupdate: json["can_autoupdate"], + disabled: json["disabled"], + changelog: json["changelog"], + updateAvailable: json['update_available'] + ); + + Map toJson() => { + "current_version": currentVersion, + "new_version": newVersion, + "announcement": announcement, + "announcement_url": announcementUrl, + "can_autoupdate": canAutoupdate, + "disabled": disabled, + "changelog": changelog, + "update_available": updateAvailable + }; +} diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index c35f3fa..40210a5 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -1,5 +1,3 @@ -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; @@ -9,11 +7,15 @@ import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; +import 'package:adguard_home_manager/models/update_available.dart'; +import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; class ServersProvider with ChangeNotifier { Database? _dbInstance; @@ -56,6 +58,11 @@ class ServersProvider with ChangeNotifier { services: null ); + final UpdateAvailable _updateAvailable = UpdateAvailable( + loadStatus: LoadStatus.loading, + data: null, + ); + FilteringStatus? _filteringStatus; List get serversList { @@ -102,6 +109,10 @@ class ServersProvider with ChangeNotifier { return _blockedServicesList; } + UpdateAvailable get updateAvailable { + return _updateAvailable; + } + void setDbInstance(Database db) { _dbInstance = db; } @@ -223,6 +234,18 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } } + + void setUpdateAvailableLoadStatus(LoadStatus status, bool notify) { + _updateAvailable.loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } + + void setUpdateAvailableData(UpdateAvailableData data) { + _updateAvailable.data = data; + notifyListeners(); + } Future createServer(Server server) async { final saved = await saveServerIntoDb(server); @@ -460,6 +483,40 @@ class ServersProvider with ChangeNotifier { } } + void checkServerUpdatesAvailable(Server server) async { + setUpdateAvailableLoadStatus(LoadStatus.loading, true); + final result = await Future.wait([ + checkServerUpdates(server: server), + getUpdateChangelog(server: server) + ]); + if (result[0]['result'] == 'success') { + UpdateAvailableData data = result[0]['data']; + data.changelog = result[1]['body']; + data.updateAvailable = data.newVersion.contains('b') + ? compareBetaVersions( + currentVersion: data.currentVersion.replaceAll('v', ''), + newVersion: data.newVersion.replaceAll('v', ''), + ) + : compareVersions( + currentVersion: data.currentVersion.replaceAll('v', ''), + newVersion: data.newVersion.replaceAll('v', ''), + ); + setUpdateAvailableData(data); + setUpdateAvailableLoadStatus(LoadStatus.loaded, true); + } + else { + setUpdateAvailableLoadStatus(LoadStatus.error, true); + } + } + + void clearUpdateAvailable(Server server, String newCurrentVersion) { + if (_updateAvailable.data != null) { + _updateAvailable.data!.updateAvailable = null; + _updateAvailable.data!.currentVersion = newCurrentVersion; + notifyListeners(); + } + } + void saveFromDb(List>? data) async { if (data != null) { for (var server in data) { @@ -484,6 +541,7 @@ class ServersProvider with ChangeNotifier { if (serverStatus['result'] == 'success') { _serverStatus.data = serverStatus['data']; _serverStatus.loadStatus = 1; + checkServerUpdatesAvailable(serverObj); // Do not await } else { _serverStatus.loadStatus = 2; diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 21dff92..aacaa01 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_web_browser/flutter_web_browser.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/server_info/server_info.dart'; @@ -10,9 +9,9 @@ import 'package:adguard_home_manager/screens/settings/access_settings/access_set import 'package:adguard_home_manager/screens/settings/customization/customization.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; +import 'package:adguard_home_manager/screens/settings/update.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'; import 'package:adguard_home_manager/screens/settings/advanced_setings.dart'; import 'package:adguard_home_manager/screens/settings/general_settings.dart'; @@ -20,6 +19,7 @@ import 'package:adguard_home_manager/screens/settings/general_settings.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/constants/strings.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -38,23 +38,7 @@ class Settings extends StatelessWidget { MaterialPageRoute(builder: (context) => const Servers()) ); })); - } - - void openWeb(String url) { - FlutterWebBrowser.openWebPage( - url: url, - customTabsOptions: const CustomTabsOptions( - instantAppsEnabled: true, - showTitle: true, - urlBarHidingEnabled: false, - ), - safariVCOptions: const SafariViewControllerOptions( - barCollapsingEnabled: true, - dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, - modalPresentationCapturesStatusBarAppearance: true, - ) - ); - } + } return Scaffold( appBar: AppBar( @@ -125,6 +109,31 @@ class Settings extends StatelessWidget { ) }, ), + CustomListTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.updates, + subtitle: AppLocalizations.of(context)!.updatesDescription, + trailing: serversProvider.updateAvailable.data != null && + serversProvider.updateAvailable.data!.updateAvailable != null && + serversProvider.updateAvailable.data!.updateAvailable == true + ? Container( + width: 10, + height: 10, + margin: const EdgeInsets.only(right: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.red + ), + ) + : null, + onTap: () => { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const UpdateScreen() + ) + ) + }, + ), CustomListTile( icon: Icons.info_rounded, title: AppLocalizations.of(context)!.serverInformation, @@ -196,7 +205,7 @@ class Settings extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ IconButton( - onPressed: () => openWeb(Urls.playStore), + onPressed: () => openUrl(Urls.playStore), icon: SvgPicture.asset( 'assets/resources/google-play.svg', color: Theme.of(context).colorScheme.onSurfaceVariant, @@ -206,7 +215,7 @@ class Settings extends StatelessWidget { tooltip: AppLocalizations.of(context)!.visitGooglePlay, ), IconButton( - onPressed: () => openWeb(Urls.gitHub), + onPressed: () => openUrl(Urls.gitHub), icon: SvgPicture.asset( 'assets/resources/github.svg', color: Theme.of(context).colorScheme.onSurfaceVariant, diff --git a/lib/screens/settings/update.dart b/lib/screens/settings/update.dart new file mode 100644 index 0000000..beba263 --- /dev/null +++ b/lib/screens/settings/update.dart @@ -0,0 +1,350 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:html/parser.dart' as html; +import 'package:markdown/markdown.dart' as md; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/functions/compare_versions.dart'; + +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class UpdateScreen extends StatelessWidget { + const UpdateScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void update() async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.requestingUpdate); + + final result = await requestUpdateServer(server: serversProvider.selectedServer!); + + processModal.close(); + + if (result['result'] == 'success') { + serversProvider.clearUpdateAvailable(serversProvider.selectedServer!, serversProvider.updateAvailable.data!.newVersion); + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.requestStartUpdateSuccessful, + color: Colors.green, + labelColor: Colors.white, + ); + } + else { + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.requestStartUpdateFailed, + color: Colors.red, + labelColor: Colors.white, + ); + appConfigProvider.addLog(result['log']); + } + } + + Widget headerPortrait() { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + icon: Icon( + Icons.arrow_back, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + onPressed: () => Navigator.pop(context), + ), + IconButton( + icon: Icon( + Icons.refresh_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + tooltip: AppLocalizations.of(context)!.checkUpdates, + onPressed: () => serversProvider.checkServerUpdatesAvailable(serversProvider.selectedServer!) + ), + ], + ), + Padding( + padding: const EdgeInsets.only( + top: 8, bottom: 16, left: 16, right: 16 + ), + child: Column( + children: [ + serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? Column( + children: const [ + CircularProgressIndicator(), + SizedBox(height: 4) + ], + ) + : Icon( + serversProvider.updateAvailable.data!.updateAvailable != null + ? serversProvider.updateAvailable.data!.updateAvailable == true + ? Icons.system_update_rounded + : Icons.system_security_update_good_rounded + : Icons.system_security_update_warning_rounded, + size: 40, + color: Theme.of(context).colorScheme.primary, + ), + const SizedBox(height: 16), + Text( + serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? AppLocalizations.of(context)!.checkingUpdates + : serversProvider.updateAvailable.data!.updateAvailable != null + ? serversProvider.updateAvailable.data!.updateAvailable == true + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.serverUpdated + : AppLocalizations.of(context)!.unknownStatus, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w400 + ), + ), + const SizedBox(height: 40), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (serversProvider.updateAvailable.loadStatus == LoadStatus.loaded) Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true + ? AppLocalizations.of(context)!.newVersion + : AppLocalizations.of(context)!.currentVersion, + style: const TextStyle( + fontSize: 16, + ), + ), + const SizedBox(height: 4), + Text( + serversProvider.updateAvailable.data!.updateAvailable != null + ? serversProvider.updateAvailable.data!.updateAvailable == true + ? serversProvider.updateAvailable.data!.newVersion + : serversProvider.updateAvailable.data!.currentVersion + : "N/A", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ), + if (serversProvider.updateAvailable.loadStatus != LoadStatus.loaded) const SizedBox(), + FilledButton.icon( + icon: const Icon(Icons.download_rounded), + label: Text(AppLocalizations.of(context)!.updateNow), + onPressed: serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true + ? () => update() + : null + ) + ], + ), + ], + ), + ), + ], + ); + } + + Widget headerLandscape() { + return Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + icon: Icon( + Icons.arrow_back, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + onPressed: () => Navigator.pop(context), + ), + IconButton( + icon: Icon( + Icons.refresh_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + tooltip: AppLocalizations.of(context)!.checkUpdates, + onPressed: () => serversProvider.checkServerUpdatesAvailable(serversProvider.selectedServer!) + ), + ], + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only( + top: 8, bottom: 16, left: 16, right: 16 + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? Column( + children: const [ + CircularProgressIndicator(), + SizedBox(height: 4) + ], + ) + : Icon( + serversProvider.updateAvailable.data!.updateAvailable != null + ? serversProvider.updateAvailable.data!.updateAvailable == true + ? Icons.system_update_rounded + : Icons.system_security_update_good_rounded + : Icons.system_security_update_warning_rounded, + size: 40, + color: Theme.of(context).colorScheme.primary, + ), + const SizedBox(height: 16), + Text( + serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? AppLocalizations.of(context)!.checkingUpdates + : serversProvider.updateAvailable.data!.updateAvailable != null + ? serversProvider.updateAvailable.data!.updateAvailable == true + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.serverUpdated + : AppLocalizations.of(context)!.unknownStatus, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w400 + ), + ), + const SizedBox(height: 40), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (serversProvider.updateAvailable.loadStatus == LoadStatus.loaded) Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true + ? AppLocalizations.of(context)!.newVersion + : AppLocalizations.of(context)!.currentVersion, + style: const TextStyle( + fontSize: 16, + ), + ), + const SizedBox(height: 4), + Text( + serversProvider.updateAvailable.data!.updateAvailable != null + ? serversProvider.updateAvailable.data!.updateAvailable == true + ? serversProvider.updateAvailable.data!.newVersion + : serversProvider.updateAvailable.data!.currentVersion + : "N/A", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ), + if (serversProvider.updateAvailable.loadStatus != LoadStatus.loaded) const SizedBox(), + FilledButton.icon( + icon: const Icon(Icons.download_rounded), + label: Text(AppLocalizations.of(context)!.updateNow), + onPressed: serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true + ? () => update() + : null + ) + ], + ), + ), + ], + ), + ), + ), + ], + ); + } + + final changelog = serversProvider.updateAvailable.loadStatus == LoadStatus.loaded && serversProvider.updateAvailable.data!.changelog != null + ? ListView( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + "Changelog ${serversProvider.updateAvailable.data!.newVersion}", + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Html( + data: html.parse(md.markdownToHtml(serversProvider.updateAvailable.data!.changelog!)).outerHtml, + onLinkTap: (url, context, attributes, element) => url != null ? openUrl(url) : null, + ) + ) + ], + ) + : null; + + return Scaffold( + body: MediaQuery.of(context).size.width > 700 + ? Row( + children: [ + Expanded( + flex: 2, + child: Container( + color: Theme.of(context).colorScheme.surfaceVariant, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + height: MediaQuery.of(context).size.height, + padding: EdgeInsets.only( + top: MediaQuery.of(context).viewPadding.top + ), + child: headerLandscape(), + ) + ], + ), + ), + ), + Expanded( + flex: 3, + child: SafeArea( + child: SizedBox( + width: MediaQuery.of(context).size.width*0.6, + child: changelog ?? const SizedBox(), + ), + ), + ) + ], + ) + : Column( + children: [ + Container( + color: Theme.of(context).colorScheme.surfaceVariant, + child: SafeArea( + child: headerPortrait() + ) + ), + changelog != null + ? Expanded(child: changelog) + : const SizedBox(), + ] + ) + ); + } +} \ No newline at end of file diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 1647526..309ef75 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -20,6 +20,7 @@ import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/constants/urls.dart'; +import 'package:adguard_home_manager/models/update_available.dart'; Future> apiRequest({ @@ -1959,4 +1960,171 @@ Future checkAppUpdatesGitHub() async { ) }; } +} + +Future checkServerUpdates({ + required Server server, +}) async { + final result = await Future.wait([ + apiRequest( + urlPath: '/version.json', + method: 'get', + server: server, + type: 'check_server_updates', + body: json.encode({ + "recheck_now": true + }) + ), + apiRequest( + urlPath: '/status', + method: 'get', + server: server, + type: 'check_server_updates', + body: json.encode({ + "recheck_now": true + }) + ), + ]); + + if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { + final Map obj = { + ...jsonDecode(result[0]['body']), + 'current_version': jsonDecode(result[1]['body'])['version'] + }; + return { + 'result': 'success', + 'data': UpdateAvailableData.fromJson(obj) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_status', + dateTime: DateTime.now(), + message: 'no_response', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } +} + +Future getUpdateChangelog({ + required Server server, +}) async { + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.adGuardHomeLatestRelease)); + HttpClientResponse response = await request.close(); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + if (response.statusCode == 200) { + return { + 'result': 'success', + 'hasResponse': true, + 'error': false, + 'statusCode': response.statusCode, + 'body': jsonDecode(reply)['body'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: response.statusCode.toString(), + resBody: reply, + ) + }; + } + } on SocketException { + return { + 'result': 'no_connection', + 'message': 'SocketException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'SocketException' + ) + }; + } on TimeoutException { + return { + 'result': 'no_connection', + 'message': 'TimeoutException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'TimeoutException' + ) + }; + } on HandshakeException { + return { + 'result': 'ssl_error', + 'message': 'HandshakeException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'HandshakeException' + ) + }; + } catch (e) { + return { + 'result': 'error', + 'message': e.toString(), + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: e.toString() + ) + }; + } +} + +Future requestUpdateServer({ + required Server server, +}) async { + final result = await apiRequest( + urlPath: '/update', + method: 'post', + server: server, + type: 'update_server' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_server', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } } \ No newline at end of file diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index dabc657..5793442 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -50,11 +50,33 @@ class BottomNavBar extends StatelessWidget { return NavigationBar( selectedIndex: appConfigProvider.selectedScreen, destinations: screens.map((screen) => NavigationDestination( - icon: Icon( - screen.icon, - color: screens[appConfigProvider.selectedScreen] == screen - ? Theme.of(context).colorScheme.onSecondaryContainer - : Theme.of(context).colorScheme.onSurfaceVariant, + icon: Stack( + children: [ + Icon( + screen.icon, + color: screens[appConfigProvider.selectedScreen] == screen + ? Theme.of(context).colorScheme.onSecondaryContainer + : Theme.of(context).colorScheme.onSurfaceVariant, + ), + if ( + screen.name == 'settings' && + serversProvider.updateAvailable.data != null && + serversProvider.updateAvailable.data!.updateAvailable != null && + serversProvider.updateAvailable.data!.updateAvailable == true + ) Positioned( + bottom: 0, + right: -12, + child: Container( + width: 10, + height: 10, + margin: const EdgeInsets.only(right: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.red + ), + ), + ) + ], ), label: translatedName(screen.name) )).toList(), diff --git a/pubspec.lock b/pubspec.lock index fd32536..93d9e05 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -246,6 +246,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.1" + flutter_html: + dependency: "direct main" + description: + name: flutter_html + sha256: "342c7908f0a67bcec62b6e0f7cf23e23bafe7f64693665dd35be98d5e783bdfd" + url: "https://pub.dev" + source: hosted + version: "3.0.0-alpha.6" flutter_launcher_icons: dependency: "direct dev" description: @@ -267,6 +275,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_markdown: + dependency: "direct main" + description: + name: flutter_markdown + sha256: "7b25c10de1fea883f3c4f9b8389506b54053cd00807beab69fd65c8653a2711f" + url: "https://pub.dev" + source: hosted + version: "0.6.14" flutter_native_splash: dependency: "direct dev" description: @@ -302,13 +318,13 @@ packages: source: sdk version: "0.0.0" html: - dependency: transitive + dependency: "direct main" description: name: html - sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 + sha256: "79d498e6d6761925a34ee5ea8fa6dfef38607781d2fa91e37523474282af55cb" url: "https://pub.dev" source: hosted - version: "0.15.1" + version: "0.15.2" http: dependency: transitive description: @@ -365,6 +381,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + markdown: + dependency: "direct main" + description: + name: markdown + sha256: d95a9d12954aafc97f984ca29baaa7690ed4d9ec4140a23ad40580bcdb6c87f5 + url: "https://pub.dev" + source: hosted + version: "7.0.2" matcher: dependency: transitive description: @@ -397,6 +421,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + numerus: + dependency: transitive + description: + name: numerus + sha256: "436759d84f233b40107d0cc31cfa92d24e0960afeb2e506be70926d4cddffd9e" + url: "https://pub.dev" + source: hosted + version: "2.0.0" package_info_plus: dependency: "direct main" description: @@ -651,5 +683,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.18.1 <3.0.0" + dart: ">=2.19.0 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index f5e0639..f50f1ab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,6 +50,10 @@ dependencies: bottom_sheet: ^3.1.2 percent_indicator: ^4.2.2 store_checker: ^1.1.0 + flutter_markdown: ^0.6.14 + markdown: ^7.0.2 + html: ^0.15.2 + flutter_html: ^3.0.0-alpha.6 dev_dependencies: flutter_test: From 5edb30294471ddf0019d26a93d09c5ae22d574c0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 7 Apr 2023 16:48:58 +0200 Subject: [PATCH 019/676] Update improvements --- lib/constants/urls.dart | 2 +- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/providers/servers_provider.dart | 14 +++--- lib/screens/settings/settings.dart | 2 +- .../update_server/autoupdate_unavailable.dart | 46 +++++++++++++++++++ .../settings/{ => update_server}/update.dart | 19 ++++++-- lib/services/http_requests.dart | 3 +- lib/widgets/servers_list/servers_list.dart | 1 + 9 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 lib/screens/settings/update_server/autoupdate_unavailable.dart rename lib/screens/settings/{ => update_server}/update.dart (95%) diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart index e37435d..c8b1afa 100644 --- a/lib/constants/urls.dart +++ b/lib/constants/urls.dart @@ -3,5 +3,5 @@ class Urls { static const String gitHub = "https://github.com/JGeek00/adguard-home-manager"; static const String customRuleDocs = "https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters"; static const String checkLatestReleaseUrl = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases/latest"; - static const String adGuardHomeLatestRelease = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/latest"; + static const String adGuardHomeReleasesTags = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/tags"; } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 088a127..f99ceb6 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -596,5 +596,7 @@ "unknownStatus": "Unknown status", "checkingUpdates": "Checking updates...", "checkUpdates": "Check updates", - "requestingUpdate": "Requesting update..." + "requestingUpdate": "Requesting update...", + "autoupdateUnavailable": "Autoupdate unavailable", + "autoupdateUnavailableDescription": "The autoupdate service is not available for this server. It could be because the server is running on a Docker container. You have to update your server manually." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 026aade..9a48639 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -596,5 +596,7 @@ "unknownStatus": "Estado desconocido", "checkingUpdates": "Comprobando actualizaciones...", "checkUpdates": "Comprobar actualizaciones", - "requestingUpdate": "Solicitando actualización..." + "requestingUpdate": "Solicitando actualización...", + "autoupdateUnavailable": "Autoactualización no disponible", + "autoupdateUnavailableDescription": "El servicio de actualización automática del servidor no está disponible. Puede ser porque el servidor se esté ejecutando en un contenedor Docker. Tienes que actualizar tu servidor manualmente." } \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 40210a5..1695049 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -485,13 +485,13 @@ class ServersProvider with ChangeNotifier { void checkServerUpdatesAvailable(Server server) async { setUpdateAvailableLoadStatus(LoadStatus.loading, true); - final result = await Future.wait([ - checkServerUpdates(server: server), - getUpdateChangelog(server: server) - ]); - if (result[0]['result'] == 'success') { - UpdateAvailableData data = result[0]['data']; - data.changelog = result[1]['body']; + final result = await checkServerUpdates(server: server); + if (result['result'] == 'success') { + UpdateAvailableData data = result['data']; + final gitHubResult = await getUpdateChangelog(server: server, releaseTag: data.newVersion); + if (gitHubResult['result'] == 'success') { + data.changelog = gitHubResult['body']; + } data.updateAvailable = data.newVersion.contains('b') ? compareBetaVersions( currentVersion: data.currentVersion.replaceAll('v', ''), diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index aacaa01..5f805ec 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -9,7 +9,7 @@ import 'package:adguard_home_manager/screens/settings/access_settings/access_set import 'package:adguard_home_manager/screens/settings/customization/customization.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; -import 'package:adguard_home_manager/screens/settings/update.dart'; +import 'package:adguard_home_manager/screens/settings/update_server/update.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/servers/servers.dart'; diff --git a/lib/screens/settings/update_server/autoupdate_unavailable.dart b/lib/screens/settings/update_server/autoupdate_unavailable.dart new file mode 100644 index 0000000..9846448 --- /dev/null +++ b/lib/screens/settings/update_server/autoupdate_unavailable.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class AutoUpdateUnavailableModal extends StatelessWidget { + const AutoUpdateUnavailableModal({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Column( + children: [ + Icon( + Icons.error_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.autoupdateUnavailable, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: Text( + AppLocalizations.of(context)!.autoupdateUnavailableDescription, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close) + ), + ], + ) + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/update.dart b/lib/screens/settings/update_server/update.dart similarity index 95% rename from lib/screens/settings/update.dart rename to lib/screens/settings/update_server/update.dart index beba263..682eebc 100644 --- a/lib/screens/settings/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'package:adguard_home_manager/screens/settings/update_server/autoupdate_unavailable.dart'; +import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:html/parser.dart' as html; @@ -7,8 +9,6 @@ import 'package:markdown/markdown.dart' as md; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; - import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -24,6 +24,13 @@ class UpdateScreen extends StatelessWidget { Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + + void showAutoUpdateUnavailableModal() { + showModal( + context: context, + builder: (context) => const AutoUpdateUnavailableModal() + ); + } void update() async { ProcessModal processModal = ProcessModal(context: context); @@ -149,7 +156,9 @@ class UpdateScreen extends StatelessWidget { icon: const Icon(Icons.download_rounded), label: Text(AppLocalizations.of(context)!.updateNow), onPressed: serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true - ? () => update() + ? serversProvider.updateAvailable.data!.canAutoupdate == true + ? () => update() + : () => showAutoUpdateUnavailableModal() : null ) ], @@ -259,7 +268,9 @@ class UpdateScreen extends StatelessWidget { icon: const Icon(Icons.download_rounded), label: Text(AppLocalizations.of(context)!.updateNow), onPressed: serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true - ? () => update() + ? serversProvider.updateAvailable.data!.canAutoupdate == true + ? () => update() + : () => showAutoUpdateUnavailableModal() : null ) ], diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 309ef75..2962937 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -2026,10 +2026,11 @@ Future checkServerUpdates({ Future getUpdateChangelog({ required Server server, + required String releaseTag }) async { try { HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.adGuardHomeLatestRelease)); + HttpClientRequest request = await httpClient.getUrl(Uri.parse("${Urls.adGuardHomeReleasesTags}/$releaseTag")); HttpClientResponse response = await request.close(); String reply = await response.transform(utf8.decoder).join(); httpClient.close(); diff --git a/lib/widgets/servers_list/servers_list.dart b/lib/widgets/servers_list/servers_list.dart index ea0fc35..9dd080b 100644 --- a/lib/widgets/servers_list/servers_list.dart +++ b/lib/widgets/servers_list/servers_list.dart @@ -117,6 +117,7 @@ class _ServersListState extends State with SingleTickerProviderStat final serverStatus = await getServerStatus(server); if (serverStatus['result'] == 'success') { serversProvider.setServerStatusData(serverStatus['data']); + serversProvider.checkServerUpdatesAvailable(server); serversProvider.setServerStatusLoad(1); } else { From 4a9d2abf198bab980e2e4adcd9ac271a0cb5649c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 7 Apr 2023 16:55:19 +0200 Subject: [PATCH 020/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index f50f1ab..1b3e3cf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.12.2+48 +version: 1.13.0+49 environment: sdk: '>=2.18.1 <3.0.0' From 026cbd523e65d1ca7fa453d58c1f6ec6482d4313 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 7 Apr 2023 22:58:44 +0200 Subject: [PATCH 021/676] Fixed bugs update system --- lib/models/update_available.dart | 4 +-- lib/providers/servers_provider.dart | 36 +++++++++++-------- lib/screens/settings/settings.dart | 2 +- .../settings/update_server/update.dart | 12 ++++--- lib/services/http_requests.dart | 2 +- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/lib/models/update_available.dart b/lib/models/update_available.dart index 2b2aca6..136a6b9 100644 --- a/lib/models/update_available.dart +++ b/lib/models/update_available.dart @@ -12,7 +12,7 @@ class UpdateAvailable { class UpdateAvailableData { String currentVersion; - final String newVersion; + String? newVersion; final String announcement; final String announcementUrl; final bool canAutoupdate; @@ -22,7 +22,7 @@ class UpdateAvailableData { UpdateAvailableData({ required this.currentVersion, - required this.newVersion, + this.newVersion, required this.announcement, required this.announcementUrl, required this.canAutoupdate, diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 1695049..b02a154 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -487,22 +487,28 @@ class ServersProvider with ChangeNotifier { setUpdateAvailableLoadStatus(LoadStatus.loading, true); final result = await checkServerUpdates(server: server); if (result['result'] == 'success') { - UpdateAvailableData data = result['data']; - final gitHubResult = await getUpdateChangelog(server: server, releaseTag: data.newVersion); - if (gitHubResult['result'] == 'success') { - data.changelog = gitHubResult['body']; + try { + UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); + final gitHubResult = await getUpdateChangelog(server: server, releaseTag: data.newVersion ?? data.currentVersion); + if (gitHubResult['result'] == 'success') { + data.changelog = gitHubResult['body']; + } + data.updateAvailable = data.newVersion != null + ? data.newVersion!.contains('b') + ? compareBetaVersions( + currentVersion: data.currentVersion.replaceAll('v', ''), + newVersion: data.newVersion!.replaceAll('v', ''), + ) + : compareVersions( + currentVersion: data.currentVersion.replaceAll('v', ''), + newVersion: data.newVersion!.replaceAll('v', ''), + ) + : false; + setUpdateAvailableData(data); + setUpdateAvailableLoadStatus(LoadStatus.loaded, true); + } catch (_) { + // AUTO UPDATE NOT AVAILABLE // } - data.updateAvailable = data.newVersion.contains('b') - ? compareBetaVersions( - currentVersion: data.currentVersion.replaceAll('v', ''), - newVersion: data.newVersion.replaceAll('v', ''), - ) - : compareVersions( - currentVersion: data.currentVersion.replaceAll('v', ''), - newVersion: data.newVersion.replaceAll('v', ''), - ); - setUpdateAvailableData(data); - setUpdateAvailableLoadStatus(LoadStatus.loaded, true); } else { setUpdateAvailableLoadStatus(LoadStatus.error, true); diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 5f805ec..ea39f97 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -109,7 +109,7 @@ class Settings extends StatelessWidget { ) }, ), - CustomListTile( + if (serversProvider.updateAvailable.data != null) CustomListTile( icon: Icons.system_update_rounded, title: AppLocalizations.of(context)!.updates, subtitle: AppLocalizations.of(context)!.updatesDescription, diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index 682eebc..5fa898e 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -41,7 +41,7 @@ class UpdateScreen extends StatelessWidget { processModal.close(); if (result['result'] == 'success') { - serversProvider.clearUpdateAvailable(serversProvider.selectedServer!, serversProvider.updateAvailable.data!.newVersion); + serversProvider.clearUpdateAvailable(serversProvider.selectedServer!, serversProvider.updateAvailable.data!.newVersion!); showSnacbkar( context: context, appConfigProvider: appConfigProvider, @@ -140,7 +140,7 @@ class UpdateScreen extends StatelessWidget { Text( serversProvider.updateAvailable.data!.updateAvailable != null ? serversProvider.updateAvailable.data!.updateAvailable == true - ? serversProvider.updateAvailable.data!.newVersion + ? serversProvider.updateAvailable.data!.newVersion ?? 'N/A' : serversProvider.updateAvailable.data!.currentVersion : "N/A", style: TextStyle( @@ -156,7 +156,7 @@ class UpdateScreen extends StatelessWidget { icon: const Icon(Icons.download_rounded), label: Text(AppLocalizations.of(context)!.updateNow), onPressed: serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true - ? serversProvider.updateAvailable.data!.canAutoupdate == true + ? serversProvider.updateAvailable.data!.canAutoupdate != null && serversProvider.updateAvailable.data!.canAutoupdate == true ? () => update() : () => showAutoUpdateUnavailableModal() : null @@ -252,7 +252,7 @@ class UpdateScreen extends StatelessWidget { Text( serversProvider.updateAvailable.data!.updateAvailable != null ? serversProvider.updateAvailable.data!.updateAvailable == true - ? serversProvider.updateAvailable.data!.newVersion + ? serversProvider.updateAvailable.data!.newVersion ?? 'N/A' : serversProvider.updateAvailable.data!.currentVersion : "N/A", style: TextStyle( @@ -290,7 +290,9 @@ class UpdateScreen extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( - "Changelog ${serversProvider.updateAvailable.data!.newVersion}", + "Changelog ${serversProvider.updateAvailable.data!.updateAvailable == true + ? serversProvider.updateAvailable.data!.newVersion + : serversProvider.updateAvailable.data!.currentVersion}", style: TextStyle( fontSize: 20, fontWeight: FontWeight.w500, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 2962937..27780f6 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1994,7 +1994,7 @@ Future checkServerUpdates({ }; return { 'result': 'success', - 'data': UpdateAvailableData.fromJson(obj) + 'data': obj }; } else { From fd981053cf44da0fea3d9c74462d7b322e133c29 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 7 Apr 2023 23:10:11 +0200 Subject: [PATCH 022/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 1b3e3cf..54a98a5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.13.0+49 +version: 1.13.1+50 environment: sdk: '>=2.18.1 <3.0.0' From 38172a2c1c445a48a97f7eefc5bbaf39ded0fc71 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 12 Apr 2023 23:26:50 +0200 Subject: [PATCH 023/676] Added timer disable general --- lib/functions/time_server_disabled.dart | 11 + lib/l10n/app_en.arb | 9 +- lib/l10n/app_es.arb | 9 +- lib/models/server_status.dart | 9 + lib/providers/servers_provider.dart | 27 ++- lib/screens/filters/filters.dart | 5 +- lib/screens/home/management_modal.dart | 283 ++++++++++++++++++++---- lib/services/http_requests.dart | 16 +- 8 files changed, 317 insertions(+), 52 deletions(-) create mode 100644 lib/functions/time_server_disabled.dart diff --git a/lib/functions/time_server_disabled.dart b/lib/functions/time_server_disabled.dart new file mode 100644 index 0000000..07b6f2b --- /dev/null +++ b/lib/functions/time_server_disabled.dart @@ -0,0 +1,11 @@ +DateTime generateTimeDeadline(int time) { + DateTime date = DateTime.now(); + date = date.add(Duration(milliseconds: time)); + return date; +} + +String generateRemainingTimeString(Duration difference) { + final int seconds = difference.inSeconds+1; + final DateTime time = DateTime(0, 0, 0, 0, 0, seconds > 0 ? seconds : 0); + return "${time.hour > 0 ? "${time.hour}:" : ''}${time.minute.toString().padLeft(2, '0')}:${time.second.toString().padLeft(2, '0')}"; +} \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f99ceb6..d42e8e7 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -355,7 +355,7 @@ "gateway": "Gateway", "gatewayNotValid": "Gateway not valid", "leaseTime": "Lease time", - "seconds": "seconds", + "seconds": "{time} seconds", "leaseTimeNotValid": "Lease time not valid", "restoreConfiguration": "Reset configuration", "restoreConfigurationMessage": "Are you sure you want to continue? This will reset all the configuration. This action cannot be undone.", @@ -598,5 +598,10 @@ "checkUpdates": "Check updates", "requestingUpdate": "Requesting update...", "autoupdateUnavailable": "Autoupdate unavailable", - "autoupdateUnavailableDescription": "The autoupdate service is not available for this server. It could be because the server is running on a Docker container. You have to update your server manually." + "autoupdateUnavailableDescription": "The autoupdate service is not available for this server. It could be because the server is running on a Docker container. You have to update your server manually.", + "minute": "{time} minute", + "minutes": "{time} minutes", + "hour": "{time} hour", + "hours": "{time} hours", + "remainingTime": "Remaining time" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 9a48639..6835437 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -355,7 +355,7 @@ "gateway": "Puerta de enlace", "gatewayNotValid": "Puerta de enlace no válida", "leaseTime": "Tiempo de asignación", - "seconds": "segundos", + "seconds": "{time} segundos", "leaseTimeNotValid": "Tiempo de asignación no válido", "restoreConfiguration": "Restaurar configuración", "restoreConfigurationMessage": "¿Estás seguro de que deseas continuar? Se reseteará toda la configuración. Esta acción no se puede deshacer.", @@ -598,5 +598,10 @@ "checkUpdates": "Comprobar actualizaciones", "requestingUpdate": "Solicitando actualización...", "autoupdateUnavailable": "Autoactualización no disponible", - "autoupdateUnavailableDescription": "El servicio de actualización automática del servidor no está disponible. Puede ser porque el servidor se esté ejecutando en un contenedor Docker. Tienes que actualizar tu servidor manualmente." + "autoupdateUnavailableDescription": "El servicio de actualización automática del servidor no está disponible. Puede ser porque el servidor se esté ejecutando en un contenedor Docker. Tienes que actualizar tu servidor manualmente.", + "minute": "{time} minuto", + "minutes": "{time} minutos", + "hour": "{time} hora", + "hours": "{time} horas", + "remainingTime": "Tiempo restante" } \ No newline at end of file diff --git a/lib/models/server_status.dart b/lib/models/server_status.dart index fec00b3..8d76613 100644 --- a/lib/models/server_status.dart +++ b/lib/models/server_status.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/dns_statistics.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; @@ -15,6 +16,8 @@ class ServerStatusData { final DnsStatistics stats; final List clients; final FilteringStatus filteringStatus; + int timeGeneralDisabled; + DateTime? disabledUntil; bool generalEnabled; bool filteringEnabled; bool safeSearchEnabled; @@ -25,6 +28,8 @@ class ServerStatusData { required this.stats, required this.clients, required this.filteringStatus, + required this.timeGeneralDisabled, + this.disabledUntil, required this.generalEnabled, required this.filteringEnabled, required this.safeSearchEnabled, @@ -36,6 +41,10 @@ class ServerStatusData { stats: DnsStatistics.fromJson(json['stats']), clients: json["clients"] != null ? List.from(json["clients"].map((x) => Client.fromJson(x))) : [], generalEnabled: json['generalEnabled']['protection_enabled'], + timeGeneralDisabled: json['generalEnabled']['protection_disabled_duration'] ?? 0, + disabledUntil: json['generalEnabled']['protection_disabled_duration'] > 0 + ? generateTimeDeadline(json['generalEnabled']['protection_disabled_duration']) + : null , filteringStatus: FilteringStatus.fromJson(json['filtering']), filteringEnabled: json['filtering']['enabled'], safeSearchEnabled: json['safeSearchEnabled']['enabled'], diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index b02a154..471bcaf 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -13,6 +13,7 @@ import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -328,18 +329,35 @@ class ServersProvider with ChangeNotifier { } } - Future updateBlocking(Server server, String block, bool newStatus) async { + Future updateBlocking({ + required Server server, + required String block, + required bool newStatus, + int? time + }) async { switch (block) { case 'general': _protectionsManagementProcess.add('general'); notifyListeners(); - final result = await updateGeneralProtection(server, newStatus); + final result = await updateGeneralProtection( + server: server, + enable: newStatus, + time: time + ); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); if (result['result'] == 'success') { _serverStatus.data!.generalEnabled = newStatus; + if (time != null) { + _serverStatus.data!.timeGeneralDisabled = time; + _serverStatus.data!.disabledUntil = generateTimeDeadline(time); + } + else { + _serverStatus.data!.timeGeneralDisabled = 0; + _serverStatus.data!.disabledUntil = null; + } notifyListeners(); return null; } @@ -352,7 +370,10 @@ class ServersProvider with ChangeNotifier { _protectionsManagementProcess.add('filtering'); notifyListeners(); - final result = await updateFiltering(server, newStatus); + final result = await updateFiltering( + server: server, + enable: newStatus, + ); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'filtering').toList(); diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index e69728c..f985f48 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -156,7 +156,10 @@ class _FiltersWidgetState extends State with TickerProviderStateM : AppLocalizations.of(context)!.enableFiltering ); - final result = await updateFiltering(serversProvider.selectedServer!, !serversProvider.serverStatus.data!.filteringEnabled); + final result = await updateFiltering( + server: serversProvider.selectedServer!, + enable: !serversProvider.serverStatus.data!.filteringEnabled + ); processModal.close(); diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 15664c5..ad40b89 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -1,27 +1,133 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:async'; import 'dart:io'; +import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:expandable/expandable.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class ManagementModal extends StatelessWidget { +class ManagementModal extends StatefulWidget { const ManagementModal({Key? key}) : super(key: key); + @override + State createState() => _ManagementModalState(); +} + +class _ManagementModalState extends State with SingleTickerProviderStateMixin { + double height = 540; + bool showTimes = false; + late AnimationController animationController; + late Animation animation; + final ExpandableController expandableController = ExpandableController(); + + DateTime? currentDeadline; + Timer? countdown; + int start = 0; + + @override + void initState() { + expandableController.addListener(() async { + await Future.delayed(const Duration(milliseconds: 200)); + if (expandableController.value == false) { + animationController.animateTo(0); + } + else { + animationController.animateBack(1); + } + }); + + animationController = AnimationController( + duration: const Duration(milliseconds: 200), + vsync: this, + ) + ..addListener(() => setState(() => {})); + animation = Tween( + begin: 0.0, + end: 0.5, + ).animate(CurvedAnimation( + parent: animationController, + curve: Curves.easeInOut + )); + + super.initState(); + } + + @override + void dispose() { + if (countdown != null) countdown!.cancel(); + animationController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - void updateBlocking(bool value, String filter) async { + void startTimer(DateTime deadline) { + setState(() { + currentDeadline = deadline; + start = deadline.difference(DateTime.now()).inSeconds+1; + }); + + const oneSec = Duration(seconds: 1); + countdown = Timer.periodic( + oneSec, + (Timer timer) async { + if (start == 0) { + setState(() { + timer.cancel(); + }); + final result = await getServerStatus(serversProvider.selectedServer!); + if (result['result'] == 'success') { + serversProvider.setServerStatusData(result['data']); + } + } else { + setState(() { + start = start - 1; + }); + } + }, + ); + } + + if ( + serversProvider.serverStatus.data != null && + serversProvider.serverStatus.data!.disabledUntil != null && + serversProvider.serverStatus.data!.disabledUntil != currentDeadline + ) { + startTimer(serversProvider.serverStatus.data!.disabledUntil!); + } + + if ( + serversProvider.serverStatus.data != null && + serversProvider.serverStatus.data!.generalEnabled == true + ) { + setState(() { + start = 0; + currentDeadline = null; + if (countdown != null) countdown!.cancel(); + countdown = null; + }); + } + + void updateBlocking({ + required bool value, + required String filter, + int? time + }) async { final result = await serversProvider.updateBlocking( - serversProvider.selectedServer!, - filter, - value + server: serversProvider.selectedServer!, + block: filter, + newStatus: value, + time: time ); if (result != null) { if (result != false) { @@ -36,42 +142,139 @@ class ManagementModal extends StatelessWidget { } } + void disableWithCountdown(int time) { + updateBlocking(value: false, filter: 'general', time: time); + expandableController.toggle(); + } + Widget mainSwitch() { + Widget topRow() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + RotationTransition( + turns: animation, + child: Icon( + Icons.keyboard_arrow_down_rounded, + size: 26, + color: serversProvider.serverStatus.data!.generalEnabled == true + ? Theme.of(context).colorScheme.onSurfaceVariant + : Colors.grey, + ), + ), + const SizedBox(width: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.allProtections, + style: const TextStyle( + fontSize: 18, + ), + ), + if (serversProvider.serverStatus.data!.timeGeneralDisabled > 0) ...[ + const SizedBox(height: 2), + if (currentDeadline != null) Text( + "${AppLocalizations.of(context)!.remainingTime}: ${generateRemainingTimeString(currentDeadline!.difference(DateTime.now()))}" + ) + ] + ], + ), + ], + ), + Switch( + value: serversProvider.serverStatus.data!.generalEnabled, + onChanged: serversProvider.protectionsManagementProcess.contains('general') == false + ? (value) => updateBlocking(value: value, filter: 'general') + : null, + activeColor: Theme.of(context).colorScheme.primary, + ) + ] + ); + } + + Widget bottomRow() { + return Container( + height: 40, + margin: const EdgeInsets.only(top: 8), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + ActionChip( + label: Text(AppLocalizations.of(context)!.seconds(30)), + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + ? () => disableWithCountdown(29000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.minute(1)), + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + ? () => disableWithCountdown(59000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.minutes(10)), + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + ? () => disableWithCountdown(599000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.hour(1)), + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + ? () => disableWithCountdown(3599000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.hours(24)), + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + ? () => disableWithCountdown(86399000) + : null, + ), + ], + ), + ); + } + return 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: serversProvider.protectionsManagementProcess.contains('general') == false - ? () => updateBlocking(!serversProvider.serverStatus.data!.generalEnabled, 'general') - : null, + child: ExpandableNotifier( + controller: expandableController, + child: Material( + color: Colors.transparent, borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.allProtections, - style: const TextStyle( - fontSize: 18, - ), - ), - Switch( - value: serversProvider.serverStatus.data!.generalEnabled, - onChanged: serversProvider.protectionsManagementProcess.contains('general') == false - ? (value) => updateBlocking(value, 'general') - : null, - activeColor: Theme.of(context).colorScheme.primary, + child: InkWell( + onTap: serversProvider.serverStatus.data!.generalEnabled == true + ? () => expandableController.toggle() + : null, + borderRadius: BorderRadius.circular(28), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: Theme.of(context).primaryColor.withOpacity(0.1) + ), + child: Expandable( + collapsed: topRow(), + expanded: Column( + children: [ + topRow(), + bottomRow(), + const SizedBox(height: 8) + ], ) - ], + ), ), ), - ), + ) ), ); } @@ -125,7 +328,7 @@ class ManagementModal extends StatelessWidget { return Container( width: double.maxFinite, - height: Platform.isIOS ? 556 : 540, + height: Platform.isIOS ? height+16 : height, decoration: BoxDecoration( color: Theme.of(context).dialogBackgroundColor, borderRadius: const BorderRadius.only( @@ -137,7 +340,7 @@ class ManagementModal extends StatelessWidget { children: [ Expanded( child: ListView( - physics: (Platform.isIOS ? 556 : 540) < MediaQuery.of(context).size.height + physics: (Platform.isIOS ? height+16 : height) < MediaQuery.of(context).size.height ? const NeverScrollableScrollPhysics() : null, children: [ @@ -166,28 +369,28 @@ class ManagementModal extends StatelessWidget { AppLocalizations.of(context)!.ruleFiltering, Icons.filter_list_rounded, serversProvider.serverStatus.data!.filteringEnabled, - (value) => updateBlocking(value, 'filtering'), + (value) => updateBlocking(value: value, filter: 'filtering'), serversProvider.protectionsManagementProcess.contains('filtering') ), smallSwitch( AppLocalizations.of(context)!.safeBrowsing, Icons.vpn_lock_rounded, serversProvider.serverStatus.data!.safeBrowsingEnabled, - (value) => updateBlocking(value, 'safeBrowsing'), + (value) => updateBlocking(value: value, filter: 'safeBrowsing'), serversProvider.protectionsManagementProcess.contains('safeBrowsing') ), smallSwitch( AppLocalizations.of(context)!.parentalFiltering, Icons.block, serversProvider.serverStatus.data!.parentalControlEnabled, - (value) => updateBlocking(value, 'parentalControl'), + (value) => updateBlocking(value: value, filter: 'parentalControl'), serversProvider.protectionsManagementProcess.contains('parentalControl') ), smallSwitch( AppLocalizations.of(context)!.safeSearch, Icons.search_rounded, serversProvider.serverStatus.data!.safeSearchEnabled, - (value) => updateBlocking(value, 'safeSearch'), + (value) => updateBlocking(value: value, filter: 'safeSearch'), serversProvider.protectionsManagementProcess.contains('safeSearch') ), ], diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 27780f6..b1b3d25 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -318,7 +318,10 @@ Future getServerStatus(Server server) async { } } -Future updateFiltering(Server server, bool enable) async { +Future updateFiltering({ + required Server server, + required bool enable, +}) async { final result = await apiRequest( urlPath: '/filtering/config', method: 'post', @@ -462,13 +465,18 @@ Future updateParentalControl(Server server, bool enable) async { } } -Future updateGeneralProtection(Server server, bool enable) async { +Future updateGeneralProtection({ + required Server server, + required bool enable, + int? time +}) async { final result = await apiRequest( - urlPath: '/dns_config', + urlPath: '/protection', method: 'post', server: server, body: { - 'protection_enabled': enable + 'enabled': enable, + 'duration': time }, type: 'general_protection' ); From e77c31b367354dd25c7d8b3f107b22e66521325c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 13 Apr 2023 02:05:00 +0200 Subject: [PATCH 024/676] Fixes and improvements --- lib/screens/home/management_modal.dart | 163 +++++++++++++------------ 1 file changed, 83 insertions(+), 80 deletions(-) diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index ad40b89..aaef255 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -21,8 +21,6 @@ class ManagementModal extends StatefulWidget { } class _ManagementModalState extends State with SingleTickerProviderStateMixin { - double height = 540; - bool showTimes = false; late AnimationController animationController; late Animation animation; final ExpandableController expandableController = ExpandableController(); @@ -142,7 +140,7 @@ class _ManagementModalState extends State with SingleTickerProv } } - void disableWithCountdown(int time) { + void disableWithCountdown(int time) async { updateBlocking(value: false, filter: 'general', time: time); expandableController.toggle(); } @@ -263,6 +261,10 @@ class _ManagementModalState extends State with SingleTickerProv color: Theme.of(context).primaryColor.withOpacity(0.1) ), child: Expandable( + theme: const ExpandableThemeData( + animationDuration: Duration(milliseconds: 200), + fadeCurve: Curves.ease + ), collapsed: topRow(), expanded: Column( children: [ @@ -326,90 +328,91 @@ class _ManagementModalState extends State with SingleTickerProv ); } - return Container( - width: double.maxFinite, - height: Platform.isIOS ? height+16 : height, - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ) - ), - child: Column( - children: [ - Expanded( - child: ListView( - physics: (Platform.isIOS ? height+16 : height) < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, + return SafeArea( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ) + ), + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Text( - AppLocalizations.of(context)!.manageServer, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface, + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor ), ), - ), - mainSwitch(), - const SizedBox(height: 10), - smallSwitch( - AppLocalizations.of(context)!.ruleFiltering, - Icons.filter_list_rounded, - serversProvider.serverStatus.data!.filteringEnabled, - (value) => updateBlocking(value: value, filter: 'filtering'), - serversProvider.protectionsManagementProcess.contains('filtering') - ), - smallSwitch( - AppLocalizations.of(context)!.safeBrowsing, - Icons.vpn_lock_rounded, - serversProvider.serverStatus.data!.safeBrowsingEnabled, - (value) => updateBlocking(value: value, filter: 'safeBrowsing'), - serversProvider.protectionsManagementProcess.contains('safeBrowsing') - ), - smallSwitch( - AppLocalizations.of(context)!.parentalFiltering, - Icons.block, - serversProvider.serverStatus.data!.parentalControlEnabled, - (value) => updateBlocking(value: value, filter: 'parentalControl'), - serversProvider.protectionsManagementProcess.contains('parentalControl') - ), - smallSwitch( - AppLocalizations.of(context)!.safeSearch, - Icons.search_rounded, - serversProvider.serverStatus.data!.safeSearchEnabled, - (value) => updateBlocking(value: value, filter: 'safeSearch'), - serversProvider.protectionsManagementProcess.contains('safeSearch') + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Text( + AppLocalizations.of(context)!.manageServer, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ), + ], ), ], ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close), - ), - ], + mainSwitch(), + const SizedBox(height: 10), + smallSwitch( + AppLocalizations.of(context)!.ruleFiltering, + Icons.filter_list_rounded, + serversProvider.serverStatus.data!.filteringEnabled, + (value) => updateBlocking(value: value, filter: 'filtering'), + serversProvider.protectionsManagementProcess.contains('filtering') ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], + smallSwitch( + AppLocalizations.of(context)!.safeBrowsing, + Icons.vpn_lock_rounded, + serversProvider.serverStatus.data!.safeBrowsingEnabled, + (value) => updateBlocking(value: value, filter: 'safeBrowsing'), + serversProvider.protectionsManagementProcess.contains('safeBrowsing') + ), + smallSwitch( + AppLocalizations.of(context)!.parentalFiltering, + Icons.block, + serversProvider.serverStatus.data!.parentalControlEnabled, + (value) => updateBlocking(value: value, filter: 'parentalControl'), + serversProvider.protectionsManagementProcess.contains('parentalControl') + ), + smallSwitch( + AppLocalizations.of(context)!.safeSearch, + Icons.search_rounded, + serversProvider.serverStatus.data!.safeSearchEnabled, + (value) => updateBlocking(value: value, filter: 'safeSearch'), + serversProvider.protectionsManagementProcess.contains('safeSearch') + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close), + ), + ], + ), + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ), ), ); } From 20b2f896028086b6156911f78586a1dc6ab661ed Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 13 Apr 2023 02:13:30 +0200 Subject: [PATCH 025/676] Logs fix --- lib/models/logs.dart | 8 ++++---- lib/screens/logs/log_details_screen.dart | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/models/logs.dart b/lib/models/logs.dart index 7061318..f48a6b7 100644 --- a/lib/models/logs.dart +++ b/lib/models/logs.dart @@ -35,7 +35,7 @@ class LogsData { } class Log { - final bool answerDnssec; + final bool? answerDnssec; final bool cached; final String client; final ClientInfo? clientInfo; @@ -44,7 +44,7 @@ class Log { final Question question; final String reason; final List rules; - final String status; + final String? status; final DateTime time; final String upstream; final List answer; @@ -53,7 +53,7 @@ class Log { final List? originalAnswer; Log({ - required this.answerDnssec, + this.answerDnssec, required this.cached, required this.client, this.clientInfo, @@ -62,7 +62,7 @@ class Log { required this.question, required this.reason, required this.rules, - required this.status, + this.status, required this.time, required this.upstream, required this.answer, diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 5386d0c..a6960a1 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -188,7 +188,7 @@ class LogDetailsScreen extends StatelessWidget { title: AppLocalizations.of(context)!.elapsedTime, subtitle: "${double.parse(log.elapsedMs).toStringAsFixed(2)} ms" ), - LogListTile( + if (log.status != null) LogListTile( icon: Icons.system_update_alt_rounded, title: AppLocalizations.of(context)!.responseCode, subtitle: log.status From 9e400f7efa43b9bc7b02e76fd2c37462f5b25a56 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 13 Apr 2023 18:07:37 +0200 Subject: [PATCH 026/676] Added support for general protection legacy mode --- lib/functions/compare_versions.dart | 62 ++++++++++++ lib/models/server_status.dart | 15 +-- lib/providers/servers_provider.dart | 19 ++++ lib/screens/home/management_modal.dart | 132 ++++++++++++++++--------- lib/services/http_requests.dart | 35 ++++++- 5 files changed, 209 insertions(+), 54 deletions(-) diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index 58c9542..5e3a81b 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -44,4 +44,66 @@ bool compareBetaVersions({ else { return false; } +} + +bool versionIsGreater({ + required String currentVersion, + required String referenceVersion, + String? referenceVersionBeta +}) { + final current = currentVersion.replaceAll('v', ''); + final reference = referenceVersion.replaceAll('v', ''); + final referenceBeta = referenceVersionBeta?.replaceAll('v', ''); + + if (current.contains('beta')) { + if (referenceBeta != null) { + final currentSplit = current.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + final newSplit = referenceBeta.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + + final currentBeta = int.parse(current.split('-')[1].replaceAll('b.', '')); + final newBeta = int.parse(referenceBeta.split('-')[1].replaceAll('b.', '')); + + if (newSplit[0] == currentSplit[0] && newSplit[1] == currentSplit[1] && newSplit[2] == currentSplit[2] && newBeta == currentBeta) { + return true; + } + else if (newSplit[0] > currentSplit[0]) { + return true; + } + else if (newSplit[1] > currentSplit[1]) { + return true; + } + else if (newSplit[2] > currentSplit[2]) { + return true; + } + else if (newBeta > currentBeta) { + return true; + } + else { + return false; + } + } + else { + return false; + } + } + else { + final currentSplit = current.split('.').map((e) => int.parse(e)).toList(); + final newSplit = reference.split('.').map((e) => int.parse(e)).toList(); + + if (newSplit[0] == currentSplit[0] && newSplit[1] == currentSplit[1] && newSplit[2] == currentSplit[2]) { + return true; + } + else if (newSplit[0] > currentSplit[0]) { + return true; + } + else if (newSplit[1] > currentSplit[1]) { + return true; + } + else if (newSplit[2] > currentSplit[2]) { + return true; + } + else { + return false; + } + } } \ No newline at end of file diff --git a/lib/models/server_status.dart b/lib/models/server_status.dart index 8d76613..2e364fb 100644 --- a/lib/models/server_status.dart +++ b/lib/models/server_status.dart @@ -23,6 +23,7 @@ class ServerStatusData { bool safeSearchEnabled; bool safeBrowsingEnabled; bool parentalControlEnabled; + final String serverVersion; ServerStatusData({ required this.stats, @@ -34,21 +35,23 @@ class ServerStatusData { required this.filteringEnabled, required this.safeSearchEnabled, required this.safeBrowsingEnabled, - required this.parentalControlEnabled + required this.parentalControlEnabled, + required this.serverVersion }); factory ServerStatusData.fromJson(Map json) => ServerStatusData( stats: DnsStatistics.fromJson(json['stats']), clients: json["clients"] != null ? List.from(json["clients"].map((x) => Client.fromJson(x))) : [], - generalEnabled: json['generalEnabled']['protection_enabled'], - timeGeneralDisabled: json['generalEnabled']['protection_disabled_duration'] ?? 0, - disabledUntil: json['generalEnabled']['protection_disabled_duration'] > 0 - ? generateTimeDeadline(json['generalEnabled']['protection_disabled_duration']) + generalEnabled: json['status']['protection_enabled'], + timeGeneralDisabled: json['status']['protection_disabled_duration'] ?? 0, + disabledUntil: json['status']['protection_disabled_duration'] > 0 + ? generateTimeDeadline(json['status']['protection_disabled_duration']) : null , filteringStatus: FilteringStatus.fromJson(json['filtering']), filteringEnabled: json['filtering']['enabled'], safeSearchEnabled: json['safeSearchEnabled']['enabled'], safeBrowsingEnabled: json['safeBrowsingEnabled']['enabled'], - parentalControlEnabled: json['parentalControlEnabled']['enabled'] + parentalControlEnabled: json['parentalControlEnabled']['enabled'], + serverVersion: json['status']['version'] ); } \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 471bcaf..fcb0131 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -366,6 +366,25 @@ class ServersProvider with ChangeNotifier { return result['log']; } + case 'general_legacy': + _protectionsManagementProcess.add('general'); + notifyListeners(); + + final result = await updateGeneralProtectionLegacy(server, newStatus); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); + + if (result['result'] == 'success') { + _serverStatus.data!.generalEnabled = newStatus; + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + case 'filtering': _protectionsManagementProcess.add('filtering'); notifyListeners(); diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index aaef255..f562b57 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -3,12 +3,13 @@ import 'dart:async'; import 'dart:io'; -import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -146,23 +147,25 @@ class _ManagementModalState extends State with SingleTickerProv } Widget mainSwitch() { - Widget topRow() { + Widget topRow(bool legacyMode) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ - RotationTransition( - turns: animation, - child: Icon( - Icons.keyboard_arrow_down_rounded, - size: 26, - color: serversProvider.serverStatus.data!.generalEnabled == true - ? Theme.of(context).colorScheme.onSurfaceVariant - : Colors.grey, + if (legacyMode == true) ...[ + RotationTransition( + turns: animation, + child: Icon( + Icons.keyboard_arrow_down_rounded, + size: 26, + color: serversProvider.serverStatus.data!.generalEnabled == true + ? Theme.of(context).colorScheme.onSurfaceVariant + : Colors.grey, + ), ), - ), - const SizedBox(width: 8), + const SizedBox(width: 8), + ], Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -185,8 +188,15 @@ class _ManagementModalState extends State with SingleTickerProv Switch( value: serversProvider.serverStatus.data!.generalEnabled, onChanged: serversProvider.protectionsManagementProcess.contains('general') == false - ? (value) => updateBlocking(value: value, filter: 'general') - : null, + ? (value) { + if (value == false) { + expandableController.toggle(); + } + updateBlocking( + value: value, + filter: legacyMode == true ? 'general_legacy' : 'general' + ); + } : null, activeColor: Theme.of(context).colorScheme.primary, ) ] @@ -241,43 +251,71 @@ class _ManagementModalState extends State with SingleTickerProv return Padding( padding: const EdgeInsets.symmetric(horizontal: 24), - child: ExpandableNotifier( - controller: expandableController, - child: Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: serversProvider.serverStatus.data!.generalEnabled == true - ? () => expandableController.toggle() - : null, - borderRadius: BorderRadius.circular(28), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12 - ), - decoration: BoxDecoration( + child: versionIsGreater( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? ExpandableNotifier( + controller: expandableController, + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: serversProvider.serverStatus.data!.generalEnabled == true + ? () => expandableController.toggle() + : null, borderRadius: BorderRadius.circular(28), - color: Theme.of(context).primaryColor.withOpacity(0.1) - ), - child: Expandable( - theme: const ExpandableThemeData( - animationDuration: Duration(milliseconds: 200), - fadeCurve: Curves.ease + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: Theme.of(context).primaryColor.withOpacity(0.1) + ), + child: Expandable( + theme: const ExpandableThemeData( + animationDuration: Duration(milliseconds: 200), + fadeCurve: Curves.ease + ), + collapsed: topRow(true), + expanded: Column( + children: [ + topRow(true), + bottomRow(), + const SizedBox(height: 8) + ], + ) + ), ), - collapsed: topRow(), - expanded: Column( - children: [ - topRow(), - bottomRow(), - const SizedBox(height: 8) - ], - ) + ), + ) + ) + : Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: serversProvider.protectionsManagementProcess.contains('general') == false + ? () => updateBlocking( + value: !serversProvider.serverStatus.data!.generalEnabled, + filter: 'general_legacy' + ) : null, + borderRadius: BorderRadius.circular(28), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: Theme.of(context).primaryColor.withOpacity(0.1) + ), + child: topRow(false) ), ), - ), - ) - ), + ) ); } diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index b1b3d25..a9ddfa7 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -280,7 +280,7 @@ Future getServerStatus(Server server) async { final Map mappedData = { 'stats': jsonDecode(result[0]['body']), 'clients': jsonDecode(result[6]['body'])['clients'], - 'generalEnabled': jsonDecode(result[1]['body']), + 'status': jsonDecode(result[1]['body']), 'filtering': jsonDecode(result[2]['body']), 'safeSearchEnabled': jsonDecode(result[3]['body']), 'safeBrowsingEnabled': jsonDecode(result[4]['body']), @@ -503,6 +503,39 @@ Future updateGeneralProtection({ } } +Future updateGeneralProtectionLegacy(Server server, bool enable) async { + final result = await apiRequest( + urlPath: '/dns_config', + method: 'post', + server: server, + body: { + 'protection_enabled': enable + }, + type: 'general_protection' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'general_protection', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } +} + Future getClients(Server server) async { final result = await Future.wait([ apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'get_clients'), From 0921576c198131a84677c0fd71dc7eb9b3f5d978 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 14 Apr 2023 01:40:40 +0200 Subject: [PATCH 027/676] Added new safesearch settings --- lib/l10n/app_en.arb | 5 +- lib/l10n/app_es.arb | 5 +- lib/models/safe_search.dart | 51 +++ lib/models/server_status.dart | 24 +- lib/providers/servers_provider.dart | 2 +- .../settings/safe_search_settings.dart | 326 ++++++++++++++++++ lib/screens/settings/settings.dart | 18 + lib/services/http_requests.dart | 92 ++++- lib/widgets/custom_switch_list_tile.dart | 5 +- 9 files changed, 516 insertions(+), 12 deletions(-) create mode 100644 lib/models/safe_search.dart create mode 100644 lib/screens/settings/safe_search_settings.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index d42e8e7..2b66b5e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -603,5 +603,8 @@ "minutes": "{time} minutes", "hour": "{time} hour", "hours": "{time} hours", - "remainingTime": "Remaining time" + "remainingTime": "Remaining time", + "safeSearchSettings": "Safe search settings", + "loadingSafeSearchSettings": "Loading safe search settings...", + "safeSearchSettingsNotLoaded": "Error when loading safe search settings." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 6835437..76cff1b 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -603,5 +603,8 @@ "minutes": "{time} minutos", "hour": "{time} hora", "hours": "{time} horas", - "remainingTime": "Tiempo restante" + "remainingTime": "Tiempo restante", + "safeSearchSettings": "Configuración de búsqueda segura", + "loadingSafeSearchSettings": "Cargando configuración de búsqueda segura...", + "safeSearchSettingsNotLoaded": "Error al cargar la configuración de búsqueda segura." } \ No newline at end of file diff --git a/lib/models/safe_search.dart b/lib/models/safe_search.dart new file mode 100644 index 0000000..9fc69d7 --- /dev/null +++ b/lib/models/safe_search.dart @@ -0,0 +1,51 @@ +import 'package:adguard_home_manager/constants/enums.dart'; + +class SafeSearch { + LoadStatus loadStatus = LoadStatus.loading; + SafeSearchData? data; + + SafeSearch({ + required this.loadStatus, + this.data + }); +} + +class SafeSearchData { + final bool enabled; + final bool bing; + final bool duckduckgo; + final bool google; + final bool pixabay; + final bool yandex; + final bool youtube; + + SafeSearchData({ + required this.enabled, + required this.bing, + required this.duckduckgo, + required this.google, + required this.pixabay, + required this.yandex, + required this.youtube, + }); + + factory SafeSearchData.fromJson(Map json) => SafeSearchData( + enabled: json["enabled"], + bing: json["bing"], + duckduckgo: json["duckduckgo"], + google: json["google"], + pixabay: json["pixabay"], + yandex: json["yandex"], + youtube: json["youtube"], + ); + + Map toJson() => { + "enabled": enabled, + "bing": bing, + "duckduckgo": duckduckgo, + "google": google, + "pixabay": pixabay, + "yandex": yandex, + "youtube": youtube, + }; +} diff --git a/lib/models/server_status.dart b/lib/models/server_status.dart index 2e364fb..180ae1f 100644 --- a/lib/models/server_status.dart +++ b/lib/models/server_status.dart @@ -24,6 +24,12 @@ class ServerStatusData { bool safeBrowsingEnabled; bool parentalControlEnabled; final String serverVersion; + bool safeSeachBing; + bool safeSearchGoogle; + bool safeSearchDuckduckgo; + bool safeSearchPixabay; + bool safeSearchYandex; + bool safeSearchYoutube; ServerStatusData({ required this.stats, @@ -36,7 +42,13 @@ class ServerStatusData { required this.safeSearchEnabled, required this.safeBrowsingEnabled, required this.parentalControlEnabled, - required this.serverVersion + required this.serverVersion, + required this.safeSeachBing, + required this.safeSearchGoogle, + required this.safeSearchDuckduckgo, + required this.safeSearchPixabay, + required this.safeSearchYandex, + required this.safeSearchYoutube }); factory ServerStatusData.fromJson(Map json) => ServerStatusData( @@ -49,9 +61,15 @@ class ServerStatusData { : null , filteringStatus: FilteringStatus.fromJson(json['filtering']), filteringEnabled: json['filtering']['enabled'], - safeSearchEnabled: json['safeSearchEnabled']['enabled'], + safeSearchEnabled: json['safeSearch']['enabled'], safeBrowsingEnabled: json['safeBrowsingEnabled']['enabled'], parentalControlEnabled: json['parentalControlEnabled']['enabled'], - serverVersion: json['status']['version'] + serverVersion: json['status']['version'], + safeSeachBing: json['safeSearch']['bing'], + safeSearchDuckduckgo: json['safeSearch']['duckduckgo'], + safeSearchGoogle: json['safeSearch']['google'], + safeSearchPixabay: json['safeSearch']['pixabay'], + safeSearchYandex: json['safeSearch']['yandex'], + safeSearchYoutube: json['safeSearch']['youtube'], ); } \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index fcb0131..3dd70dc 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -247,7 +247,7 @@ class ServersProvider with ChangeNotifier { _updateAvailable.data = data; notifyListeners(); } - + Future createServer(Server server) async { final saved = await saveServerIntoDb(server); if (saved == null) { diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart new file mode 100644 index 0000000..8334bcf --- /dev/null +++ b/lib/screens/settings/safe_search_settings.dart @@ -0,0 +1,326 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class SafeSearchSettingsScreen extends StatelessWidget { + const SafeSearchSettingsScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + return SafeSearchSettingsScreenWidget( + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + ); + } +} + +class SafeSearchSettingsScreenWidget extends StatefulWidget { + final ServersProvider serversProvider; + final AppConfigProvider appConfigProvider; + + const SafeSearchSettingsScreenWidget({ + Key? key, + required this.serversProvider, + required this.appConfigProvider + }) : super(key: key); + + @override + State createState() => _SafeSearchSettingsScreenWidgetState(); +} + +class _SafeSearchSettingsScreenWidgetState extends State { + bool generalEnabled = false; + bool bingEnabled = false; + bool duckduckgoEnabled = false; + bool googleEnabled = false; + bool pixabayEnabled = false; + bool yandexEnabled = false; + bool youtubeEnabled = false; + + Future requestSafeSearchSettings() async { + final result = await getServerStatus(widget.serversProvider.selectedServer!); + if (mounted) { + if (result['result'] == 'success') { + widget.serversProvider.setServerStatusData(result['data']); + widget.serversProvider.setServerStatusLoad(1); + setState(() { + generalEnabled = result['data'].safeSearchEnabled; + bingEnabled = result['data'].safeSeachBing; + duckduckgoEnabled = result['data'].safeSearchDuckduckgo; + googleEnabled = result['data'].safeSearchGoogle; + pixabayEnabled = result['data'].safeSearchPixabay; + yandexEnabled = result['data'].safeSearchYandex; + youtubeEnabled = result['data'].safeSearchYoutube; + }); + } + else { + widget.appConfigProvider.addLog(result['log']); + widget.serversProvider.setServerStatusLoad(2); + } + } + } + + @override + void initState() { + if (widget.serversProvider.serverStatus.loadStatus == 0) { + requestSafeSearchSettings(); + } + else if (widget.serversProvider.serverStatus.loadStatus == 1) { + generalEnabled = widget.serversProvider.serverStatus.data!.safeSearchEnabled; + bingEnabled = widget.serversProvider.serverStatus.data!.safeSeachBing; + duckduckgoEnabled = widget.serversProvider.serverStatus.data!.safeSearchDuckduckgo; + googleEnabled = widget.serversProvider.serverStatus.data!.safeSearchGoogle; + pixabayEnabled = widget.serversProvider.serverStatus.data!.safeSearchPixabay; + yandexEnabled = widget.serversProvider.serverStatus.data!.safeSearchYandex; + youtubeEnabled = widget.serversProvider.serverStatus.data!.safeSearchYoutube; + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void saveConfig() async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.savingSettings); + + final result = await updateSafeSearchSettings( + server: serversProvider.selectedServer!, + body: { + "enabled": generalEnabled, + "bing": bingEnabled, + "duckduckgo": duckduckgoEnabled, + "google": googleEnabled, + "pixabay": pixabayEnabled, + "yandex": yandexEnabled, + "youtube": youtubeEnabled + } + ); + + processModal.close(); + + if (result['result'] == 'success') { + ServerStatusData data = serversProvider.serverStatus.data!; + data.safeSearchEnabled = generalEnabled; + data.safeSeachBing = bingEnabled; + data.safeSearchDuckduckgo = duckduckgoEnabled; + data.safeSearchGoogle = googleEnabled; + data.safeSearchPixabay = pixabayEnabled; + data.safeSearchYandex = yandexEnabled; + data.safeSearchYoutube = youtubeEnabled; + + serversProvider.setServerStatusData(data); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.settingsUpdatedSuccessfully, + color: Colors.green, + labelColor: Colors.white + ); + } + else { + appConfigProvider.addLog(result['log']); + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.settingsNotSaved, + color: Colors.red, + labelColor: Colors.white + ); + } + } + + Widget body() { + switch (serversProvider.serverStatus.loadStatus) { + case 0: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingSafeSearchSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case 1: + return RefreshIndicator( + onRefresh: requestSafeSearchSettings, + child: ListView( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 16, + left: 16, + right: 16, + bottom: 8 + ), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + borderRadius: BorderRadius.circular(28), + onTap: () => setState(() => generalEnabled = !generalEnabled), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 12 + ), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(28) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.enableSafeSearch, + style: const TextStyle( + fontSize: 18 + ), + ), + Switch( + value: generalEnabled, + onChanged: (value) => setState(() => generalEnabled = value) + ) + ], + ), + ), + ), + ), + ), + CustomSwitchListTile( + value: bingEnabled, + onChanged: (value) => setState(() => bingEnabled = value), + title: "Bing", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomSwitchListTile( + value: duckduckgoEnabled, + onChanged: (value) => setState(() => duckduckgoEnabled = value), + title: "DuckDuckGo", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomSwitchListTile( + value: googleEnabled, + onChanged: (value) => setState(() => googleEnabled = value), + title: "Google", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomSwitchListTile( + value: pixabayEnabled, + onChanged: (value) => setState(() => pixabayEnabled = value), + title: "Pixabay", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomSwitchListTile( + value: yandexEnabled, + onChanged: (value) => setState(() => yandexEnabled = value), + title: "Yandex", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomSwitchListTile( + value: youtubeEnabled, + onChanged: (value) => setState(() => youtubeEnabled = value), + title: "YouTube", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + ], + ), + ); + + case 2: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.safeSearchSettingsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + + default: + return const SizedBox(); + } + } + + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.safeSearchSettings), + centerTitle: false, + actions: [ + IconButton( + onPressed: serversProvider.serverStatus.loadStatus == 1 + ? () => saveConfig() + : null, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 8) + ], + ), + body: body(), + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index ea39f97..fe231d2 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -8,6 +8,7 @@ import 'package:adguard_home_manager/screens/settings/encryption/encryption.dart import 'package:adguard_home_manager/screens/settings/access_settings/access_settings.dart'; import 'package:adguard_home_manager/screens/settings/customization/customization.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp.dart'; +import 'package:adguard_home_manager/screens/settings/safe_search_settings.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/screens/settings/update_server/update.dart'; import 'package:adguard_home_manager/screens/settings/dns/dns.dart'; @@ -20,6 +21,7 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -49,6 +51,22 @@ class Settings extends StatelessWidget { children: [ if (serversProvider.selectedServer != null) ...[ SectionLabel(label: AppLocalizations.of(context)!.serverSettings), + if (versionIsGreater( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true) CustomListTile( + icon: Icons.search_rounded, + title: AppLocalizations.of(context)!.safeSearch, + subtitle: AppLocalizations.of(context)!.safeSearchSettings, + onTap: () => { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const SafeSearchSettingsScreen() + ) + ) + }, + ), CustomListTile( icon: Icons.lock_rounded, title: AppLocalizations.of(context)!.accessSettings, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index a9ddfa7..df1603f 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -14,13 +14,13 @@ import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; +import 'package:adguard_home_manager/models/safe_search.dart'; import 'package:adguard_home_manager/models/server_info.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/constants/urls.dart'; -import 'package:adguard_home_manager/models/update_available.dart'; Future> apiRequest({ @@ -61,8 +61,23 @@ Future> apiRequest({ }; } } - else if (method == 'post') { - HttpClientRequest request = await httpClient.postUrl(Uri.parse(connectionString)); + else if (method == 'post' || method == 'put') { + HttpClientRequest? request; + if (method == 'post') { + request = await httpClient.postUrl(Uri.parse(connectionString)); + } + else if (method == 'put') { + request = await httpClient.putUrl(Uri.parse(connectionString)); + } + else { + return { + 'hasResponse': false, + 'error': true, + 'statusCode': null, + 'body': 'Invalid method [selected $method]' + }; + } + if (server.authToken != null) { request.headers.set('Authorization', 'Basic ${server.authToken}'); } @@ -282,7 +297,7 @@ Future getServerStatus(Server server) async { 'clients': jsonDecode(result[6]['body'])['clients'], 'status': jsonDecode(result[1]['body']), 'filtering': jsonDecode(result[2]['body']), - 'safeSearchEnabled': jsonDecode(result[3]['body']), + 'safeSearch': jsonDecode(result[3]['body']), 'safeBrowsingEnabled': jsonDecode(result[4]['body']), 'parentalControlEnabled': jsonDecode(result[5]['body']), }; @@ -2169,4 +2184,73 @@ Future requestUpdateServer({ else { return result; } +} + +Future getSafeSearchSettings({ + required Server server, +}) async { + final result = await apiRequest( + urlPath: '/safesearch/status', + method: 'get', + server: server, + type: 'safesearch_settings' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': SafeSearchData.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'safesearch_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } +} + +Future updateSafeSearchSettings({ + required Server server, + required Map body +}) async { + final result = await apiRequest( + urlPath: '/safesearch/settings', + method: 'put', + server: server, + type: 'safesearch_settings', + body: body + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'safesearch_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } } \ No newline at end of file diff --git a/lib/widgets/custom_switch_list_tile.dart b/lib/widgets/custom_switch_list_tile.dart index fc6a1cd..84db718 100644 --- a/lib/widgets/custom_switch_list_tile.dart +++ b/lib/widgets/custom_switch_list_tile.dart @@ -6,6 +6,7 @@ class CustomSwitchListTile extends StatelessWidget { final String title; final String? subtitle; final bool? disabled; + final EdgeInsets? padding; const CustomSwitchListTile({ Key? key, @@ -14,6 +15,7 @@ class CustomSwitchListTile extends StatelessWidget { required this.title, this.disabled, this.subtitle, + this.padding }) : super(key: key); @override @@ -25,7 +27,7 @@ class CustomSwitchListTile extends StatelessWidget { ? null : () => onChanged(!value), child: Padding( - padding: const EdgeInsets.only( + padding: padding ?? const EdgeInsets.only( top: 12, left: 16, right: 18, bottom: 16 ), child: Row( @@ -68,7 +70,6 @@ class CustomSwitchListTile extends StatelessWidget { onChanged: disabled != null && disabled == true ? null : onChanged, - activeColor: Theme.of(context).colorScheme.primary, ) ], ), From 7b900ff90754a03faa986d1fc485c33c34797bf3 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 14 Apr 2023 01:53:08 +0200 Subject: [PATCH 028/676] Adapted compatibility --- lib/providers/servers_provider.dart | 8 +++++++- lib/services/http_requests.dart | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 3dd70dc..ce20665 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -411,7 +411,13 @@ class ServersProvider with ChangeNotifier { _protectionsManagementProcess.add('safeSearch'); notifyListeners(); - final result = await updateSafeSearch(server, newStatus); + final result = versionIsGreater( + currentVersion: serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? await updateSafeSearchSettings(server: server, body: { 'enabled': newStatus }) + : await updateSafeSearchLegacy(server, newStatus); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeSearch').toList(); diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index df1603f..909362d 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -369,7 +369,7 @@ Future updateFiltering({ } } -Future updateSafeSearch(Server server, bool enable) async { +Future updateSafeSearchLegacy(Server server, bool enable) async { final result = enable == true ? await apiRequest( urlPath: '/safesearch/enable', @@ -2223,7 +2223,7 @@ Future getSafeSearchSettings({ Future updateSafeSearchSettings({ required Server server, - required Map body + required Map body }) async { final result = await apiRequest( urlPath: '/safesearch/settings', From 81acf61505a1ec07e2bcda467b3b2addc170c22a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 14 Apr 2023 22:49:16 +0200 Subject: [PATCH 029/676] Safe search replaced toggles with checkboxes --- .../settings/safe_search_settings.dart | 13 +-- lib/widgets/custom_checkbox_list_tile.dart | 95 +++++++++++++++++++ 2 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 lib/widgets/custom_checkbox_list_tile.dart diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 8334bcf..1d8a31e 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -8,6 +8,7 @@ import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -216,7 +217,7 @@ class _SafeSearchSettingsScreenWidgetState extends State setState(() => bingEnabled = value), title: "Bing", @@ -225,7 +226,7 @@ class _SafeSearchSettingsScreenWidgetState extends State setState(() => duckduckgoEnabled = value), title: "DuckDuckGo", @@ -234,7 +235,7 @@ class _SafeSearchSettingsScreenWidgetState extends State setState(() => googleEnabled = value), title: "Google", @@ -243,7 +244,7 @@ class _SafeSearchSettingsScreenWidgetState extends State setState(() => pixabayEnabled = value), title: "Pixabay", @@ -252,7 +253,7 @@ class _SafeSearchSettingsScreenWidgetState extends State setState(() => yandexEnabled = value), title: "Yandex", @@ -261,7 +262,7 @@ class _SafeSearchSettingsScreenWidgetState extends State setState(() => youtubeEnabled = value), title: "YouTube", diff --git a/lib/widgets/custom_checkbox_list_tile.dart b/lib/widgets/custom_checkbox_list_tile.dart new file mode 100644 index 0000000..be14a3c --- /dev/null +++ b/lib/widgets/custom_checkbox_list_tile.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; + +class CustomCheckboxListTile extends StatelessWidget { + final bool value; + final void Function(bool) onChanged; + final String title; + final String? subtitle; + final bool? disabled; + final EdgeInsets? padding; + + const CustomCheckboxListTile({ + Key? key, + required this.value, + required this.onChanged, + required this.title, + this.disabled, + this.subtitle, + this.padding + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: disabled != null && disabled == true + ? null + : () => onChanged(!value), + child: Padding( + padding: padding ?? const EdgeInsets.only( + top: 12, left: 16, right: 18, bottom: 16 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + fontSize: 16, + color: disabled != null && disabled == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + : Theme.of(context).colorScheme.onSurface, + ), + ), + if (subtitle != null) ... [ + const SizedBox(height: 5), + SizedBox( + width: MediaQuery.of(context).size.width-110, + child: Text( + subtitle!, + style: TextStyle( + fontSize: 14, + color: disabled != null && disabled == true + ? Theme.of(context).listTileTheme.textColor!.withOpacity(0.38) + : Theme.of(context).listTileTheme.textColor + ), + ), + ), + ] + ], + ), + ), + const SizedBox(width: 16), + Theme( + data: ThemeData( + unselectedWidgetColor: disabled == true + ? Colors.grey + : Theme.of(context).colorScheme.onSurface, + disabledColor: Colors.grey + ), + child: Checkbox( + value: value, + onChanged: (value) => disabled != null && disabled == true && value != null + ? null + : onChanged(value!), + tristate: false, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + activeColor: disabled == true + ? Colors.grey + : Theme.of(context).colorScheme.primary, + ), + ) + ], + ), + ), + ), + ); + } +} \ No newline at end of file From 3aac65a3060a46e3f18b3363b34c6e9afaa8d0e7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 14 Apr 2023 23:16:48 +0200 Subject: [PATCH 030/676] Supported new querylog endpoints --- lib/services/http_requests.dart | 69 +++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 909362d..662acb0 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1591,6 +1591,41 @@ Future addDnsRewriteRule({ Future getQueryLogInfo({ required Server server, +}) async { + final result = await apiRequest( + urlPath: '/querylog/config', + method: 'get', + server: server, + type: 'get_query_log_info' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': jsonDecode(result['body']) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_query_log_info', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } +} + +Future getQueryLogInfoLegacy({ + required Server server, }) async { final result = await apiRequest( urlPath: '/querylog_info', @@ -1627,6 +1662,40 @@ Future getQueryLogInfo({ Future updateQueryLogParameters({ required Server server, required Map data, +}) async { + final result = await apiRequest( + urlPath: '/querylog/config/update', + method: 'put', + server: server, + body: data, + type: 'update_query_log_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_query_log_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } +} + +Future updateQueryLogParametersLegacy({ + required Server server, + required Map data, }) async { final result = await apiRequest( urlPath: '/querylog_config', From 415194d7a593677e6db00d76d81113dbdb49ef84 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 14 Apr 2023 23:17:54 +0200 Subject: [PATCH 031/676] Support edit querylog config --- lib/screens/logs/logs.dart | 9 +++++- lib/screens/logs/logs_config_modal.dart | 37 +++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index a70abfa..575becd 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -11,6 +11,7 @@ import 'package:adguard_home_manager/screens/logs/log_tile.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -191,7 +192,13 @@ class _LogsWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingSettings); - final result = await updateQueryLogParameters(server: serversProvider.selectedServer!, data: data); + final result = versionIsGreater( + currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? await updateQueryLogParameters(server: serversProvider.selectedServer!, data: data) + : await updateQueryLogParametersLegacy(server: serversProvider.selectedServer!, data: data); processModal.close(); diff --git a/lib/screens/logs/logs_config_modal.dart b/lib/screens/logs/logs_config_modal.dart index 9a33dbf..472fd55 100644 --- a/lib/screens/logs/logs_config_modal.dart +++ b/lib/screens/logs/logs_config_modal.dart @@ -5,6 +5,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -63,7 +64,13 @@ class _LogsConfigModalWidgetState extends State { int loadStatus = 0; void loadData() async { - final result = await getQueryLogInfo(server: widget.serversProvider.selectedServer!); + final result = versionIsGreater( + currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? await getQueryLogInfo(server: widget.serversProvider.selectedServer!) + : await getQueryLogInfoLegacy(server: widget.serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { @@ -82,7 +89,32 @@ class _LogsConfigModalWidgetState extends State { @override void initState() { - retentionItems = [ + retentionItems = versionIsGreater( + currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true ? [ + { + 'label': AppLocalizations.of(widget.context)!.hours6, + 'value': 21600000 + }, + { + 'label': AppLocalizations.of(widget.context)!.hours24, + 'value': 86400000 + }, + { + 'label': AppLocalizations.of(widget.context)!.days7, + 'value': 604800000 + }, + { + 'label': AppLocalizations.of(widget.context)!.days30, + 'value': 2592000000 + }, + { + 'label': AppLocalizations.of(widget.context)!.days90, + 'value': 7776000000 + }, + ] : [ { 'label': AppLocalizations.of(widget.context)!.hours6, 'value': 0.25 @@ -111,7 +143,6 @@ class _LogsConfigModalWidgetState extends State { @override Widget build(BuildContext context) { - Widget generateBody() { switch (loadStatus) { case 0: From f54770dbbacb7b48cecacc38c6c3e55b66dd2179 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 15 Apr 2023 01:22:44 +0200 Subject: [PATCH 032/676] Adapted added clients new version --- lib/models/clients.dart | 9 +- lib/models/safe_search.dart | 28 +-- lib/screens/clients/added_list.dart | 28 ++- lib/screens/clients/client_screen.dart | 85 +++++++- lib/screens/clients/fab.dart | 13 +- lib/screens/clients/safe_search_modal.dart | 196 ++++++++++++++++++ lib/screens/clients/search_clients.dart | 28 ++- lib/screens/filters/add_custom_rule.dart | 1 - lib/screens/home/management_modal.dart | 2 - lib/screens/logs/logs_config_modal.dart | 2 - lib/screens/settings/advanced_setings.dart | 1 - lib/screens/settings/dhcp/dhcp.dart | 1 - .../settings/encryption/master_switch.dart | 1 - lib/screens/settings/general_settings.dart | 2 - .../settings/safe_search_settings.dart | 3 +- lib/services/http_requests.dart | 35 ---- lib/widgets/add_server_modal.dart | 2 - 17 files changed, 343 insertions(+), 94 deletions(-) create mode 100644 lib/screens/clients/safe_search_modal.dart diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 9fc9b06..2c9f222 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; +import 'package:adguard_home_manager/models/safe_search.dart'; class Clients { LoadStatus loadStatus; @@ -100,9 +101,10 @@ class Client { final bool filteringEnabled; final bool parentalEnabled; final bool safebrowsingEnabled; - final bool safesearchEnabled; + final bool? safesearchEnabled; final bool useGlobalBlockedServices; final bool useGlobalSettings; + final SafeSearch? safeSearch; Client({ required this.name, @@ -116,6 +118,7 @@ class Client { required this.safesearchEnabled, required this.useGlobalBlockedServices, required this.useGlobalSettings, + required this.safeSearch, }); factory Client.fromJson(Map json) => Client( @@ -130,6 +133,9 @@ class Client { safesearchEnabled: json["safesearch_enabled"], useGlobalBlockedServices: json["use_global_blocked_services"], useGlobalSettings: json["use_global_settings"], + safeSearch: json["safe_search"] != null + ? SafeSearch.fromJson(json["safe_search"]) + : null ); Map toJson() => { @@ -142,6 +148,7 @@ class Client { "parental_enabled": parentalEnabled, "safebrowsing_enabled": safebrowsingEnabled, "safesearch_enabled": safesearchEnabled, + "safe_search": safeSearch, "use_global_blocked_services": useGlobalBlockedServices, "use_global_settings": useGlobalSettings, }; diff --git a/lib/models/safe_search.dart b/lib/models/safe_search.dart index 9fc69d7..4b960c9 100644 --- a/lib/models/safe_search.dart +++ b/lib/models/safe_search.dart @@ -1,25 +1,13 @@ -import 'package:adguard_home_manager/constants/enums.dart'; - class SafeSearch { - LoadStatus loadStatus = LoadStatus.loading; - SafeSearchData? data; + bool enabled = false; + bool bing = false; + bool duckduckgo = false; + bool google = false; + bool pixabay = false; + bool yandex = false; + bool youtube = false; SafeSearch({ - required this.loadStatus, - this.data - }); -} - -class SafeSearchData { - final bool enabled; - final bool bing; - final bool duckduckgo; - final bool google; - final bool pixabay; - final bool yandex; - final bool youtube; - - SafeSearchData({ required this.enabled, required this.bing, required this.duckduckgo, @@ -29,7 +17,7 @@ class SafeSearchData { required this.youtube, }); - factory SafeSearchData.fromJson(Map json) => SafeSearchData( + factory SafeSearch.fromJson(Map json) => SafeSearch( enabled: json["enabled"], bing: json["bing"], duckduckgo: json["duckduckgo"], diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index b18dcf4..0aeb121 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -16,6 +16,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -146,6 +147,7 @@ class _AddedListState extends State { fullscreenDialog: true, builder: (BuildContext context) => ClientScreen( onConfirm: confirmEditClient, + serverVersion: serversProvider.serverStatus.data!.serverVersion, onDelete: deleteClient, client: client, ) @@ -260,13 +262,25 @@ class _AddedListState extends State { Icon( Icons.search_rounded, size: 19, - color: widget.data[index].safesearchEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, + color: versionIsGreater( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? widget.data[index].safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + : widget.data[index].safesearchEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, ) ], ) diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart index 51dcb6e..9cd22b4 100644 --- a/lib/screens/clients/client_screen.dart +++ b/lib/screens/clients/client_screen.dart @@ -4,20 +4,26 @@ import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; +import 'package:adguard_home_manager/screens/clients/safe_search_modal.dart'; import 'package:adguard_home_manager/screens/clients/services_modal.dart'; import 'package:adguard_home_manager/screens/clients/tags_modal.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'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; class ClientScreen extends StatefulWidget { final Client? client; + final String serverVersion; final void Function(Client) onConfirm; final void Function(Client)? onDelete; const ClientScreen({ Key? key, this.client, + required this.serverVersion, required this.onConfirm, this.onDelete, }) : super(key: key); @@ -46,6 +52,15 @@ class _ClientScreenState extends State { bool? enableSafeBrowsing; bool? enableParentalControl; bool? enableSafeSearch; + SafeSearch safeSearch = SafeSearch( + enabled: false, + bing: false, + duckduckgo: false, + google: false, + pixabay: false, + yandex: false, + youtube: false + ); bool useGlobalSettingsServices = true; List blockedServices = []; @@ -66,8 +81,16 @@ class _ClientScreenState extends State { } } + bool version = false; + @override void initState() { + version = versionIsGreater( + currentVersion: widget.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ); + if (widget.client != null) { editMode = false; @@ -81,7 +104,12 @@ class _ClientScreenState extends State { enableFiltering = widget.client!.filteringEnabled; enableParentalControl = widget.client!.parentalEnabled; enableSafeBrowsing = widget.client!.safebrowsingEnabled; - enableSafeSearch = widget.client!.safesearchEnabled; + if (version == true) { + safeSearch = widget.client!.safeSearch!; + } + else { + enableSafeSearch = widget.client!.safesearchEnabled!; + } useGlobalSettingsServices = widget.client!.useGlobalBlockedServices; blockedServices = widget.client!.blockedServices; upstreamServers = widget.client!.upstreams.map((e) => { @@ -104,7 +132,8 @@ class _ClientScreenState extends State { filteringEnabled: enableFiltering ?? false, parentalEnabled: enableParentalControl ?? false, safebrowsingEnabled: enableSafeBrowsing ?? false, - safesearchEnabled: enableSafeSearch ?? false, + safesearchEnabled: version == true ? enableSafeSearch : null, + safeSearch: version == true ? safeSearch : null, useGlobalBlockedServices: useGlobalSettingsServices, blockedServices: blockedServices, upstreams: List.from(upstreamServers.map((e) => e['controller'].text)), @@ -141,7 +170,7 @@ class _ClientScreenState extends State { enableFiltering = false; enableSafeBrowsing = false; enableParentalControl = false; - enableSafeSearch = false; + safeSearch.enabled = false; }); } else if (useGlobalSettingsFiltering == false) { @@ -151,7 +180,7 @@ class _ClientScreenState extends State { enableFiltering = null; enableSafeBrowsing = null; enableParentalControl = null; - enableSafeSearch = null; + safeSearch.enabled = false; }); } } @@ -203,6 +232,17 @@ class _ClientScreenState extends State { ); } + void openSafeSearchModal() { + showDialog( + context: context, + builder: (context) => SafeSearchModal( + safeSearch: safeSearch, + disabled: !editMode, + onConfirm: (s) => setState(() => safeSearch = s) + ) + ); + } + Widget settignsTile({ required String label, required bool? value, @@ -233,10 +273,12 @@ class _ClientScreenState extends State { ? Switch( value: value!, onChanged: onChange, - activeColor: Theme.of(context).colorScheme.primary, ) : Padding( - padding: const EdgeInsets.symmetric(vertical: 14), + padding: const EdgeInsets.symmetric( + vertical: 14, + horizontal: 12 + ), child: Text( "Global", style: TextStyle( @@ -461,7 +503,6 @@ class _ClientScreenState extends State { onChanged: editMode == true ? (value) => enableDisableGlobalSettingsFiltering() : null, - activeColor: Theme.of(context).colorScheme.primary, ) ], ), @@ -491,7 +532,34 @@ class _ClientScreenState extends State { ? (value) => setState(() => enableParentalControl = value) : null ), - settignsTile( + if ( + versionIsGreater( + currentVersion: serversProvider.serverStatus.data!.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: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + onTap: openSafeSearchModal, + ), + if ( + versionIsGreater( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == false + ) settignsTile( label: AppLocalizations.of(context)!.enableSafeSearch, value: enableSafeSearch, onChange: editMode == true @@ -529,7 +597,6 @@ class _ClientScreenState extends State { onChanged: editMode == true ? (value) => updateServicesGlobalSettings(value) : null, - activeColor: Theme.of(context).colorScheme.primary, ) ], ), diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index d916486..2c84151 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -7,6 +7,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/client_screen.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -25,7 +26,16 @@ class ClientsFab extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingClient); - final result = await postAddClient(server: serversProvider.selectedServer!, data: client.toJson()); + final result = await postAddClient( + server: serversProvider.selectedServer!, + data: versionIsGreater( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == false + ? client.toJson().remove('safesearch_enabled') + : client.toJson().remove('safe_search') + ); processModal.close(); @@ -58,6 +68,7 @@ class ClientsFab extends StatelessWidget { fullscreenDialog: true, builder: (BuildContext context) => ClientScreen( onConfirm: confirmAddClient, + serverVersion: serversProvider.serverStatus.data!.serverVersion, ) )); } diff --git a/lib/screens/clients/safe_search_modal.dart b/lib/screens/clients/safe_search_modal.dart new file mode 100644 index 0000000..9d51f01 --- /dev/null +++ b/lib/screens/clients/safe_search_modal.dart @@ -0,0 +1,196 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; + +import 'package:adguard_home_manager/models/safe_search.dart'; + +class SafeSearchModal extends StatefulWidget { + final SafeSearch safeSearch; + final bool disabled; + final void Function(SafeSearch) onConfirm; + + const SafeSearchModal({ + Key? key, + required this.safeSearch, + required this.disabled, + required this.onConfirm + }) : super(key: key); + + @override + State createState() => _SafeSearchModalState(); +} + +class _SafeSearchModalState extends State { + bool generalEnabled = false; + bool bingEnabled = false; + bool duckduckgoEnabled = false; + bool googleEnabled = false; + bool pixabayEnabled = false; + bool yandexEnabled = false; + bool youtubeEnabled = false; + + @override + void initState() { + generalEnabled = widget.safeSearch.enabled; + bingEnabled = widget.safeSearch.bing; + duckduckgoEnabled = widget.safeSearch.duckduckgo; + googleEnabled = widget.safeSearch.google; + pixabayEnabled = widget.safeSearch.pixabay; + yandexEnabled = widget.safeSearch.yandex; + youtubeEnabled = widget.safeSearch.youtube; + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + contentPadding: const EdgeInsets.symmetric(horizontal: 0, vertical: 16), + title: Column( + children: [ + Icon( + Icons.search_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.safeSearch, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: Wrap( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Material( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: widget.disabled == true + ? null + : () => setState(() => generalEnabled = !generalEnabled), + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 5 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.enable, + style: TextStyle( + fontSize: 16, + color: widget.disabled == true + ? Colors.grey + : Theme.of(context).colorScheme.onSurface + ), + ), + Switch( + value: generalEnabled, + onChanged: widget.disabled == true + ? null + : (value) => setState(() => generalEnabled = value), + ) + ], + ), + ), + ), + ), + ), + const SizedBox(height: 4, width: double.maxFinite), + CustomCheckboxListTile( + value: bingEnabled, + onChanged: (value) => setState(() => bingEnabled = value), + title: "Bing", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), + ), + CustomCheckboxListTile( + value: duckduckgoEnabled, + onChanged: (value) => setState(() => duckduckgoEnabled = value), + title: "DuckDuckGo", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), + ), + CustomCheckboxListTile( + value: googleEnabled, + onChanged: (value) => setState(() => googleEnabled = value), + title: "Google", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), + ), + CustomCheckboxListTile( + value: pixabayEnabled, + onChanged: (value) => setState(() => pixabayEnabled = value), + title: "Pixabay", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), + ), + CustomCheckboxListTile( + value: yandexEnabled, + onChanged: (value) => setState(() => yandexEnabled = value), + title: "Yandex", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), + ), + CustomCheckboxListTile( + value: youtubeEnabled, + onChanged: (value) => setState(() => youtubeEnabled = value), + title: "YouTube", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + TextButton( + onPressed: widget.disabled == false ? () { + widget.onConfirm( + SafeSearch( + enabled: generalEnabled, + bing: bingEnabled, + duckduckgo: duckduckgoEnabled, + google: googleEnabled, + pixabay: pixabayEnabled, + yandex: yandexEnabled, + youtube: youtubeEnabled + ) + ); + Navigator.pop(context); + } : null, + child: Text(AppLocalizations.of(context)!.confirm) + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index 9a570af..4ac2a66 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -13,6 +13,7 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; @@ -188,6 +189,7 @@ class _SearchClientsWidgetState extends State { onConfirm: confirmEditClient, onDelete: deleteClient, client: client, + serverVersion: serversProvider.serverStatus.data!.serverVersion, ) )); } @@ -337,13 +339,25 @@ class _SearchClientsWidgetState extends State { Icon( Icons.search_rounded, size: 19, - color: clientsScreen[index].safesearchEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, + color: versionIsGreater( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? clientsScreen[index].safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + : clientsScreen[index].safesearchEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, ) ], ) diff --git a/lib/screens/filters/add_custom_rule.dart b/lib/screens/filters/add_custom_rule.dart index a0941c1..3f1e1f2 100644 --- a/lib/screens/filters/add_custom_rule.dart +++ b/lib/screens/filters/add_custom_rule.dart @@ -200,7 +200,6 @@ class _AddCustomRuleState extends State { Switch( value: addImportant, onChanged: (value) => setState(() => addImportant = value), - activeColor: Theme.of(context).colorScheme.primary, ) ], ), diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index f562b57..83029b8 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -197,7 +197,6 @@ class _ManagementModalState extends State with SingleTickerProv filter: legacyMode == true ? 'general_legacy' : 'general' ); } : null, - activeColor: Theme.of(context).colorScheme.primary, ) ] ); @@ -357,7 +356,6 @@ class _ManagementModalState extends State with SingleTickerProv onChanged: disabled == false ? onChange : null, - activeColor: Theme.of(context).colorScheme.primary, ) ], ), diff --git a/lib/screens/logs/logs_config_modal.dart b/lib/screens/logs/logs_config_modal.dart index 472fd55..3d80a87 100644 --- a/lib/screens/logs/logs_config_modal.dart +++ b/lib/screens/logs/logs_config_modal.dart @@ -202,7 +202,6 @@ class _LogsConfigModalWidgetState extends State { Switch( value: generalSwitch, onChanged: (value) => setState(() => generalSwitch = value), - activeColor: Theme.of(context).colorScheme.primary, ) ], ), @@ -233,7 +232,6 @@ class _LogsConfigModalWidgetState extends State { Switch( value: anonymizeClientIp, onChanged: (value) => setState(() => anonymizeClientIp = value), - activeColor: Theme.of(context).colorScheme.primary, ) ], ), diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index f1da7f5..987d406 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -50,7 +50,6 @@ class AdvancedSettings extends StatelessWidget { trailing: Switch( value: appConfigProvider.overrideSslCheck, onChanged: updateSslCheck, - activeColor: Theme.of(context).colorScheme.primary, ), onTap: () => updateSslCheck(!appConfigProvider.overrideSslCheck), padding: const EdgeInsets.only( diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 3ba3b68..a4a8319 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -449,7 +449,6 @@ class _DhcpWidgetState extends State { onChanged: selectedInterface != null ? (value) => setState(() => enabled = value) : null, - activeColor: Theme.of(context).colorScheme.primary, ), ], ), diff --git a/lib/screens/settings/encryption/master_switch.dart b/lib/screens/settings/encryption/master_switch.dart index af68536..f13c4fa 100644 --- a/lib/screens/settings/encryption/master_switch.dart +++ b/lib/screens/settings/encryption/master_switch.dart @@ -58,7 +58,6 @@ class EncryptionMasterSwitch extends StatelessWidget { Switch( value: value, onChanged: (value) => onChange(value), - activeColor: Theme.of(context).colorScheme.primary, ), ], ), diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index afad45e..fed1be1 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -69,7 +69,6 @@ class GeneralSettings extends StatelessWidget { trailing: Switch( value: appConfigProvider.hideZeroValues, onChanged: updateHideZeroValues, - activeColor: Theme.of(context).colorScheme.primary, ), onTap: () => updateHideZeroValues(!appConfigProvider.hideZeroValues), padding: const EdgeInsets.only( @@ -86,7 +85,6 @@ class GeneralSettings extends StatelessWidget { trailing: Switch( value: appConfigProvider.showNameTimeLogs, onChanged: updateShowNameTimeLogs, - activeColor: Theme.of(context).colorScheme.primary, ), onTap: () => updateShowNameTimeLogs(!appConfigProvider.showNameTimeLogs), padding: const EdgeInsets.only( diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 1d8a31e..02a9c1d 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -4,11 +4,10 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; +import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 662acb0..041368e 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -2255,41 +2255,6 @@ Future requestUpdateServer({ } } -Future getSafeSearchSettings({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/safesearch/status', - method: 'get', - server: server, - type: 'safesearch_settings' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': SafeSearchData.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'safesearch_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - Future updateSafeSearchSettings({ required Server server, required Map body diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 758876b..7fc830d 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -580,7 +580,6 @@ class _AddServerModalState extends State { onChanged: widget.server == null ? (value) => setState(() => defaultServer = value) : null, - activeColor: Theme.of(context).colorScheme.primary, ) ], ), @@ -606,7 +605,6 @@ class _AddServerModalState extends State { Switch( value: homeAssistant, onChanged: (value) => setState(() => homeAssistant = value), - activeColor: Theme.of(context).colorScheme.primary, ) ], ), From d152293594cc6e2edf967df995c984c13ae0ccac Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 15 Apr 2023 02:02:40 +0200 Subject: [PATCH 033/676] Fixes --- lib/functions/compare_versions.dart | 16 +++++++-------- lib/functions/maps_fns.dart | 5 +++++ lib/models/server_status.dart | 20 ++++++++++--------- lib/providers/servers_provider.dart | 2 +- lib/screens/clients/added_list.dart | 11 ++++++++-- lib/screens/clients/client_screen.dart | 12 ++++++----- lib/screens/clients/fab.dart | 7 ++++--- lib/screens/clients/search_clients.dart | 2 +- lib/screens/home/management_modal.dart | 2 +- lib/screens/logs/logs.dart | 2 +- lib/screens/logs/logs_config_modal.dart | 4 ++-- .../access_settings/access_settings.dart | 1 - .../settings/safe_search_settings.dart | 12 +++++------ lib/screens/settings/settings.dart | 2 +- 14 files changed, 57 insertions(+), 41 deletions(-) create mode 100644 lib/functions/maps_fns.dart diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index 5e3a81b..39b78cd 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -46,7 +46,7 @@ bool compareBetaVersions({ } } -bool versionIsGreater({ +bool serverVersionIsAhead({ required String currentVersion, required String referenceVersion, String? referenceVersionBeta @@ -66,16 +66,16 @@ bool versionIsGreater({ if (newSplit[0] == currentSplit[0] && newSplit[1] == currentSplit[1] && newSplit[2] == currentSplit[2] && newBeta == currentBeta) { return true; } - else if (newSplit[0] > currentSplit[0]) { + else if (newSplit[0] < currentSplit[0]) { return true; } - else if (newSplit[1] > currentSplit[1]) { + else if (newSplit[1] < currentSplit[1]) { return true; } - else if (newSplit[2] > currentSplit[2]) { + else if (newSplit[2] < currentSplit[2]) { return true; } - else if (newBeta > currentBeta) { + else if (newBeta < currentBeta) { return true; } else { @@ -93,13 +93,13 @@ bool versionIsGreater({ if (newSplit[0] == currentSplit[0] && newSplit[1] == currentSplit[1] && newSplit[2] == currentSplit[2]) { return true; } - else if (newSplit[0] > currentSplit[0]) { + else if (newSplit[0] < currentSplit[0]) { return true; } - else if (newSplit[1] > currentSplit[1]) { + else if (newSplit[1] < currentSplit[1]) { return true; } - else if (newSplit[2] > currentSplit[2]) { + else if (newSplit[2] < currentSplit[2]) { return true; } else { diff --git a/lib/functions/maps_fns.dart b/lib/functions/maps_fns.dart new file mode 100644 index 0000000..974e5f0 --- /dev/null +++ b/lib/functions/maps_fns.dart @@ -0,0 +1,5 @@ +Map removePropFromMap(Map o, String prop) { + Map obj = {...o}; + obj.remove(prop); + return o; +} \ No newline at end of file diff --git a/lib/models/server_status.dart b/lib/models/server_status.dart index 180ae1f..3d68399 100644 --- a/lib/models/server_status.dart +++ b/lib/models/server_status.dart @@ -24,12 +24,12 @@ class ServerStatusData { bool safeBrowsingEnabled; bool parentalControlEnabled; final String serverVersion; - bool safeSeachBing; - bool safeSearchGoogle; - bool safeSearchDuckduckgo; - bool safeSearchPixabay; - bool safeSearchYandex; - bool safeSearchYoutube; + bool? safeSeachBing; + bool? safeSearchGoogle; + bool? safeSearchDuckduckgo; + bool? safeSearchPixabay; + bool? safeSearchYandex; + bool? safeSearchYoutube; ServerStatusData({ required this.stats, @@ -56,9 +56,11 @@ class ServerStatusData { clients: json["clients"] != null ? List.from(json["clients"].map((x) => Client.fromJson(x))) : [], generalEnabled: json['status']['protection_enabled'], timeGeneralDisabled: json['status']['protection_disabled_duration'] ?? 0, - disabledUntil: json['status']['protection_disabled_duration'] > 0 - ? generateTimeDeadline(json['status']['protection_disabled_duration']) - : null , + disabledUntil: json['status']['protection_disabled_duration'] != null + ? json['status']['protection_disabled_duration'] > 0 + ? generateTimeDeadline(json['status']['protection_disabled_duration']) + : null + : null, filteringStatus: FilteringStatus.fromJson(json['filtering']), filteringEnabled: json['filtering']['enabled'], safeSearchEnabled: json['safeSearch']['enabled'], diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index ce20665..f448c74 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -411,7 +411,7 @@ class ServersProvider with ChangeNotifier { _protectionsManagementProcess.add('safeSearch'); notifyListeners(); - final result = versionIsGreater( + final result = serverVersionIsAhead( currentVersion: serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 0aeb121..dc9c974 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -13,6 +13,7 @@ import 'package:adguard_home_manager/screens/clients/options_modal.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/functions/maps_fns.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -74,7 +75,13 @@ class _AddedListState extends State { final result = await postUpdateClient(server: serversProvider.selectedServer!, data: { 'name': client.name, - 'data': client.toJson() + 'data': serverVersionIsAhead( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == false + ? removePropFromMap(client.toJson(), 'safesearch_enabled') + : removePropFromMap(client.toJson(), 'safe_search') }); processModal.close(); @@ -262,7 +269,7 @@ class _AddedListState extends State { Icon( Icons.search_rounded, size: 19, - color: versionIsGreater( + color: serverVersionIsAhead( currentVersion: serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart index 9cd22b4..277970a 100644 --- a/lib/screens/clients/client_screen.dart +++ b/lib/screens/clients/client_screen.dart @@ -85,7 +85,7 @@ class _ClientScreenState extends State { @override void initState() { - version = versionIsGreater( + version = serverVersionIsAhead( currentVersion: widget.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' @@ -108,7 +108,7 @@ class _ClientScreenState extends State { safeSearch = widget.client!.safeSearch!; } else { - enableSafeSearch = widget.client!.safesearchEnabled!; + enableSafeSearch = widget.client!.safesearchEnabled ?? false; } useGlobalSettingsServices = widget.client!.useGlobalBlockedServices; blockedServices = widget.client!.blockedServices; @@ -132,7 +132,7 @@ class _ClientScreenState extends State { filteringEnabled: enableFiltering ?? false, parentalEnabled: enableParentalControl ?? false, safebrowsingEnabled: enableSafeBrowsing ?? false, - safesearchEnabled: version == true ? enableSafeSearch : null, + safesearchEnabled: version == false ? enableSafeSearch : null, safeSearch: version == true ? safeSearch : null, useGlobalBlockedServices: useGlobalSettingsServices, blockedServices: blockedServices, @@ -170,6 +170,7 @@ class _ClientScreenState extends State { enableFiltering = false; enableSafeBrowsing = false; enableParentalControl = false; + enableSafeSearch = false; safeSearch.enabled = false; }); } @@ -180,6 +181,7 @@ class _ClientScreenState extends State { enableFiltering = null; enableSafeBrowsing = null; enableParentalControl = null; + enableSafeSearch = null; safeSearch.enabled = false; }); } @@ -533,7 +535,7 @@ class _ClientScreenState extends State { : null ), if ( - versionIsGreater( + serverVersionIsAhead( currentVersion: serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' @@ -554,7 +556,7 @@ class _ClientScreenState extends State { onTap: openSafeSearchModal, ), if ( - versionIsGreater( + serverVersionIsAhead( currentVersion: serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 2c84151..4eff04e 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -9,6 +9,7 @@ import 'package:adguard_home_manager/screens/clients/client_screen.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/functions/maps_fns.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -28,13 +29,13 @@ class ClientsFab extends StatelessWidget { final result = await postAddClient( server: serversProvider.selectedServer!, - data: versionIsGreater( + data: serverVersionIsAhead( currentVersion: serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == false - ? client.toJson().remove('safesearch_enabled') - : client.toJson().remove('safe_search') + ? removePropFromMap(client.toJson(), 'safesearch_enabled') + : removePropFromMap(client.toJson(), 'safe_search') ); processModal.close(); diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index 4ac2a66..32fc0b4 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -339,7 +339,7 @@ class _SearchClientsWidgetState extends State { Icon( Icons.search_rounded, size: 19, - color: versionIsGreater( + color: serverVersionIsAhead( currentVersion: serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 83029b8..72908fc 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -250,7 +250,7 @@ class _ManagementModalState extends State with SingleTickerProv return Padding( padding: const EdgeInsets.symmetric(horizontal: 24), - child: versionIsGreater( + child: serverVersionIsAhead( currentVersion: serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 575becd..5393c04 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -192,7 +192,7 @@ class _LogsWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingSettings); - final result = versionIsGreater( + final result = serverVersionIsAhead( currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' diff --git a/lib/screens/logs/logs_config_modal.dart b/lib/screens/logs/logs_config_modal.dart index 3d80a87..9af7335 100644 --- a/lib/screens/logs/logs_config_modal.dart +++ b/lib/screens/logs/logs_config_modal.dart @@ -64,7 +64,7 @@ class _LogsConfigModalWidgetState extends State { int loadStatus = 0; void loadData() async { - final result = versionIsGreater( + final result = serverVersionIsAhead( currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' @@ -89,7 +89,7 @@ class _LogsConfigModalWidgetState extends State { @override void initState() { - retentionItems = versionIsGreater( + retentionItems = serverVersionIsAhead( currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index 5a59e2e..9fc8a86 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -72,7 +72,6 @@ class _AccessSettingsWidgetState extends State with Ticker @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); -print(serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts.length); return Scaffold( body: DefaultTabController( length: 3, diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 02a9c1d..cefd757 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -81,12 +81,12 @@ class _SafeSearchSettingsScreenWidgetState extends State Date: Sat, 15 Apr 2023 02:06:33 +0200 Subject: [PATCH 034/676] Small fix --- lib/screens/clients/client_screen.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart index 277970a..e9093a7 100644 --- a/lib/screens/clients/client_screen.dart +++ b/lib/screens/clients/client_screen.dart @@ -36,6 +36,8 @@ class _ClientScreenState extends State { final Uuid uuid = const Uuid(); bool editMode = true; + bool validValues = false; + TextEditingController nameController = TextEditingController(); List selectedTags = []; @@ -68,16 +70,16 @@ class _ClientScreenState extends State { List> upstreamServers = []; - bool checkValidValues() { + void checkValidValues() { if ( nameController.text != '' && identifiersControllers.isNotEmpty && identifiersControllers[0]['controller'].text != '' ) { - return true; + setState(() => validValues = true); } else { - return false; + setState(() => validValues = false); } } @@ -94,6 +96,8 @@ class _ClientScreenState extends State { if (widget.client != null) { editMode = false; + validValues = true; + nameController.text = widget.client!.name; selectedTags = widget.client!.tags; identifiersControllers = widget.client!.ids.map((e) => { @@ -308,7 +312,7 @@ class _ClientScreenState extends State { ), actions: [ if (widget.client == null || (widget.client != null && editMode == true)) IconButton( - onPressed: checkValidValues() == true + onPressed: validValues == true ? () { createClient(); Navigator.pop(context); From 37af353cdaca5dd4322f53c46942f200dd79c0b0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 15 Apr 2023 02:19:33 +0200 Subject: [PATCH 035/676] Small fixes --- lib/screens/clients/added_list.dart | 2 +- lib/screens/clients/client_screen.dart | 20 +++++++++++++------- lib/screens/clients/search_clients.dart | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index dc9c974..922d2de 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -274,7 +274,7 @@ class _AddedListState extends State { referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true - ? widget.data[index].safeSearch!.enabled == true + ? widget.data[index].safeSearch != null && widget.data[index].safeSearch!.enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart index e9093a7..461ba42 100644 --- a/lib/screens/clients/client_screen.dart +++ b/lib/screens/clients/client_screen.dart @@ -54,7 +54,9 @@ class _ClientScreenState extends State { bool? enableSafeBrowsing; bool? enableParentalControl; bool? enableSafeSearch; - SafeSearch safeSearch = SafeSearch( + SafeSearch? safeSearch; + + final SafeSearch defaultSafeSearch = SafeSearch( enabled: false, bing: false, duckduckgo: false, @@ -109,7 +111,7 @@ class _ClientScreenState extends State { enableParentalControl = widget.client!.parentalEnabled; enableSafeBrowsing = widget.client!.safebrowsingEnabled; if (version == true) { - safeSearch = widget.client!.safeSearch!; + safeSearch = widget.client!.safeSearch; } else { enableSafeSearch = widget.client!.safesearchEnabled ?? false; @@ -175,7 +177,7 @@ class _ClientScreenState extends State { enableSafeBrowsing = false; enableParentalControl = false; enableSafeSearch = false; - safeSearch.enabled = false; + safeSearch = defaultSafeSearch; }); } else if (useGlobalSettingsFiltering == false) { @@ -186,7 +188,7 @@ class _ClientScreenState extends State { enableSafeBrowsing = null; enableParentalControl = null; enableSafeSearch = null; - safeSearch.enabled = false; + safeSearch = null; }); } } @@ -242,7 +244,7 @@ class _ClientScreenState extends State { showDialog( context: context, builder: (context) => SafeSearchModal( - safeSearch: safeSearch, + safeSearch: safeSearch ?? defaultSafeSearch, disabled: !editMode, onConfirm: (s) => setState(() => safeSearch = s) ) @@ -554,10 +556,14 @@ class _ClientScreenState extends State { padding: const EdgeInsets.only(right: 16), child: Icon( Icons.chevron_right_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, + color: useGlobalSettingsFiltering == true + ? Colors.grey + : Theme.of(context).colorScheme.onSurfaceVariant, ), ), - onTap: openSafeSearchModal, + onTap: useGlobalSettingsFiltering == false + ? () => openSafeSearchModal() + : null, ), if ( serverVersionIsAhead( diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index 32fc0b4..ce5d2bf 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -344,7 +344,7 @@ class _SearchClientsWidgetState extends State { referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true - ? clientsScreen[index].safeSearch!.enabled == true + ? clientsScreen[index].safeSearch != null && clientsScreen[index].safeSearch!.enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green From 67b41b3382b621909eca4224ca51cf42dafb12e3 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 15 Apr 2023 02:24:48 +0200 Subject: [PATCH 036/676] Removed autouptdate option on unsupported servers --- lib/screens/settings/settings.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index c8c432a..2c3221a 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -127,7 +127,7 @@ class Settings extends StatelessWidget { ) }, ), - if (serversProvider.updateAvailable.data != null) CustomListTile( + if (serversProvider.updateAvailable.data != null && serversProvider.updateAvailable.data!.canAutoupdate == true) CustomListTile( icon: Icons.system_update_rounded, title: AppLocalizations.of(context)!.updates, subtitle: AppLocalizations.of(context)!.updatesDescription, From f63ac9eb66d4ca62a5f39b1a5e5e46819a12f851 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 15 Apr 2023 02:52:23 +0200 Subject: [PATCH 037/676] Improved updater --- lib/models/update_available.dart | 6 ++--- lib/providers/servers_provider.dart | 38 +++++++++++++---------------- lib/screens/settings/settings.dart | 2 +- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/lib/models/update_available.dart b/lib/models/update_available.dart index 136a6b9..ee766e0 100644 --- a/lib/models/update_available.dart +++ b/lib/models/update_available.dart @@ -13,9 +13,9 @@ class UpdateAvailable { class UpdateAvailableData { String currentVersion; String? newVersion; - final String announcement; - final String announcementUrl; - final bool canAutoupdate; + final String? announcement; + final String? announcementUrl; + final bool? canAutoupdate; final bool disabled; String? changelog; bool? updateAvailable; diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index f448c74..c5cde45 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -533,28 +533,24 @@ class ServersProvider with ChangeNotifier { setUpdateAvailableLoadStatus(LoadStatus.loading, true); final result = await checkServerUpdates(server: server); if (result['result'] == 'success') { - try { - UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); - final gitHubResult = await getUpdateChangelog(server: server, releaseTag: data.newVersion ?? data.currentVersion); - if (gitHubResult['result'] == 'success') { - data.changelog = gitHubResult['body']; - } - data.updateAvailable = data.newVersion != null - ? data.newVersion!.contains('b') - ? compareBetaVersions( - currentVersion: data.currentVersion.replaceAll('v', ''), - newVersion: data.newVersion!.replaceAll('v', ''), - ) - : compareVersions( - currentVersion: data.currentVersion.replaceAll('v', ''), - newVersion: data.newVersion!.replaceAll('v', ''), - ) - : false; - setUpdateAvailableData(data); - setUpdateAvailableLoadStatus(LoadStatus.loaded, true); - } catch (_) { - // AUTO UPDATE NOT AVAILABLE // + UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); + final gitHubResult = await getUpdateChangelog(server: server, releaseTag: data.newVersion ?? data.currentVersion); + if (gitHubResult['result'] == 'success') { + data.changelog = gitHubResult['body']; } + data.updateAvailable = data.newVersion != null + ? data.newVersion!.contains('b') + ? compareBetaVersions( + currentVersion: data.currentVersion.replaceAll('v', ''), + newVersion: data.newVersion!.replaceAll('v', ''), + ) + : compareVersions( + currentVersion: data.currentVersion.replaceAll('v', ''), + newVersion: data.newVersion!.replaceAll('v', ''), + ) + : false; + setUpdateAvailableData(data); + setUpdateAvailableLoadStatus(LoadStatus.loaded, true); } else { setUpdateAvailableLoadStatus(LoadStatus.error, true); diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 2c3221a..c8c432a 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -127,7 +127,7 @@ class Settings extends StatelessWidget { ) }, ), - if (serversProvider.updateAvailable.data != null && serversProvider.updateAvailable.data!.canAutoupdate == true) CustomListTile( + if (serversProvider.updateAvailable.data != null) CustomListTile( icon: Icons.system_update_rounded, title: AppLocalizations.of(context)!.updates, subtitle: AppLocalizations.of(context)!.updatesDescription, From 89c1d1cfe49df8e387001b2b679f6d785f41f2ed Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 15 Apr 2023 03:07:56 +0200 Subject: [PATCH 038/676] Fixed servers list arrow animation --- lib/widgets/servers_list/servers_list.dart | 424 ++---------------- .../servers_list/servers_list_item.dart | 405 +++++++++++++++++ 2 files changed, 430 insertions(+), 399 deletions(-) create mode 100644 lib/widgets/servers_list/servers_list_item.dart diff --git a/lib/widgets/servers_list/servers_list.dart b/lib/widgets/servers_list/servers_list.dart index 9dd080b..c69f5ed 100644 --- a/lib/widgets/servers_list/servers_list.dart +++ b/lib/widgets/servers_list/servers_list.dart @@ -1,21 +1,14 @@ // ignore_for_file: use_build_context_synchronously -import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:flutter/material.dart'; import 'package:expandable/expandable.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; -import 'package:adguard_home_manager/widgets/add_server_modal.dart'; +import 'package:adguard_home_manager/widgets/servers_list/servers_list_item.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/models/app_log.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -class ServersList extends StatefulWidget { +class ServersList extends StatelessWidget { final BuildContext context; final List controllers; final Function(int) onChange; @@ -30,402 +23,35 @@ class ServersList extends StatefulWidget { }) : super(key: key); @override - State createState() => _ServersListState(); -} - -class _ServersListState extends State with SingleTickerProviderStateMixin { - late AnimationController animationController; - late Animation animation; - - @override - void initState() { - for (ExpandableController controller in widget.controllers) { - controller.addListener(() async { - await Future.delayed(const Duration(milliseconds: 200)); - if (controller.value == false) { - animationController.animateTo(0); - } - else { - animationController.animateBack(1); - } - }); - } - - animationController = AnimationController( - duration: const Duration(milliseconds: 200), - vsync: this, - ) - ..addListener(() => setState(() => {})); - animation = Tween( - begin: 0.0, - end: 0.5, - ).animate(CurvedAnimation( - parent: animationController, - curve: Curves.easeInOut - )); - - super.initState(); - } - - @override - void dispose() { - animationController.dispose(); - super.dispose(); - } - - @override - // ignore: avoid_renaming_method_parameters Widget build(BuildContext context) { final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - List servers = serversProvider.serversList; - - void showDeleteModal(Server server) async { - await Future.delayed(const Duration(seconds: 0), () => { - showDialog( - context: context, - builder: (context) => DeleteModal( - serverToDelete: server, - ), - barrierDismissible: false + + if (serversProvider.serversList.isNotEmpty) { + return ListView.builder( + controller: scrollController, + itemCount: serversProvider.serversList.length, + itemBuilder: (context, index) => ServersListItem( + expandableController: controllers[index], + server: serversProvider.serversList[index], + index: index, + onChange: onChange ) - }); - } - - void openAddServerBottomSheet({Server? server}) async { - await Future.delayed(const Duration(seconds: 0), (() => { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => AddServerModal(server: server) - )) - })); - } - - void connectToServer(Server server) async { - final ProcessModal process = ProcessModal(context: context); - process.open(AppLocalizations.of(context)!.connecting); - - final result = server.runningOnHa == true - ? await loginHA(server) - : await login(server); - - if (result['result'] == 'success') { - serversProvider.setSelectedServer(server); - - serversProvider.setServerStatusLoad(0); - final serverStatus = await getServerStatus(server); - if (serverStatus['result'] == 'success') { - serversProvider.setServerStatusData(serverStatus['data']); - serversProvider.checkServerUpdatesAvailable(server); - serversProvider.setServerStatusLoad(1); - } - else { - appConfigProvider.addLog(serverStatus['log']); - serversProvider.setServerStatusLoad(2); - } - - process.close(); - } - else { - process.close(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.cannotConnect, - color: Colors.red - ); - } - } - - void setDefaultServer(Server server) async { - final result = await serversProvider.setDefaultServer(server); - if (result == null) { - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, - color: Colors.green - ); - } - else { - appConfigProvider.addLog( - AppLog( - type: 'set_default_server', - dateTime: DateTime.now(), - message: result.toString() - ) - ); - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionDefaultFailed, - color: Colors.red - ); - } - } - - Widget leadingIcon(Server server) { - if (server.defaultServer == true) { - return Stack( - alignment: Alignment.center, - children: [ - Icon( - Icons.storage_rounded, - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null - ? Colors.green - : Colors.orange - : null, - ), - SizedBox( - width: 25, - height: 25, - child: Stack( - alignment: Alignment.bottomRight, - children: [ - Container( - padding: const EdgeInsets.all(1), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primaryContainer, - borderRadius: BorderRadius.circular(20) - ), - child: Icon( - Icons.star, - color: Theme.of(context).colorScheme.onPrimaryContainer, - size: 10, - ), - ), - ], - ), - ) - ], - ); - } - else { - return Icon( - Icons.storage_rounded, - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null - ? Colors.green - : Colors.orange - : null, - ); - } - } - - Widget topRow(Server server, int index) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Row( - children: [ - Container( - margin: const EdgeInsets.only(right: 16), - child: leadingIcon(servers[index]), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Column( - children: [ - const SizedBox(height: 3), - Text( - servers[index].name, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ) - ], - ) - ], - ), - ), - ], - ), - ), - RotationTransition( - turns: animation, - child: const Icon(Icons.keyboard_arrow_down_rounded), - ), - ], ); } - - Widget bottomRow(Server server, int index) { - return Column( - children: [ - const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - PopupMenuButton( - // color: Theme.of(context).dialogBackgroundColor, - itemBuilder: (context) => [ - PopupMenuItem( - enabled: server.defaultServer == false - ? true - : false, - onTap: server.defaultServer == false - ? (() => setDefaultServer(server)) - : null, - child: SizedBox( - child: Row( - children: [ - const Icon(Icons.star), - const SizedBox(width: 15), - Text( - server.defaultServer == true - ? AppLocalizations.of(context)!.defaultConnection - : AppLocalizations.of(context)!.setDefault, - ) - ], - ), - ) - ), - PopupMenuItem( - onTap: (() => openAddServerBottomSheet(server: server)), - child: Row( - children: [ - const Icon(Icons.edit), - const SizedBox(width: 15), - Text(AppLocalizations.of(context)!.edit) - ], - ) - ), - PopupMenuItem( - onTap: (() => showDeleteModal(server)), - child: Row( - children: [ - const Icon(Icons.delete), - const SizedBox(width: 15), - Text(AppLocalizations.of(context)!.delete) - ], - ) - ), - ] - ), - SizedBox( - child: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == servers[index].id - ? Container( - margin: const EdgeInsets.only(right: 12), - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), - decoration: BoxDecoration( - color: serversProvider.serverStatus.data != null - ? Colors.green - : Colors.orange, - borderRadius: BorderRadius.circular(30) - ), - child: Row( - children: [ - Icon( - serversProvider.serverStatus.data != null - ? Icons.check - : Icons.warning, - color: Colors.white, - ), - const SizedBox(width: 10), - Text( - serversProvider.serverStatus.data != null - ? AppLocalizations.of(context)!.connected - : AppLocalizations.of(context)!.selectedDisconnected, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ) - ], - ), - ) - : Container( - margin: const EdgeInsets.only(right: 10), - child: TextButton( - onPressed: () => connectToServer(servers[index]), - child: Text(AppLocalizations.of(context)!.connect), - ), - ), - ) - ], - ) - ], + else { + return SizedBox( + height: double.maxFinite, + child: Center( + child: Text( + AppLocalizations.of(context)!.noSavedConnections, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), ); } - - return servers.isNotEmpty ? - ListView.builder( - controller: widget.scrollController, - itemCount: servers.length, - itemBuilder: (context, index) => Container( - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: Theme.of(context).colorScheme.surfaceVariant, - width: 1 - ) - ) - ), - child: ExpandableNotifier( - controller: widget.controllers[index], - child: Column( - children: [ - Expandable( - collapsed: Material( - color: Colors.transparent, - child: InkWell( - onTap: () => widget.onChange(index), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: topRow(servers[index], index), - ), - ), - ), - expanded: Material( - color: Colors.transparent, - child: InkWell( - onTap: () => widget.onChange(index), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: Column( - children: [ - topRow(servers[index], index), - bottomRow(servers[index], index) - ], - ), - ), - ), - ) - ) - ], - ), - ), - ) - ) : SizedBox( - height: double.maxFinite, - child: Center( - child: Text( - AppLocalizations.of(context)!.noSavedConnections, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - ); } } \ No newline at end of file diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart new file mode 100644 index 0000000..919a680 --- /dev/null +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -0,0 +1,405 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:expandable/expandable.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/add_server_modal.dart'; +import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/app_log.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/models/server.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class ServersListItem extends StatefulWidget { + final ExpandableController expandableController; + final Server server; + final int index; + final void Function(int) onChange; + + const ServersListItem({ + Key? key, + required this.expandableController, + required this.server, + required this.index, + required this.onChange + }) : super(key: key); + + @override + State createState() => _ServersListItemState(); +} + +class _ServersListItemState extends State with SingleTickerProviderStateMixin { + late AnimationController animationController; + late Animation animation; + + @override + void initState() { + widget.expandableController.addListener(() async { + await Future.delayed(const Duration(milliseconds: 200)); + if (widget.expandableController.value == false) { + animationController.animateTo(0); + } + else { + animationController.animateBack(1); + } + }); + + animationController = AnimationController( + duration: const Duration(milliseconds: 200), + vsync: this, + ) + ..addListener(() => setState(() => {})); + animation = Tween( + begin: 0.0, + end: 0.5, + ).animate(CurvedAnimation( + parent: animationController, + curve: Curves.easeInOut + )); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void showDeleteModal(Server server) async { + await Future.delayed(const Duration(seconds: 0), () => { + showDialog( + context: context, + builder: (context) => DeleteModal( + serverToDelete: server, + ), + barrierDismissible: false + ) + }); + } + + void openAddServerBottomSheet({Server? server}) async { + await Future.delayed(const Duration(seconds: 0), (() => { + Navigator.push(context, MaterialPageRoute( + fullscreenDialog: true, + builder: (BuildContext context) => AddServerModal(server: server) + )) + })); + } + + void connectToServer(Server server) async { + final ProcessModal process = ProcessModal(context: context); + process.open(AppLocalizations.of(context)!.connecting); + + final result = server.runningOnHa == true + ? await loginHA(server) + : await login(server); + + if (result['result'] == 'success') { + serversProvider.setSelectedServer(server); + + serversProvider.setServerStatusLoad(0); + final serverStatus = await getServerStatus(server); + if (serverStatus['result'] == 'success') { + serversProvider.setServerStatusData(serverStatus['data']); + serversProvider.checkServerUpdatesAvailable(server); + serversProvider.setServerStatusLoad(1); + } + else { + appConfigProvider.addLog(serverStatus['log']); + serversProvider.setServerStatusLoad(2); + } + + process.close(); + } + else { + process.close(); + appConfigProvider.addLog(result['log']); + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.cannotConnect, + color: Colors.red + ); + } + } + + void setDefaultServer(Server server) async { + final result = await serversProvider.setDefaultServer(server); + if (result == null) { + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, + color: Colors.green + ); + } + else { + appConfigProvider.addLog( + AppLog( + type: 'set_default_server', + dateTime: DateTime.now(), + message: result.toString() + ) + ); + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionDefaultFailed, + color: Colors.red + ); + } + } + + Widget leadingIcon(Server server) { + if (server.defaultServer == true) { + return Stack( + alignment: Alignment.center, + children: [ + Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? serversProvider.serverStatus.data != null + ? Colors.green + : Colors.orange + : null, + ), + SizedBox( + width: 25, + height: 25, + child: Stack( + alignment: Alignment.bottomRight, + children: [ + Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(20) + ), + child: Icon( + Icons.star, + color: Theme.of(context).colorScheme.onPrimaryContainer, + size: 10, + ), + ), + ], + ), + ) + ], + ); + } + else { + return Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? serversProvider.serverStatus.data != null + ? Colors.green + : Colors.orange + : null, + ); + } + } + + Widget topRow(Server server, int index) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 16), + child: leadingIcon(server), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Column( + children: [ + const SizedBox(height: 3), + Text( + server.name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ) + ], + ), + ), + ], + ), + ), + RotationTransition( + turns: animation, + child: const Icon(Icons.keyboard_arrow_down_rounded), + ), + ], + ); + } + + Widget bottomRow(Server server, int index) { + return Column( + children: [ + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + PopupMenuButton( + // color: Theme.of(context).dialogBackgroundColor, + itemBuilder: (context) => [ + PopupMenuItem( + enabled: server.defaultServer == false + ? true + : false, + onTap: server.defaultServer == false + ? (() => setDefaultServer(server)) + : null, + child: SizedBox( + child: Row( + children: [ + const Icon(Icons.star), + const SizedBox(width: 15), + Text( + server.defaultServer == true + ? AppLocalizations.of(context)!.defaultConnection + : AppLocalizations.of(context)!.setDefault, + ) + ], + ), + ) + ), + PopupMenuItem( + onTap: (() => openAddServerBottomSheet(server: server)), + child: Row( + children: [ + const Icon(Icons.edit), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.edit) + ], + ) + ), + PopupMenuItem( + onTap: (() => showDeleteModal(server)), + child: Row( + children: [ + const Icon(Icons.delete), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.delete) + ], + ) + ), + ] + ), + SizedBox( + child: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? Container( + margin: const EdgeInsets.only(right: 12), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + decoration: BoxDecoration( + color: serversProvider.serverStatus.data != null + ? Colors.green + : Colors.orange, + borderRadius: BorderRadius.circular(30) + ), + child: Row( + children: [ + Icon( + serversProvider.serverStatus.data != null + ? Icons.check + : Icons.warning, + color: Colors.white, + ), + const SizedBox(width: 10), + Text( + serversProvider.serverStatus.data != null + ? AppLocalizations.of(context)!.connected + : AppLocalizations.of(context)!.selectedDisconnected, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w500 + ), + ) + ], + ), + ) + : Container( + margin: const EdgeInsets.only(right: 10), + child: TextButton( + onPressed: () => connectToServer(server), + child: Text(AppLocalizations.of(context)!.connect), + ), + ), + ) + ], + ) + ], + ); + } + + + return Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Theme.of(context).colorScheme.surfaceVariant, + width: 1 + ) + ) + ), + child: ExpandableNotifier( + controller: widget.expandableController, + child: Column( + children: [ + Expandable( + collapsed: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => widget.onChange(widget.index), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: topRow(widget.server, widget.index), + ), + ), + ), + expanded: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => widget.onChange(widget.index), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Column( + children: [ + topRow(widget.server, widget.index), + bottomRow(widget.server, widget.index) + ], + ), + ), + ), + ) + ) + ], + ), + ), + ); + } +} \ No newline at end of file From 554d6616efba872a3605bf8d781bf3e8e2e3e8af Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 15 Apr 2023 03:19:36 +0200 Subject: [PATCH 039/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 54a98a5..558cd0e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.13.1+50 +version: 1.14.0+51 environment: sdk: '>=2.18.1 <3.0.0' From 661396d5f9f4f3a1c13e9b84a13a41082779163a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 15 Apr 2023 05:01:30 +0200 Subject: [PATCH 040/676] Fixed small issue general protection toggle --- lib/screens/home/management_modal.dart | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 72908fc..e36fbc7 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -147,13 +147,13 @@ class _ManagementModalState extends State with SingleTickerProv } Widget mainSwitch() { - Widget topRow(bool legacyMode) { + Widget topRow({required bool legacyMode}) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ - if (legacyMode == true) ...[ + if (legacyMode == false) ...[ RotationTransition( turns: animation, child: Icon( @@ -189,7 +189,7 @@ class _ManagementModalState extends State with SingleTickerProv value: serversProvider.serverStatus.data!.generalEnabled, onChanged: serversProvider.protectionsManagementProcess.contains('general') == false ? (value) { - if (value == false) { + if (value == false && expandableController.expanded == true && legacyMode == false) { expandableController.toggle(); } updateBlocking( @@ -211,35 +211,35 @@ class _ManagementModalState extends State with SingleTickerProv children: [ ActionChip( label: Text(AppLocalizations.of(context)!.seconds(30)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true ? () => disableWithCountdown(29000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.minute(1)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true ? () => disableWithCountdown(59000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.minutes(10)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true ? () => disableWithCountdown(599000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.hour(1)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true ? () => disableWithCountdown(3599000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.hours(24)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false + onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true ? () => disableWithCountdown(86399000) : null, ), @@ -261,7 +261,7 @@ class _ManagementModalState extends State with SingleTickerProv color: Colors.transparent, borderRadius: BorderRadius.circular(28), child: InkWell( - onTap: serversProvider.serverStatus.data!.generalEnabled == true + onTap: serversProvider.serverStatus.data!.generalEnabled == true && !serversProvider.protectionsManagementProcess.contains('general') ? () => expandableController.toggle() : null, borderRadius: BorderRadius.circular(28), @@ -279,10 +279,10 @@ class _ManagementModalState extends State with SingleTickerProv animationDuration: Duration(milliseconds: 200), fadeCurve: Curves.ease ), - collapsed: topRow(true), + collapsed: topRow(legacyMode: false), expanded: Column( children: [ - topRow(true), + topRow(legacyMode: false), bottomRow(), const SizedBox(height: 8) ], @@ -311,7 +311,7 @@ class _ManagementModalState extends State with SingleTickerProv borderRadius: BorderRadius.circular(28), color: Theme.of(context).primaryColor.withOpacity(0.1) ), - child: topRow(false) + child: topRow(legacyMode: true) ), ), ) From 6ba9eecf8ea1799acbd57ba60e04ca32abe583d4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 15 Apr 2023 05:04:29 +0200 Subject: [PATCH 041/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 558cd0e..78908b2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.14.0+51 +version: 1.14.1+52 environment: sdk: '>=2.18.1 <3.0.0' From e53f4f59728af159b783c3c38ee6807149d27d64 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 29 Apr 2023 00:24:30 +0200 Subject: [PATCH 042/676] Changed queries and added macOS support --- .metadata | 25 +- assets/icon/icon-macos.png | Bin 0 -> 422255 bytes ios/Runner.xcodeproj/project.pbxproj | 6 +- lib/base.dart | 15 +- lib/main.dart | 15 +- lib/providers/app_config_provider.dart | 152 ++-- lib/providers/servers_provider.dart | 68 +- lib/services/{ => db}/database.dart | 0 lib/services/db/queries.dart | 114 +++ macos/.gitignore | 7 + macos/Flutter/Flutter-Debug.xcconfig | 2 + macos/Flutter/Flutter-Release.xcconfig | 2 + macos/Flutter/GeneratedPluginRegistrant.swift | 22 + macos/Podfile | 40 ++ macos/Podfile.lock | 76 ++ macos/Runner.xcodeproj/project.pbxproj | 650 ++++++++++++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 87 +++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + macos/Runner/AppDelegate.swift | 9 + .../AppIcon.appiconset/Contents.json | 68 ++ .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 414551 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 4705 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 515 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 14960 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 938 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 76128 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 1956 bytes macos/Runner/Base.lproj/MainMenu.xib | 343 +++++++++ macos/Runner/Configs/AppInfo.xcconfig | 14 + macos/Runner/Configs/Debug.xcconfig | 2 + macos/Runner/Configs/Release.xcconfig | 2 + macos/Runner/Configs/Warnings.xcconfig | 13 + macos/Runner/DebugProfile.entitlements | 14 + macos/Runner/Info.plist | 32 + macos/Runner/MainFlutterWindow.swift | 15 + macos/Runner/Release.entitlements | 10 + pubspec.lock | 53 +- pubspec.yaml | 12 +- 40 files changed, 1680 insertions(+), 214 deletions(-) create mode 100755 assets/icon/icon-macos.png rename lib/services/{ => db}/database.dart (100%) create mode 100644 lib/services/db/queries.dart create mode 100644 macos/.gitignore create mode 100644 macos/Flutter/Flutter-Debug.xcconfig create mode 100644 macos/Flutter/Flutter-Release.xcconfig create mode 100644 macos/Flutter/GeneratedPluginRegistrant.swift create mode 100644 macos/Podfile create mode 100644 macos/Podfile.lock create mode 100644 macos/Runner.xcodeproj/project.pbxproj create mode 100644 macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 macos/Runner/AppDelegate.swift create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 macos/Runner/Base.lproj/MainMenu.xib create mode 100644 macos/Runner/Configs/AppInfo.xcconfig create mode 100644 macos/Runner/Configs/Debug.xcconfig create mode 100644 macos/Runner/Configs/Release.xcconfig create mode 100644 macos/Runner/Configs/Warnings.xcconfig create mode 100644 macos/Runner/DebugProfile.entitlements create mode 100644 macos/Runner/Info.plist create mode 100644 macos/Runner/MainFlutterWindow.swift create mode 100644 macos/Runner/Release.entitlements diff --git a/.metadata b/.metadata index e27f5cc..b5d8c1f 100644 --- a/.metadata +++ b/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled. version: - revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf channel: stable project_type: app @@ -13,26 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - - platform: android - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - - platform: ios - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - - platform: linux - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf + base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf - platform: macos - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - - platform: web - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - - platform: windows - create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 - base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1 + create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf + base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf # User provided section diff --git a/assets/icon/icon-macos.png b/assets/icon/icon-macos.png new file mode 100755 index 0000000000000000000000000000000000000000..54f7bda4a1028f0f34720f74cf0e2abceb0f4a25 GIT binary patch literal 422255 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%0AmidQWxFzTvLVm4iej2u+t+z% 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 Rfk{i;O=x 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 literal 0 HcmV?d00001 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 1ffa568..7d212ec 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -365,7 +365,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.adguardHomeManager; + PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguard_home_manager; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -494,7 +494,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.adguardHomeManager; + PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguard_home_manager; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -517,7 +517,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.adguardHomeManager; + PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguard_home_manager; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/lib/base.dart b/lib/base.dart index 327b6ca..509df8e 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -1,6 +1,7 @@ // ignore_for_file: use_build_context_synchronously, depend_on_referenced_packages import 'dart:async'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; @@ -53,12 +54,14 @@ class _BaseState extends State with WidgetsBindingObserver { } Future checkInstallationSource() async { - Source installationSource = await StoreChecker.getSource; - if (installationSource != Source.IS_INSTALLED_FROM_PLAY_STORE) { - final result = await checkAppUpdatesGitHub(); - if (result['result'] == 'success') { - if (updateExists(widget.appConfigProvider.getAppInfo!.version, result['body'].tagName)) { - return result['body']; + if (Platform.isAndroid) { + Source installationSource = await StoreChecker.getSource; + if (installationSource != Source.IS_INSTALLED_FROM_PLAY_STORE) { + final result = await checkAppUpdatesGitHub(); + if (result['result'] == 'success') { + if (updateExists(widget.appConfigProvider.getAppInfo!.version, result['body'].tagName)) { + return result['body']; + } } } } diff --git a/lib/main.dart b/lib/main.dart index 5ef8610..94a44e9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,18 +7,20 @@ import 'package:provider/provider.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:sqflite_common_ffi/sqflite_ffi.dart'; +import 'package:window_size/window_size.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/base.dart'; import 'package:adguard_home_manager/classes/http_override.dart'; -import 'package:adguard_home_manager/services/database.dart'; +import 'package:adguard_home_manager/services/db/database.dart'; import 'package:adguard_home_manager/constants/colors.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/config/theme.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; void main() async { @@ -26,6 +28,15 @@ void main() async { SystemChrome.setPreferredOrientations( [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown] ); + + if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { + setWindowMinSize(const Size(500, 500)); + } + + if (Platform.isWindows || Platform.isLinux) { + sqfliteFfiInit(); + databaseFactory = databaseFactoryFfi; + } AppConfigProvider appConfigProvider = AppConfigProvider(); ServersProvider serversProvider = ServersProvider(); diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 262a448..1952d9b 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -4,6 +4,7 @@ import 'package:flutter/scheduler.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sqflite/sqlite_api.dart'; +import 'package:adguard_home_manager/services/db/queries.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/models/app_log.dart'; @@ -160,7 +161,11 @@ class AppConfigProvider with ChangeNotifier { } Future setOverrideSslCheck(bool status) async { - final updated = await _updateOverrideSslCheck(status == true ? 1 : 0); + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'overrideSslCheck', + value: status == true ? 1 : 0 + ); if (updated == true) { _overrideSslCheck = status == true ? 1 : 0; notifyListeners(); @@ -172,7 +177,11 @@ class AppConfigProvider with ChangeNotifier { } Future setHideZeroValues(bool status) async { - final updated = await _updateSetHideZeroValues(status == true ? 1 : 0); + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'overrideSslCheck', + value: status == true ? 1 : 0 + ); if (updated == true) { _hideZeroValues = status == true ? 1 : 0; notifyListeners(); @@ -184,7 +193,11 @@ class AppConfigProvider with ChangeNotifier { } Future setShowNameTimeLogs(bool status) async { - final updated = await _updateShowNameTimeLogsDb(status == true ? 1 : 0); + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'showNameTimeLogs', + value: status == true ? 1 : 0 + ); if (updated == true) { _showNameTimeLogs = status == true ? 1 : 0; notifyListeners(); @@ -196,7 +209,11 @@ class AppConfigProvider with ChangeNotifier { } Future setSelectedTheme(int value) async { - final updated = await _updateThemeDb(value); + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'theme', + value: value + ); if (updated == true) { _selectedTheme = value; notifyListeners(); @@ -208,7 +225,11 @@ class AppConfigProvider with ChangeNotifier { } Future setUseDynamicColor(bool value) async { - final updated = await _updateDynamicColorDb(value == true ? 1 : 0); + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'useDynamicColor', + value: value == true ? 1 : 0 + ); if (updated == true) { _useDynamicColor = value; notifyListeners(); @@ -220,7 +241,11 @@ class AppConfigProvider with ChangeNotifier { } Future setUseThemeColorForStatus(bool value) async { - final updated = await _updateUseThemeColorForStatusDb(value == true ? 1 : 0); + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'useThemeColorForStatus', + value: value == true ? 1 : 0 + ); if (updated == true) { _useThemeColorForStatus = value; notifyListeners(); @@ -232,7 +257,11 @@ class AppConfigProvider with ChangeNotifier { } Future setStaticColor(int value) async { - final updated = await _updateStaticColorDb(value); + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'staticColor', + value: value + ); if (updated == true) { _staticColor = value; notifyListeners(); @@ -244,109 +273,12 @@ class AppConfigProvider with ChangeNotifier { } Future setDoNotRememberVersion(String value) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE appConfig SET doNotRememberVersion = "$value"', - ); - _doNotRememberVersion = value; - notifyListeners(); - return true; - }); - } catch (e) { - return false; - } - } - - Future _updateThemeDb(int value) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE appConfig SET theme = $value', - ); - return true; - }); - } catch (e) { - return false; - } - } - - Future _updateDynamicColorDb(int value) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE appConfig SET useDynamicColor = $value', - ); - return true; - }); - } catch (e) { - return false; - } - } - - Future _updateUseThemeColorForStatusDb(int value) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE appConfig SET useThemeColorForStatus = $value', - ); - return true; - }); - } catch (e) { - return false; - } - } - - Future _updateStaticColorDb(int value) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE appConfig SET staticColor = $value', - ); - return true; - }); - } catch (e) { - return false; - } - } - - Future _updateOverrideSslCheck(int value) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE appConfig SET overrideSslCheck = $value', - ); - return true; - }); - } catch (e) { - return false; - } - } - - Future _updateSetHideZeroValues(int value) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE appConfig SET hideZeroValues = $value', - ); - return true; - }); - } catch (e) { - return false; - } - } - - Future _updateShowNameTimeLogsDb(int value) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE appConfig SET showNameTimeLogs = $value', - ); - return true; - }); - } catch (e) { - return false; - } + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'doNotRememberVersion', + value: value + ); + return updated; } void saveFromDb(Database dbInstance, Map dbData) { diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index c5cde45..fd0bd58 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -7,14 +7,15 @@ import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; -import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/server.dart'; +import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; +import 'package:adguard_home_manager/services/db/queries.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -249,7 +250,7 @@ class ServersProvider with ChangeNotifier { } Future createServer(Server server) async { - final saved = await saveServerIntoDb(server); + final saved = await saveServerQuery(_dbInstance!, server); if (saved == null) { if (server.defaultServer == true) { final defaultServer = await setDefaultServer(server); @@ -274,7 +275,7 @@ class ServersProvider with ChangeNotifier { } Future setDefaultServer(Server server) async { - final updated = await setDefaultServerDb(server.id); + final updated = await setDefaultServerQuery(_dbInstance!, server.id); if (updated == null) { List newServers = _serversList.map((s) { if (s.id == server.id) { @@ -296,7 +297,7 @@ class ServersProvider with ChangeNotifier { } Future editServer(Server server) async { - final result = await editServerDb(server); + final result = await editServerQuery(_dbInstance!, server); if (result == null) { List newServers = _serversList.map((s) { if (s.id == server.id) { @@ -316,7 +317,7 @@ class ServersProvider with ChangeNotifier { } Future removeServer(Server server) async { - final result = await removeFromDb(server.id); + final result = await removeServerQuery(_dbInstance!, server.id); if (result == true) { _selectedServer = null; List newServers = _serversList.where((s) => s.id != server.id).toList(); @@ -472,63 +473,6 @@ class ServersProvider with ChangeNotifier { } } - Future saveServerIntoDb(Server server) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawInsert( - 'INSERT INTO servers (id, name, connectionMethod, domain, path, port, user, password, defaultServer, authToken, runningOnHa) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - [server.id, server.name, server.connectionMethod, server.domain, server.path, server.port, server.user, server.password, server.defaultServer, server.authToken, convertFromBoolToInt(server.runningOnHa)] - ); - return null; - }); - } catch (e) { - return e; - } - } - - Future editServerDb(Server server) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE servers SET name = ?, connectionMethod = ?, domain = ?, path = ?, port = ?, user = ?, password = ?, authToken = ?, runningOnHa = ? WHERE id = "${server.id}"', - [server.name, server.connectionMethod, server.domain, server.path, server.port, server.user, server.password, server.authToken, server.runningOnHa] - ); - return null; - }); - } catch (e) { - return e; - } - } - - Future removeFromDb(String id) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawDelete( - 'DELETE FROM servers WHERE id = "$id"', - ); - return true; - }); - } catch (e) { - return false; - } - } - - Future setDefaultServerDb(String id) async { - try { - return await _dbInstance!.transaction((txn) async { - await txn.rawUpdate( - 'UPDATE servers SET defaultServer = 0 WHERE defaultServer = 1', - ); - await txn.rawUpdate( - 'UPDATE servers SET defaultServer = 1 WHERE id = "$id"', - ); - return null; - }); - } catch (e) { - return e; - } - } - void checkServerUpdatesAvailable(Server server) async { setUpdateAvailableLoadStatus(LoadStatus.loading, true); final result = await checkServerUpdates(server: server); diff --git a/lib/services/database.dart b/lib/services/db/database.dart similarity index 100% rename from lib/services/database.dart rename to lib/services/db/database.dart diff --git a/lib/services/db/queries.dart b/lib/services/db/queries.dart new file mode 100644 index 0000000..4b59427 --- /dev/null +++ b/lib/services/db/queries.dart @@ -0,0 +1,114 @@ +import 'package:sqflite/sqflite.dart'; + +import 'package:adguard_home_manager/functions/conversions.dart'; +import 'package:adguard_home_manager/models/server.dart'; + +Future saveServerQuery(Database db, Server server) async { + try { + return await db.transaction((txn) async { + await txn.insert( + 'servers', + { + 'id': server.id, + 'name': server.name, + 'connectionMethod': server.connectionMethod, + 'domain': server.domain, + 'path': server.path, + 'port': server.port, + 'user': server.user, + 'password': server.password, + 'defaultServer': server.defaultServer, + 'authToken': server.authToken, + 'runningOnHa': convertFromBoolToInt(server.runningOnHa) + } + ); + return null; + }); + } catch (e) { + return e; + } +} + +Future editServerQuery(Database db, Server server) async { + try { + return await db.transaction((txn) async { + await txn.update( + 'servers', + { + 'id': server.id, + 'name': server.name, + 'connectionMethod': server.connectionMethod, + 'domain': server.domain, + 'path': server.path, + 'port': server.port, + 'user': server.user, + 'password': server.password, + 'defaultServer': server.defaultServer, + 'authToken': server.authToken, + 'runningOnHa': convertFromBoolToInt(server.runningOnHa) + }, + where: 'id = ?', + whereArgs: [server.id] + ); + return null; + }); + } catch (e) { + return e; + } +} + + +Future removeServerQuery(Database db, String id) async { + try { + return await db.transaction((txn) async { + await txn.delete( + 'servers', + where: 'id = ?', + whereArgs: [id] + ); + return true; + }); + } catch (e) { + return false; + } +} + +Future setDefaultServerQuery(Database db, String id) async { + try { + return await db.transaction((txn) async { + await txn.update( + 'servers', + {'defaultServer': '0'}, + where: 'defaultServer = ?', + whereArgs: [1] + ); + await txn.update( + 'servers', + {'defaultServer': '1'}, + where: 'id = ?', + whereArgs: [id] + ); + return null; + }); + } catch (e) { + return e; + } +} + +Future updateConfigQuery({ + required Database db, + required String column, + required dynamic value +}) async { + try { + return await db.transaction((txn) async { + await txn.update( + 'appConfig', + { column: value }, + ); + return true; + }); + } catch (e) { + return false; + } +} \ No newline at end of file diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 0000000..746adbb --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..4b81f9b --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..5caa9d1 --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..b4f5f0d --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,22 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import device_info_plus_macos +import dynamic_color +import package_info_plus_macos +import sqflite +import sqlite3_flutter_libs +import window_size + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) + FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) + WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin")) +} diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000..049abe2 --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,40 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/macos/Podfile.lock b/macos/Podfile.lock new file mode 100644 index 0000000..338e2e2 --- /dev/null +++ b/macos/Podfile.lock @@ -0,0 +1,76 @@ +PODS: + - device_info_plus_macos (0.0.1): + - FlutterMacOS + - dynamic_color (0.0.2): + - FlutterMacOS + - FlutterMacOS (1.0.0) + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) + - package_info_plus_macos (0.0.1): + - FlutterMacOS + - sqflite (0.0.2): + - FlutterMacOS + - FMDB (>= 2.7.5) + - sqlite3 (3.41.0): + - sqlite3/common (= 3.41.0) + - sqlite3/common (3.41.0) + - sqlite3/fts5 (3.41.0): + - sqlite3/common + - sqlite3/perf-threadsafe (3.41.0): + - sqlite3/common + - sqlite3/rtree (3.41.0): + - sqlite3/common + - sqlite3_flutter_libs (0.0.1): + - FlutterMacOS + - sqlite3 (~> 3.41.0) + - sqlite3/fts5 + - sqlite3/perf-threadsafe + - sqlite3/rtree + - window_size (0.0.2): + - FlutterMacOS + +DEPENDENCIES: + - device_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus_macos/macos`) + - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) + - FlutterMacOS (from `Flutter/ephemeral`) + - package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`) + - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) + - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) + - window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`) + +SPEC REPOS: + trunk: + - FMDB + - sqlite3 + +EXTERNAL SOURCES: + device_info_plus_macos: + :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus_macos/macos + dynamic_color: + :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos + FlutterMacOS: + :path: Flutter/ephemeral + package_info_plus_macos: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos + sqflite: + :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos + sqlite3_flutter_libs: + :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos + window_size: + :path: Flutter/ephemeral/.symlinks/plugins/window_size/macos + +SPEC CHECKSUMS: + device_info_plus_macos: 1ad388a1ef433505c4038e7dd9605aadd1e2e9c7 + dynamic_color: 394d6a888650f8534e029b27d2f8bc5c64e44008 + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + package_info_plus_macos: f010621b07802a241d96d01876d6705f15e77c1c + sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea + sqlite3: d31b2b69d59bd1b4ab30e5c92eb18fd8e82fa392 + sqlite3_flutter_libs: f20746e4a0245afbee4f20d9afc0072ebff7cc26 + window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 + +PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 + +COCOAPODS: 1.11.2 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a91bd3f --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,650 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + E73513DE6359E03D97EE7354 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D05500669291AB89B123249 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0C04B50F31022114B20541C8 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 2B20822A5E5ADA2133261EFB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* My Server Status.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "My Server Status.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 7D05500669291AB89B123249 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + 985E47E8D393FC1DF77CB4F3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E73513DE6359E03D97EE7354 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 46371A716FC111389EADDE5D /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* My Server Status.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + 46371A716FC111389EADDE5D /* Pods */ = { + isa = PBXGroup; + children = ( + 2B20822A5E5ADA2133261EFB /* Pods-Runner.debug.xcconfig */, + 985E47E8D393FC1DF77CB4F3 /* Pods-Runner.release.xcconfig */, + 0C04B50F31022114B20541C8 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 7D05500669291AB89B123249 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 7C0020C10EF81232492FC538 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + CC375DDE73754317056A739B /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* My Server Status.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 7C0020C10EF81232492FC538 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + CC375DDE73754317056A739B /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 52; + DEVELOPMENT_TEAM = 38Z3B9TJTR; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MARKETING_VERSION = 1.14.1; + PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; + PRODUCT_NAME = "My Server Status"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 52; + DEVELOPMENT_TEAM = 38Z3B9TJTR; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MARKETING_VERSION = 1.14.1; + PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; + PRODUCT_NAME = "My Server Status"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 52; + DEVELOPMENT_TEAM = 38Z3B9TJTR; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MARKETING_VERSION = 1.14.1; + PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; + PRODUCT_NAME = "My Server Status"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..85b0db9 --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..d53ef64 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..96d3fee --- /dev/null +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "info": { + "version": 1, + "author": "xcode" + }, + "images": [ + { + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" + }, + { + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" + }, + { + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" + }, + { + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" + }, + { + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" + }, + { + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" + }, + { + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" + }, + { + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" + }, + { + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" + }, + { + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" + } + ] +} \ No newline at end of file diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..23f69c7f2b91ba82eb71646e0a40c145c1767b4e GIT binary patch literal 414551 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%0Av$#x(xI)-?8+*zSQ+z0Qh1T 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 literal 0 HcmV?d00001 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..d033f2d678a3c7f50ff690d1fd883ecfcb980454 GIT binary patch literal 4705 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 FV1hci=*$2B literal 0 HcmV?d00001 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..6eb2156ae33306b8f22e059a48234cecb9f36355 GIT binary patch literal 14960 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 V0QC9Cr;-%#LsCJaTFfZ$e*iSv>xKXT literal 0 HcmV?d00001 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000000000000000000000000000000000000..cc4f25caf52a17be52676661f4cbb263a0bfd55f GIT binary patch literal 938 zcmV;b16BNqP)-XonZEh-Pw)p{81ZgR1ndyUXNg;`pMJ1SE_7F%>(L*8hQbq_GS%Hd@ zs6_PA$68C8FZIxeUp-j(5vZxGny$|6&fRsH*_|2P#juAC9QMw=_nh;abI#1(@xlg+ z*M9)vh3;k{H2NTZc$jJl)p)9Ek318{h@;w1wU%o8@`MGGmztyjG@F7bK*$|BEcYm= zycntGQLUz6=YeZ2|x%rOVxe1ZkX^fWC7@EJk5gp0PYAM zLmDcEL+zGz{ijU;DfIr13KS8JkBgZvVJSOj_?ab zvH3ox7w1+7a4NBL20&H;hz``D>0l|ghZr1lso_R+WS67RRD+SZDP;go0f4NMfgQRi zG}7P(|4^5;L~R6~l*Y12QLSjbl#h8-V7VGMsz!5YL7_xCtQ9 z1Eooaa4qEs)G8Ib{y08_+Rv}hH8$X=cVvJTX#CqXddXolfn0*xmoLPw9>gyS{@#N7mZ4dsK#Wovf%J~Pe$T*RaIfWT;%J{lSH ziFiBQi>jV>nuU2-mzIzjmB`jaW>UVKn%u4T052-qjJLB+BCquZ`X+|iTzEhTn^V~v z)d4NxOSuPx?*X=3049*=5IvseSK`$3d+fSCuZ+#Ph{PkUTmr($7`aYu(;D!i;3^w? zYa~u~M6LuL{TE1=MKZ96K)Ih>0c7enH9xBmNLrYUyBVMr;H0Rpm>QUhVcll3nGqtY zv2zCcDWTCb*J~7x^veTqq>d8iNgA%#NsXXR9)OTG3Q>*qKbEgZHH#q!z)j8a5d68_ zM3q0idj4S|a0}aq34iBp+_d=ECIXnLeYrAhgW%}=H|5{@HrxpL11idmk&VTc{r~^~ M07*qoM6N<$f|n+`asU7T literal 0 HcmV?d00001 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000000000000000000000000000000000000..cde1401e1262960fced044fc48a3c1eae026e2a9 GIT binary patch literal 76128 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í?a}nFKOMpde#Zkn|F`jt{#lZ)Qp73} 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 + + + + + + + + + + + + + + + + + + + + + +

+ + + + - + - - + + - + + diff --git a/pubspec.lock b/pubspec.lock index fd67c77..2a10f2b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -41,22 +41,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" - bottom_inset_observer: - dependency: transitive - description: - name: bottom_inset_observer - sha256: cbfb01e0e07cc4922052701786d5e607765a6f54e1844f41061abf8744519a7d - url: "https://pub.dev" - source: hosted - version: "3.1.0" - bottom_sheet: - dependency: "direct main" - description: - name: bottom_sheet - sha256: "7a3d4a1515eba91a7d9e1359e49416147de339889170fc879a8b905d27958c94" - url: "https://pub.dev" - source: hosted - version: "3.1.2" characters: dependency: transitive description: @@ -181,10 +165,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: "37a15576f5a0bfd5555b613cf20ea3bd379607cf88d457374a16032f4e942174" + sha256: bbebb1b7ebed819e0ec83d4abdc2a8482d934f6a85289ffc1c6acf7589fa2aad url: "https://pub.dev" source: hosted - version: "1.5.4" + version: "1.6.3" equatable: dependency: transitive description: @@ -442,50 +426,18 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: f62d7253edc197fe3c88d7c2ddab82d68f555e778d55390ccc3537eca8e8d637 + sha256: "10259b111176fba5c505b102e3a5b022b51dd97e30522e906d6922c745584745" url: "https://pub.dev" source: hosted - version: "1.4.3+1" - package_info_plus_linux: - dependency: transitive - description: - name: package_info_plus_linux - sha256: "04b575f44233d30edbb80a94e57cad9107aada334fc02aabb42b6becd13c43fc" - url: "https://pub.dev" - source: hosted - version: "1.0.5" - package_info_plus_macos: - dependency: transitive - description: - name: package_info_plus_macos - sha256: a2ad8b4acf4cd479d4a0afa5a74ea3f5b1c7563b77e52cc32b3ee6956d5482a6 - url: "https://pub.dev" - source: hosted - version: "1.3.0" + version: "3.1.2" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: f7a0c8f1e7e981bc65f8b64137a53fd3c195b18d429fba960babc59a5a1c7ae8 + sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6" url: "https://pub.dev" source: hosted - version: "1.0.2" - package_info_plus_web: - dependency: transitive - description: - name: package_info_plus_web - sha256: f0829327eb534789e0a16ccac8936a80beed4e2401c4d3a74f3f39094a822d3b - url: "https://pub.dev" - source: hosted - version: "1.0.6" - package_info_plus_windows: - dependency: transitive - description: - name: package_info_plus_windows - sha256: "79524f11c42dd9078b96d797b3cf79c0a2883a50c4920dc43da8562c115089bc" - url: "https://pub.dev" - source: hosted - version: "2.1.0" + version: "2.0.1" path: dependency: transitive description: @@ -615,10 +567,10 @@ packages: dependency: "direct main" description: name: store_checker - sha256: "0bb9b67fe3c9b0545918ca8621983ab830a1b242eef12ac19b17abac56d452b8" + sha256: "9a08c82715fc72b8ef3520b18be98715e95e623ca6dc9693451606c276062b63" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" stream_channel: dependency: transitive description: @@ -790,4 +742,4 @@ packages: version: "3.1.1" sdks: dart: ">=2.19.0 <3.0.0" - flutter: ">=3.3.0" + flutter: ">=3.4.0-17.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index 6d6f8ce..900ee58 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,10 +38,10 @@ dependencies: cupertino_icons: ^1.0.2 flutter_localizations: sdk: flutter - intl: ^0.17.0 + intl: any provider: ^6.0.3 sqflite: ^2.2.5 - package_info_plus: ^1.4.3+1 + package_info_plus: ^3.1.2 flutter_displaymode: ^0.4.0 dynamic_color: ^1.5.4 animations: ^2.0.5 @@ -51,9 +51,8 @@ dependencies: fl_chart: ^0.55.2 flutter_web_browser: ^0.17.1 flutter_svg: ^1.1.5 - bottom_sheet: ^3.1.2 percent_indicator: ^4.2.2 - store_checker: ^1.1.0 + store_checker: ^1.2.0 flutter_markdown: ^0.6.14 markdown: ^7.0.2 html: ^0.15.2 From d628e56248917083ecf9364c95ea0c3685bf8667 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 20:35:54 +0200 Subject: [PATCH 078/676] Fixed log details screen client mobile --- lib/screens/clients/logs_list_client.dart | 28 +++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/logs_list_client.dart index 91b8424..e2c0c27 100644 --- a/lib/screens/clients/logs_list_client.dart +++ b/lib/screens/clients/logs_list_client.dart @@ -111,6 +111,8 @@ class _LogsListClientState extends State { @override Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + if (widget.ip != previousIp) { setState(() => loadStatus = 0); if (scrollController.hasClients) scrollController.animateTo(0, duration: const Duration(milliseconds: 1), curve: Curves.ease); @@ -165,13 +167,25 @@ class _LogsListClientState extends State { index: index, length: logsData!.data.length, useAlwaysNormalTile: true, - onLogTap: (log) => showDialog( - context: context, - builder: (context) => LogDetailsScreen( - log: log, - dialog: true - ) - ) + onLogTap: (log) => { + if (width > 700) { + showDialog( + context: context, + builder: (context) => LogDetailsScreen( + log: log, + dialog: true + ) + ) + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false + ) + )) + } + } ); } } From 27ffa75d63ff13a24cc294e072dd8d23b9d3ba1b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 22:38:37 +0200 Subject: [PATCH 079/676] Added some context menus on desktop --- lib/functions/get_filtered_status.dart | 39 ++ lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/main.dart | 6 +- lib/models/menu_option.dart | 15 + lib/screens/clients/active_client_tile.dart | 157 ++++--- lib/screens/clients/added_client_tile.dart | 405 ++++++++++-------- lib/screens/clients/logs_list_client.dart | 102 +++-- .../filters/filters_triple_column.dart | 58 ++- lib/screens/home/home.dart | 6 +- lib/screens/home/top_items.dart | 42 +- lib/screens/home/top_items_options_modal.dart | 84 ---- lib/screens/logs/log_tile.dart | 47 +- lib/screens/top_items/top_items.dart | 142 +++--- lib/screens/top_items/top_items_modal.dart | 142 +++--- lib/widgets/domain_options.dart | 158 +++++++ lib/widgets/options_modal.dart | 59 +++ pubspec.lock | 16 + pubspec.yaml | 1 + 19 files changed, 864 insertions(+), 623 deletions(-) create mode 100644 lib/models/menu_option.dart delete mode 100644 lib/screens/home/top_items_options_modal.dart create mode 100644 lib/widgets/domain_options.dart create mode 100644 lib/widgets/options_modal.dart diff --git a/lib/functions/get_filtered_status.dart b/lib/functions/get_filtered_status.dart index 7cddfab..6825ebf 100644 --- a/lib/functions/get_filtered_status.dart +++ b/lib/functions/get_filtered_status.dart @@ -126,4 +126,43 @@ Map getFilteredStatus(BuildContext context, AppConfigProvider a default: return {'filtered': null, 'label': 'Unknown'}; } +} + +bool isDomainBlocked(String filterKey) { + switch (filterKey) { + case 'NotFilteredNotFound': + return false; + + case 'NotFilteredWhiteList': + return false; + + case 'NotFilteredError': + return false; + + case 'FilteredBlackList': + return true; + + case 'FilteredSafeBrowsing': + return true; + + case 'FilteredParental': + return true; + + case 'FilteredInvalid': + return true; + + case 'FilteredSafeSearch': + return true; + + case 'FilteredBlockedService': + return true; + + case 'Rewrite': + case 'RewriteEtcHosts': + case 'RewriteRule': + return false; + + default: + return false; + } } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 3b087c6..f6beb3f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -612,5 +612,7 @@ "selectClientLeftColumn": "Select a client of the left column", "disableList": "Disable list", "enableList": "Enable list", - "screens": "Screens" + "screens": "Screens", + "copiedClipboard": "Copied to clipboard", + "seeDetails": "See details" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 90c396a..88940fd 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -612,5 +612,7 @@ "selectClientLeftColumn": "Selecciona un cliente de la columna de la izquierda", "disableList": "Deshabilitar lista", "enableList": "Habilitar lista", - "screens": "Pantallas" + "screens": "Pantallas", + "copiedClipboard": "Copiado al portapapeles", + "seeDetails": "Ver los detalles" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 5efba05..1d900af 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -140,7 +140,11 @@ class _MainState extends State
{ ], builder: (context, child) { return MediaQuery( - data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), + data: MediaQuery.of(context).copyWith( + textScaleFactor: !(Platform.isAndroid || Platform.isIOS) + ? 0.9 + : 1.0 + ), child: child!, ); }, diff --git a/lib/models/menu_option.dart b/lib/models/menu_option.dart new file mode 100644 index 0000000..e898514 --- /dev/null +++ b/lib/models/menu_option.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class MenuOption { + final IconData? icon; + final String title; + final void Function() action; + final bool? disabled; + + const MenuOption({ + required this.title, + required this.action, + this.icon, + this.disabled + }); +} \ No newline at end of file diff --git a/lib/screens/clients/active_client_tile.dart b/lib/screens/clients/active_client_tile.dart index cabbb6c..975ddbf 100644 --- a/lib/screens/clients/active_client_tile.dart +++ b/lib/screens/clients/active_client_tile.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:contextmenu/contextmenu.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/clients.dart'; class ActiveClientTile extends StatelessWidget { @@ -23,77 +26,113 @@ class ActiveClientTile extends StatelessWidget { if (splitView == true) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), - child: Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(28), - child: InkWell( + child: ContextMenuArea( + builder: (context) => [ + CustomListTile( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + onTap: () { + copyToClipboard( + context: context, + value: client.name != '' + ? client.name! + : client.ip, + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ); + Navigator.pop(context); + }, + ) + ], + child: Material( + color: Colors.transparent, borderRadius: BorderRadius.circular(28), - onTap: () => onTap(client), - child: Container( - width: double.maxFinite, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(28), - color: client == selectedClient - ? Theme.of(context).colorScheme.primaryContainer - : null - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - client.name != '' - ? client.name! - : client.ip, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface, + child: InkWell( + borderRadius: BorderRadius.circular(28), + onTap: () => onTap(client), + child: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: client == selectedClient + ? Theme.of(context).colorScheme.primaryContainer + : null + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + client.name != '' + ? client.name! + : client.ip, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), ), - ), - if (client.name != '') Text(client.ip) - ], - ), - ) - ], + if (client.name != '') Text(client.ip) + ], + ), + ) + ], + ), ), - ), - Text( - client.source, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface + Text( + client.source, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - ], - ) + ], + ) + ), ), ), ), ); } else { - return CustomListTile( - title: client.name != '' - ? client.name! - : client.ip, - subtitle: client.name != '' - ? client.ip - : null, - trailing: Text( - client.source, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface + return ContextMenuArea( + builder: (context) => [ + CustomListTile( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + onTap: () { + copyToClipboard( + context: context, + value: client.name != '' + ? client.name! + : client.ip, + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ); + Navigator.pop(context); + }, + ) + ], + child: CustomListTile( + title: client.name != '' + ? client.name! + : client.ip, + subtitle: client.name != '' + ? client.ip + : null, + trailing: Text( + client.source, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), ), + onTap: () => onTap(client), ), - onTap: () => onTap(client), ); } } diff --git a/lib/screens/clients/added_client_tile.dart b/lib/screens/clients/added_client_tile.dart index d8a4b8f..fcf2ac8 100644 --- a/lib/screens/clients/added_client_tile.dart +++ b/lib/screens/clients/added_client_tile.dart @@ -1,14 +1,17 @@ import 'package:flutter/material.dart'; +import 'package:contextmenu/contextmenu.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.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/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class AddedClientTile extends StatefulWidget { +class AddedClientTile extends StatelessWidget { final Client client; final void Function(Client) onTap; final void Function(Client) onLongPress; @@ -26,224 +29,254 @@ class AddedClientTile extends StatefulWidget { required this.splitView }) : super(key: key); - @override - State createState() => _AddedClientTileState(); -} - -class _AddedClientTileState extends State { - bool hover = false; - @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - if (widget.splitView == true) { + if (splitView == true) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: Material( color: Colors.transparent, borderRadius: BorderRadius.circular(28), - child: InkWell( - borderRadius: BorderRadius.circular(28), - onTap: () => widget.onTap(widget.client), - onHover: (v) => setState(() => hover = v), - child: Container( - width: double.maxFinite, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(28), - color: widget.client == widget.selectedClient - ? Theme.of(context).colorScheme.primaryContainer - : null + child: ContextMenuArea( + builder: (context) => [ + CustomListTile( + title: AppLocalizations.of(context)!.seeDetails, + icon: Icons.file_open_rounded, + onTap: () { + Navigator.pop(context); + onEdit(client); + } ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface, + CustomListTile( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + onTap: () { + copyToClipboard( + context: context, + value: client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ); + Navigator.pop(context); + } + ), + ], + child: InkWell( + borderRadius: BorderRadius.circular(28), + onTap: () => onTap(client), + onLongPress: () => onLongPress(client), + child: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: client == selectedClient + ? Theme.of(context).colorScheme.primaryContainer + : null + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), ), - ), - const SizedBox(height: 8), - Row( - children: [ - Icon( - Icons.filter_list_rounded, - size: 19, - color: widget.client.filteringEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.vpn_lock_rounded, - size: 18, - color: widget.client.safebrowsingEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.block, - size: 18, - color: widget.client.parentalEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.search_rounded, - size: 19, - color: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? widget.client.safeSearch != null && widget.client.safeSearch!.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - : widget.client.safesearchEnabled == true + const SizedBox(height: 8), + Row( + children: [ + Icon( + Icons.filter_list_rounded, + size: 19, + color: client.filteringEnabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green : appConfigProvider.useThemeColorForStatus == true ? Colors.grey : Colors.red, - ) - ], - ) - ], - ), - ) - ], + ), + const SizedBox(width: 10), + Icon( + Icons.vpn_lock_rounded, + size: 18, + color: client.safebrowsingEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.block, + size: 18, + color: client.parentalEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.search_rounded, + size: 19, + color: serverVersionIsAhead( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? client.safeSearch != null && client.safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + : client.safesearchEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ) + ], + ) + ], + ), + ) + ], + ), ), - ), - if (hover == true) IconButton( - onPressed: () => widget.onEdit(widget.client), - icon: const Icon(Icons.edit_rounded) - ) - ], - ) + ], + ) + ), ), ), ), ); } else { - return CustomListTile( - onLongPress: () => widget.onLongPress(widget.client), - onTap: () => widget.onTap(widget.client), - onHover: (v) => setState(() => hover = v), - title: widget.client.name, - subtitleWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor + return ContextMenuArea( + builder: (context) => [ + CustomListTile( + title: AppLocalizations.of(context)!.seeDetails, + icon: Icons.file_open_rounded, + onTap: () { + Navigator.pop(context); + onEdit(client); + } + ), + CustomListTile( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + onTap: () { + copyToClipboard( + context: context, + value: client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ); + Navigator.pop(context); + } + ), + ], + child: CustomListTile( + onLongPress: () => onLongPress(client), + onTap: () => onTap(client), + title: client.name, + subtitleWidget: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor + ), ), - ), - const SizedBox(height: 8), - Row( - children: [ - Icon( - Icons.filter_list_rounded, - size: 19, - color: widget.client.filteringEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.vpn_lock_rounded, - size: 18, - color: widget.client.safebrowsingEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.block, - size: 18, - color: widget.client.parentalEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.search_rounded, - size: 19, - color: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? widget.client.safeSearch != null && widget.client.safeSearch!.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - : widget.client.safesearchEnabled == true + const SizedBox(height: 8), + Row( + children: [ + Icon( + Icons.filter_list_rounded, + size: 19, + color: client.filteringEnabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green : appConfigProvider.useThemeColorForStatus == true ? Colors.grey : Colors.red, - ) - ], - ) - ], + ), + const SizedBox(width: 10), + Icon( + Icons.vpn_lock_rounded, + size: 18, + color: client.safebrowsingEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.block, + size: 18, + color: client.parentalEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.search_rounded, + size: 19, + color: serverVersionIsAhead( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? client.safeSearch != null && client.safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + : client.safesearchEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ) + ], + ) + ], + ), ), - trailing: hover == true - ? IconButton( - onPressed: () => widget.onEdit(widget.client), - icon: const Icon(Icons.edit_rounded) - ) - : null, ); } } diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/logs_list_client.dart index e2c0c27..99b0891 100644 --- a/lib/screens/clients/logs_list_client.dart +++ b/lib/screens/clients/logs_list_client.dart @@ -144,53 +144,67 @@ class _LogsListClientState extends State { ); case 1: - return RefreshIndicator( - onRefresh: fetchLogs, - child: ListView.builder( - controller: scrollController, - padding: const EdgeInsets.only(top: 0), - itemCount: isLoadingMore == true - ? logsData!.data.length+1 - : logsData!.data.length, - itemBuilder: (context, index) { - if (isLoadingMore == true && index == logsData!.data.length) { - return const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - else { - return LogTile( - log: logsData!.data[index], - index: index, - length: logsData!.data.length, - useAlwaysNormalTile: true, - onLogTap: (log) => { - if (width > 700) { - showDialog( - context: context, - builder: (context) => LogDetailsScreen( - log: log, - dialog: true + if (logsData!.data.isNotEmpty) { + return RefreshIndicator( + onRefresh: fetchLogs, + child: ListView.builder( + controller: scrollController, + padding: const EdgeInsets.only(top: 0), + itemCount: isLoadingMore == true + ? logsData!.data.length+1 + : logsData!.data.length, + itemBuilder: (context, index) { + if (isLoadingMore == true && index == logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else { + return LogTile( + log: logsData!.data[index], + index: index, + length: logsData!.data.length, + useAlwaysNormalTile: true, + onLogTap: (log) => { + if (width > 700) { + showDialog( + context: context, + builder: (context) => LogDetailsScreen( + log: log, + dialog: true + ) ) - ) + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false + ) + )) + } } - else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false - ) - )) - } - } - ); + ); + } } - } - ), - ); + ), + ); + } + else { + return Center( + child: Text( + AppLocalizations.of(context)!.noLogsDisplay, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ); + } case 2: return SizedBox( diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 3e82fc5..337a1e8 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -1,13 +1,17 @@ import 'dart:io'; -import 'package:adguard_home_manager/screens/filters/add_button.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:contextmenu/contextmenu.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/filters/add_button.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; +import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -235,20 +239,44 @@ class FiltersTripleColumn extends StatelessWidget { Expanded( child: ListView.builder( itemCount: serversProvider.filtering.data!.userRules.length, - itemBuilder: (context, index) => ListTile( - title: Text( - serversProvider.filtering.data!.userRules[index], - style: TextStyle( - color: checkIfComment(serversProvider.filtering.data!.userRules[index]) == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.6) - : Theme.of(context).colorScheme.onSurface, - fontWeight: FontWeight.normal, + itemBuilder: (context, index) => ContextMenuArea( + builder: (context) => [ + CustomListTile( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + onTap: () { + copyToClipboard( + context: context, + value: serversProvider.filtering.data!.userRules[index], + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ); + Navigator.pop(context); + } + ), + ], + child: CustomListTile( + onLongPress: () => showDialog( + context: context, + builder: (context) => OptionsModal( + options: [ + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: () => copyToClipboard( + context: context, + value: serversProvider.filtering.data!.userRules[index], + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ) + ) + ] + ) + ), + title: serversProvider.filtering.data!.userRules[index], + subtitleWidget: generateSubtitle(serversProvider.filtering.data!.userRules[index]), + trailing: IconButton( + onPressed: () => onRemoveCustomRule(serversProvider.filtering.data!.userRules[index]), + icon: const Icon(Icons.delete) ), - ), - subtitle: generateSubtitle(serversProvider.filtering.data!.userRules[index]), - trailing: IconButton( - onPressed: () => onRemoveCustomRule(serversProvider.filtering.data!.userRules[index]), - icon: const Icon(Icons.delete) ), ), ), diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 541f732..20eff68 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -216,9 +216,9 @@ class _HomeState extends State { maxWidth: 500 ), child: TopItems( - label: AppLocalizations.of(context)!.topBlockedDomains, - data: serversProvider.serverStatus.data!.stats.topBlockedDomains, - type: 'topBlockedDomains', + label: AppLocalizations.of(context)!.topClients, + data: serversProvider.serverStatus.data!.stats.topClients, + type: 'topClients', ), ), ), diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 0bf85d2..e956409 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -2,17 +2,18 @@ import 'dart:io'; -import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; -import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/home/top_items_options_modal.dart'; +import 'package:adguard_home_manager/widgets/domain_options.dart'; +import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; +import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; @@ -119,14 +120,32 @@ class TopItems extends StatelessWidget { ); } + List generateOptions(String domain) { + final isBlocked = getIsBlocked(); + return [ + if (isBlocked == true) MenuOption( + title: AppLocalizations.of(context)!.unblock, + icon: Icons.check, + action: () => blockUnblock(domain, 'unblock') + ), + if (isBlocked == false) MenuOption( + title: AppLocalizations.of(context)!.block, + icon: Icons.check, + action: () => blockUnblock(domain, 'block') + ), + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.check, + action: () => copyDomainClipboard(domain) + ), + ]; + } + void openOptionsModal(String domain, String type) { showDialog( context: context, - builder: (context) => TopItemsOptionsModal( - isBlocked: getIsBlocked(), - changeStatus: (String status) => blockUnblock(domain, status), - copyToClipboard: () => copyDomainClipboard(domain), - type: type, + builder: (context) => OptionsModal( + options: generateOptions(domain), ) ); } @@ -143,7 +162,10 @@ class TopItems extends StatelessWidget { return Material( color: Colors.transparent, - child: InkWell( + child: DomainOptions( + item: item.keys.toList()[0], + isClient: type == 'topClients', + isBlocked: type == 'topBlockedDomains', onTap: () { if (type == 'topQueriedDomains' || type == 'topBlockedDomains') { logsProvider.setSearchText(item.keys.toList()[0]); @@ -167,10 +189,8 @@ class TopItems extends StatelessWidget { clients: [item.keys.toList()[0]] ) ); - appConfigProvider.setSelectedScreen(2); } }, - onLongPress: () => openOptionsModal(item.keys.toList()[0], type), child: Padding( padding: const EdgeInsets.symmetric( horizontal: 20, diff --git a/lib/screens/home/top_items_options_modal.dart b/lib/screens/home/top_items_options_modal.dart deleted file mode 100644 index 18c8f9e..0000000 --- a/lib/screens/home/top_items_options_modal.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/widgets/custom_list_tile_dialog.dart'; - -class TopItemsOptionsModal extends StatelessWidget { - final bool? isBlocked; - final void Function(String status)? changeStatus; - final void Function() copyToClipboard; - final String type; - - const TopItemsOptionsModal({ - Key? key, - this.isBlocked, - this.changeStatus, - required this.copyToClipboard, - required this.type - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return AlertDialog( - contentPadding: const EdgeInsets.symmetric(vertical: 16), - title: Column( - children: [ - Icon( - Icons.more_horiz, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.options, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (type == 'topQueriedDomains' || type == 'topBlockedDomains') ...[ - if (isBlocked == true && changeStatus != null) CustomListTileDialog( - title: AppLocalizations.of(context)!.unblock, - icon: Icons.check, - onTap: () { - Navigator.pop(context); - changeStatus!('unblock'); - }, - ), - if (isBlocked == false && changeStatus != null) CustomListTileDialog( - title: AppLocalizations.of(context)!.block, - icon: Icons.block, - onTap: () { - Navigator.pop(context); - changeStatus!('block'); - }, - ), - ], - CustomListTileDialog( - title: AppLocalizations.of(context)!.copyClipboard, - icon: Icons.copy, - onTap: () { - Navigator.pop(context); - copyToClipboard(); - } - ), - ], - ), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ) - ], - ) - ], - ); - } -} \ No newline at end of file diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index a4c082f..a3c25f9 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -2,15 +2,11 @@ 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/home/top_items_options_modal.dart'; +import 'package:adguard_home_manager/widgets/domain_options.dart'; -import 'package:adguard_home_manager/functions/copy_clipboard.dart'; -import 'package:adguard_home_manager/functions/block_unblock_domain.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; @@ -75,42 +71,16 @@ class LogTile extends StatelessWidget { ); } - void changeBlockStatus(String status) async { - final result = await blockUnblock(context, log.question.name, status); - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: result['message'], - color: result['success'] == true ? Colors.green : Colors.red - ); - } - - void openOptionsModal(Log log) { - showDialog( - context: context, - builder: (context) => TopItemsOptionsModal( - isBlocked: getFilteredStatus(context, appConfigProvider, log.reason, false)['color'] == Colors.red - ? true : false, - changeStatus: changeBlockStatus, - copyToClipboard: () => copyToClipboard( - context: context, - value: log.question.name, - successMessage: AppLocalizations.of(context)!.domainCopiedClipboard - ), - type: 'topQueriedDomains', // topQueriedDomains can also be used here. It's the same - ) - ); - } - if (width > 1100 && !(useAlwaysNormalTile == true)) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), - child: Material( - color: Colors.transparent, + child: InkWell( borderRadius: BorderRadius.circular(28), - child: InkWell( - borderRadius: BorderRadius.circular(28), + child: DomainOptions( onTap: () => onLogTap(log), + borderRadius: BorderRadius.circular(28), + item: log.question.name, + isBlocked: isDomainBlocked(log.reason), child: Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), @@ -291,9 +261,10 @@ class LogTile extends StatelessWidget { else { return Material( color: Colors.transparent, - child: InkWell( + child: DomainOptions( onTap: () => onLogTap(log), - onLongPress: () => openOptionsModal(log), + item: log.question.name, + isBlocked: isDomainBlocked(log.reason), child: Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index efee2af..8f7fd9e 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -7,11 +7,10 @@ import 'package:percent_indicator/percent_indicator.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/home/top_items_options_modal.dart'; +import 'package:adguard_home_manager/widgets/domain_options.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; @@ -67,45 +66,7 @@ class _TopItemsScreenState extends State { for (var element in data) { total = total + int.parse(element.values.toList()[0].toString()); } - - bool? getIsBlocked() { - if (widget.type == 'topBlockedDomains') { - return true; - } - else if (widget.type == 'topQueriedDomains') { - return false; - } - else { - return null; - } - } - - void changeBlockStatus(String status, String domain) async { - final result = await blockUnblock(context, domain, status); - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: result['message'], - color: result['success'] == true ? Colors.green : Colors.red - ); - } - - void openOptionsModal(String domain, String type) { - showDialog( - context: context, - builder: (context) => TopItemsOptionsModal( - isBlocked: getIsBlocked(), - changeStatus: (String status) => changeBlockStatus(status, domain), - copyToClipboard: () => copyToClipboard( - context: context, - value: domain, - successMessage: AppLocalizations.of(context)!.domainCopiedClipboard - ), - type: type, - ) - ); - } - + return Scaffold( appBar: AppBar( title: searchActive == true @@ -197,7 +158,10 @@ class _TopItemsScreenState extends State { } } - return CustomListTile( + return DomainOptions( + item: screenData[index].keys.toList()[0], + isBlocked: widget.type == 'topBlockedDomains', + isClient: widget.type == 'topClients', onTap: () { if (widget.type == 'topQueriedDomains' || widget.type == 'topBlockedDomains') { logsProvider.setSearchText(screenData[index].keys.toList()[0]); @@ -226,59 +190,57 @@ class _TopItemsScreenState extends State { Navigator.pop(context); } }, - onLongPress: () => openOptionsModal( - screenData[index].keys.toList()[0], - widget.type - ), - title: screenData[index].keys.toList()[0], - trailing: Text( - screenData[index].values.toList()[0].toString(), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant + child: CustomListTile( + title: screenData[index].keys.toList()[0], + trailing: Text( + screenData[index].values.toList()[0].toString(), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant + ), ), - ), - subtitleWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (name != null) ...[ - Text( - name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurface + subtitleWidget: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (name != null) ...[ + Text( + name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - const SizedBox(height: 5), - ], - Row( - children: [ - SizedBox( - width: 50, - child: Text( - "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor + const SizedBox(height: 5), + ], + Row( + children: [ + SizedBox( + width: 50, + child: Text( + "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor + ), ), ), - ), - const SizedBox(width: 10), - Flexible( - child: LinearPercentIndicator( - animation: true, - lineHeight: 4, - animationDuration: 500, - curve: Curves.easeOut, - percent: screenData[index].values.toList()[0]/total, - barRadius: const Radius.circular(5), - progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: Theme.of(context).colorScheme.surfaceVariant, + const SizedBox(width: 10), + Flexible( + child: LinearPercentIndicator( + animation: true, + lineHeight: 4, + animationDuration: 500, + curve: Curves.easeOut, + percent: screenData[index].values.toList()[0]/total, + barRadius: const Radius.circular(5), + progressColor: Theme.of(context).colorScheme.primary, + backgroundColor: Theme.of(context).colorScheme.surfaceVariant, + ), ), - ), - const SizedBox(width: 10), - ], - ), - ], - ) + const SizedBox(width: 10), + ], + ), + ], + ) + ), ); } ) diff --git a/lib/screens/top_items/top_items_modal.dart b/lib/screens/top_items/top_items_modal.dart index 55aae09..d07c5f8 100644 --- a/lib/screens/top_items/top_items_modal.dart +++ b/lib/screens/top_items/top_items_modal.dart @@ -7,11 +7,10 @@ import 'package:percent_indicator/percent_indicator.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/home/top_items_options_modal.dart'; +import 'package:adguard_home_manager/widgets/domain_options.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; @@ -66,45 +65,7 @@ class _TopItemsModalState extends State { for (var element in data) { total = total + int.parse(element.values.toList()[0].toString()); } - - bool? getIsBlocked() { - if (widget.type == 'topBlockedDomains') { - return true; - } - else if (widget.type == 'topQueriedDomains') { - return false; - } - else { - return null; - } - } - - void changeBlockStatus(String status, String domain) async { - final result = await blockUnblock(context, domain, status); - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: result['message'], - color: result['success'] == true ? Colors.green : Colors.red - ); - } - - void openOptionsModal(String domain, String type) { - showDialog( - context: context, - builder: (context) => TopItemsOptionsModal( - isBlocked: getIsBlocked(), - changeStatus: (String status) => changeBlockStatus(status, domain), - copyToClipboard: () => copyToClipboard( - context: context, - value: domain, - successMessage: AppLocalizations.of(context)!.domainCopiedClipboard - ), - type: type, - ) - ); - } - + return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( @@ -169,7 +130,10 @@ class _TopItemsModalState extends State { } } - return CustomListTile( + return DomainOptions( + isBlocked: widget.type == 'topBlockedDomains', + isClient: widget.type == 'topClients', + item: screenData[index].keys.toList()[0], onTap: () { if (widget.type == 'topQueriedDomains' || widget.type == 'topBlockedDomains') { logsProvider.setSearchText(screenData[index].keys.toList()[0]); @@ -198,59 +162,57 @@ class _TopItemsModalState extends State { Navigator.pop(context); } }, - onLongPress: () => openOptionsModal( - screenData[index].keys.toList()[0], - widget.type - ), - title: screenData[index].keys.toList()[0], - trailing: Text( - screenData[index].values.toList()[0].toString(), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant + child: CustomListTile( + title: screenData[index].keys.toList()[0], + trailing: Text( + screenData[index].values.toList()[0].toString(), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant + ), ), - ), - subtitleWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (name != null) ...[ - Text( - name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurface + subtitleWidget: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (name != null) ...[ + Text( + name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - const SizedBox(height: 5), - ], - Row( - children: [ - SizedBox( - width: 50, - child: Text( - "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor + const SizedBox(height: 5), + ], + Row( + children: [ + SizedBox( + width: 50, + child: Text( + "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor + ), ), ), - ), - const SizedBox(width: 10), - Flexible( - child: LinearPercentIndicator( - animation: true, - lineHeight: 4, - animationDuration: 500, - curve: Curves.easeOut, - percent: screenData[index].values.toList()[0]/total, - barRadius: const Radius.circular(5), - progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: Theme.of(context).colorScheme.surfaceVariant, + const SizedBox(width: 10), + Flexible( + child: LinearPercentIndicator( + animation: true, + lineHeight: 4, + animationDuration: 500, + curve: Curves.easeOut, + percent: screenData[index].values.toList()[0]/total, + barRadius: const Radius.circular(5), + progressColor: Theme.of(context).colorScheme.primary, + backgroundColor: Theme.of(context).colorScheme.surfaceVariant, + ), ), - ), - const SizedBox(width: 10), - ], - ), - ], - ) + const SizedBox(width: 10), + ], + ), + ], + ) + ), ); } ), diff --git a/lib/widgets/domain_options.dart b/lib/widgets/domain_options.dart new file mode 100644 index 0000000..e250763 --- /dev/null +++ b/lib/widgets/domain_options.dart @@ -0,0 +1,158 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:contextmenu/contextmenu.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/options_modal.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/models/filtering_status.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; + +class DomainOptions extends StatelessWidget { + final bool isBlocked; + final bool? isClient; + final String item; + final Widget child; + final void Function() onTap; + final BorderRadius? borderRadius; + + const DomainOptions({ + Key? key, + required this.isBlocked, + this.isClient, + required this.item, + required this.child, + required this.onTap, + this.borderRadius + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void blockUnblock(String domain, String newStatus) async { + final ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.savingUserFilters); + + final rules = await getFilteringRules(server: serversProvider.selectedServer!); + + if (rules['result'] == 'success') { + FilteringStatus oldStatus = serversProvider.serverStatus.data!.filteringStatus; + + List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); + if (newStatus == 'block') { + newRules.add("||$domain^"); + } + else if (newStatus == 'unblock') { + newRules.add("@@||$domain^"); + } + FilteringStatus newObj = serversProvider.serverStatus.data!.filteringStatus; + newObj.userRules = newRules; + serversProvider.setFilteringStatus(newObj); + + final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); + + processModal.close(); + + if (result['result'] == 'success') { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppLocalizations.of(context)!.userFilteringRulesUpdated), + backgroundColor: Colors.green, + ) + ); + } + else { + appConfigProvider.addLog(result['log']); + serversProvider.setFilteringStatus(oldStatus); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), + backgroundColor: Colors.red, + ) + ); + } + } + else { + appConfigProvider.addLog(rules['log']); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), + backgroundColor: Colors.red, + ) + ); + } + } + + void copyDomainClipboard(String domain) async { + await Clipboard.setData( + ClipboardData(text: domain) + ); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppLocalizations.of(context)!.domainCopiedClipboard), + backgroundColor: Colors.green, + ) + ); + } + + List generateOptions() { + return [ + if (isClient != true && isBlocked == true) MenuOption( + title: AppLocalizations.of(context)!.unblock, + icon: Icons.check, + action: () => blockUnblock(item, 'unblock') + ), + if (isClient != true && isBlocked == false) MenuOption( + title: AppLocalizations.of(context)!.block, + icon: Icons.block, + action: () => blockUnblock(item, 'block') + ), + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy, + action: () => copyDomainClipboard(item) + ), + ]; + } + + void openOptionsModal() { + showDialog( + context: context, + builder: (context) => OptionsModal( + options: generateOptions(), + ) + ); + } + + return Material( + color: Colors.transparent, + borderRadius: borderRadius, + child: ContextMenuArea( + builder: (context) => generateOptions().map((opt) => CustomListTile( + title: opt.title, + icon: opt.icon, + onTap: () { + opt.action(); + Navigator.pop(context); + }, + )).toList(), + child: InkWell( + onTap: onTap, + onLongPress: () => openOptionsModal(), + borderRadius: borderRadius, + child: child, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/options_modal.dart b/lib/widgets/options_modal.dart new file mode 100644 index 0000000..4128fb2 --- /dev/null +++ b/lib/widgets/options_modal.dart @@ -0,0 +1,59 @@ +import 'package:adguard_home_manager/models/menu_option.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/custom_list_tile_dialog.dart'; + +class OptionsModal extends StatelessWidget { + final List options; + + const OptionsModal({ + Key? key, + required this.options, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return AlertDialog( + contentPadding: const EdgeInsets.symmetric(vertical: 16), + title: Column( + children: [ + Icon( + Icons.more_horiz, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.options, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: options.map((opt) => CustomListTileDialog( + title: opt.title, + icon: opt.icon, + onTap: () { + Navigator.pop(context); + opt.action(); + }, + )).toList() + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ) + ], + ) + ], + ); + } +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 2a10f2b..421a3d4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + after_layout: + dependency: transitive + description: + name: after_layout + sha256: "95a1cb2ca1464f44f14769329fbf15987d20ab6c88f8fc5d359bd362be625f29" + url: "https://pub.dev" + source: hosted + version: "1.2.0" animations: dependency: "direct main" description: @@ -81,6 +89,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.0" + contextmenu: + dependency: "direct main" + description: + name: contextmenu + sha256: e0c7d60e2fc9f316f5b03f5fe2c0f977d65125345d1a1f77eea02be612e32d0c + url: "https://pub.dev" + source: hosted + version: "3.0.0" convert: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 900ee58..ab4be31 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -68,6 +68,7 @@ dependencies: url: https://github.com/JGeek00/flutter_split_view ref: master-alt url_launcher: ^6.1.10 + contextmenu: ^3.0.0 dev_dependencies: flutter_test: From 31b6c0fdae0150adb5f5acd01af3ac15114e7409 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 6 May 2023 02:25:41 +0200 Subject: [PATCH 080/676] Fixed snackbar function --- lib/config/globals.dart | 3 +++ lib/functions/snackbar.dart | 25 ++++++++++++++----------- lib/main.dart | 2 ++ 3 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 lib/config/globals.dart diff --git a/lib/config/globals.dart b/lib/config/globals.dart new file mode 100644 index 0000000..d21860b --- /dev/null +++ b/lib/config/globals.dart @@ -0,0 +1,3 @@ +import 'package:flutter/material.dart'; + +final GlobalKey scaffoldMessengerKey = GlobalKey(); \ No newline at end of file diff --git a/lib/functions/snackbar.dart b/lib/functions/snackbar.dart index ac74407..be636e5 100644 --- a/lib/functions/snackbar.dart +++ b/lib/functions/snackbar.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/config/globals.dart'; void showSnacbkar({ required BuildContext context, @@ -12,19 +13,21 @@ void showSnacbkar({ Color? labelColor }) async { if (appConfigProvider.showingSnackbar == true) { - ScaffoldMessenger.of(context).clearSnackBars(); + scaffoldMessengerKey.currentState?.clearSnackBars(); await Future.delayed(const Duration(milliseconds: 500)); } appConfigProvider.setShowingSnackbar(true); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - label, - style: TextStyle( - color: labelColor ?? Colors.white - ), + + final snackBar = SnackBar( + content: Text( + label, + style: TextStyle( + color: labelColor ?? Colors.white ), - backgroundColor: color, - ) - ).closed.then((value) => appConfigProvider.setShowingSnackbar(false)); + ), + backgroundColor: color, + ); + scaffoldMessengerKey.currentState?.showSnackBar(snackBar).closed.then( + (value) => appConfigProvider.setShowingSnackbar(false) + ); } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 1d900af..62d4acc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,7 @@ import 'package:adguard_home_manager/base.dart'; import 'package:adguard_home_manager/classes/http_override.dart'; import 'package:adguard_home_manager/services/db/database.dart'; import 'package:adguard_home_manager/constants/colors.dart'; +import 'package:adguard_home_manager/config/globals.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/config/theme.dart'; @@ -138,6 +139,7 @@ class _MainState extends State
{ Locale('en', ''), Locale('es', '') ], + scaffoldMessengerKey: scaffoldMessengerKey, builder: (context, child) { return MediaQuery( data: MediaQuery.of(context).copyWith( From 767f4affc6418231c1eb17b11262e00a9c221d04 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 6 May 2023 02:26:56 +0200 Subject: [PATCH 081/676] Changed macOS default screen size --- macos/Runner/Base.lproj/MainMenu.xib | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib index ebf8e43..ea900ed 100644 --- a/macos/Runner/Base.lproj/MainMenu.xib +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -332,10 +332,10 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..01712f7 --- /dev/null +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = adguard_home_manager + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguardHomeManager + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 com.jgeek00. All rights reserved. diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..08c3ab1 --- /dev/null +++ b/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + com.apple.security.network.client + + + diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist new file mode 100644 index 0000000..1618df3 --- /dev/null +++ b/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + My Server Status + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..2722837 --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements new file mode 100644 index 0000000..ee95ab7 --- /dev/null +++ b/macos/Runner/Release.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + + diff --git a/pubspec.lock b/pubspec.lock index 93d9e05..878d2c0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -77,10 +77,10 @@ packages: dependency: transitive description: name: cli_util - sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" + sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 url: "https://pub.dev" source: hosted - version: "0.3.5" + version: "0.4.0" clock: dependency: transitive description: @@ -258,10 +258,10 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: a9de6706cd844668beac27c0aed5910fa0534832b3c2cad61a5fd977fce82a5d + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" url: "https://pub.dev" source: hosted - version: "0.10.0" + version: "0.13.1" flutter_lints: dependency: "direct dev" description: @@ -287,10 +287,10 @@ packages: dependency: "direct dev" description: name: flutter_native_splash - sha256: "6777a3abb974021a39b5fdd2d46a03ca390e03903b6351f21d10e7ecc969f12d" + sha256: "048bd1f1dc0e5ea25899f702815934d9a9e916fe23451c320e7dd94d5e3ad933" url: "https://pub.dev" source: hosted - version: "2.2.16" + version: "2.2.17" flutter_svg: dependency: "direct main" description: @@ -345,10 +345,10 @@ packages: dependency: transitive description: name: image - sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + sha256: "73964e3609fb96e01e69b0924b939967c556e46c7ff05db2ea9e31019000f4ef" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "4.0.16" intl: dependency: "direct main" description: @@ -566,10 +566,34 @@ packages: dependency: transitive description: name: sqflite_common - sha256: b2ed22d1d62c944ec0dac5cc687ae99cb3331c3ebe146d726ed24704634b5ccd + sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.5" + sqflite_common_ffi: + dependency: "direct main" + description: + name: sqflite_common_ffi + sha256: f86de82d37403af491b21920a696b19f01465b596f545d1acd4d29a0a72418ad + url: "https://pub.dev" + source: hosted + version: "2.2.5" + sqlite3: + dependency: transitive + description: + name: sqlite3 + sha256: a3ba4b66a7ab170ce7aa3f5ac43c19ee8d6637afbe7b7c95c94112b4f4d91566 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + sqlite3_flutter_libs: + dependency: "direct main" + description: + name: sqlite3_flutter_libs + sha256: "02f80aea54a19a36b347dedf6d4181ecd9107f5831ea6139cfd0376a3de197ba" + url: "https://pub.dev" + source: hosted + version: "0.5.13" stack_trace: dependency: transitive description: @@ -666,6 +690,15 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.3" + window_size: + dependency: "direct main" + description: + path: "plugins/window_size" + ref: HEAD + resolved-ref: "6c66ad23ee79749f30a8eece542cf54eaf157ed8" + url: "https://github.com/google/flutter-desktop-embedding" + source: git + version: "0.1.0" xml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 78908b2..88ca854 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -54,6 +54,12 @@ dependencies: markdown: ^7.0.2 html: ^0.15.2 flutter_html: ^3.0.0-alpha.6 + sqlite3_flutter_libs: ^0.5.13 + sqflite_common_ffi: ^2.2.3 + window_size: + git: + url: https://github.com/google/flutter-desktop-embedding + path: plugins/window_size dev_dependencies: flutter_test: @@ -65,7 +71,7 @@ dev_dependencies: # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^2.0.0 - flutter_launcher_icons: ^0.10.0 + flutter_launcher_icons: ^0.13.1 flutter_native_splash: ^2.2.10+1 # For information on the generic Dart part of this file, see the @@ -79,6 +85,9 @@ flutter_icons: image_path_android: "assets/icon/icon-android.png" adaptive_icon_foreground: "assets/icon/icon-android-adap.png" adaptive_icon_background: "#ffffff" + macos: + generate: true + image_path: "assets/icon/icon-macos.png" flutter_native_splash: android12: true @@ -102,6 +111,7 @@ flutter: - assets/icon/icon-android-adap.png - assets/icon/icon-android.png - assets/icon/icon-splash.png + - assets/icon/icon-macos.png - assets/icon/icon1024-white-center.png - assets/other/get_google_play.png - assets/resources/github.svg From 82d319ce66dc713d93e70d1af3207e687a894eec Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 29 Apr 2023 00:59:45 +0200 Subject: [PATCH 043/676] Added Windows support --- .metadata | 2 +- assets/icon/icon-circle.png | Bin 0 -> 42466 bytes lib/services/db/queries.dart | 2 +- pubspec.lock | 4 +- pubspec.yaml | 6 +- windows/.gitignore | 17 ++ windows/CMakeLists.txt | 101 ++++++ windows/flutter/CMakeLists.txt | 104 +++++++ .../flutter/generated_plugin_registrant.cc | 20 ++ windows/flutter/generated_plugin_registrant.h | 15 + windows/flutter/generated_plugins.cmake | 26 ++ windows/runner/CMakeLists.txt | 40 +++ windows/runner/Runner.rc | 121 ++++++++ windows/runner/flutter_window.cpp | 66 ++++ windows/runner/flutter_window.h | 33 ++ windows/runner/main.cpp | 43 +++ windows/runner/resource.h | 16 + windows/runner/resources/app_icon.ico | Bin 0 -> 1799 bytes windows/runner/runner.exe.manifest | 20 ++ windows/runner/utils.cpp | 64 ++++ windows/runner/utils.h | 19 ++ windows/runner/win32_window.cpp | 288 ++++++++++++++++++ windows/runner/win32_window.h | 102 +++++++ 23 files changed, 1104 insertions(+), 5 deletions(-) create mode 100644 assets/icon/icon-circle.png create mode 100644 windows/.gitignore create mode 100644 windows/CMakeLists.txt create mode 100644 windows/flutter/CMakeLists.txt create mode 100644 windows/flutter/generated_plugin_registrant.cc create mode 100644 windows/flutter/generated_plugin_registrant.h create mode 100644 windows/flutter/generated_plugins.cmake create mode 100644 windows/runner/CMakeLists.txt create mode 100644 windows/runner/Runner.rc create mode 100644 windows/runner/flutter_window.cpp create mode 100644 windows/runner/flutter_window.h create mode 100644 windows/runner/main.cpp create mode 100644 windows/runner/resource.h create mode 100644 windows/runner/resources/app_icon.ico create mode 100644 windows/runner/runner.exe.manifest create mode 100644 windows/runner/utils.cpp create mode 100644 windows/runner/utils.h create mode 100644 windows/runner/win32_window.cpp create mode 100644 windows/runner/win32_window.h diff --git a/.metadata b/.metadata index b5d8c1f..0b30307 100644 --- a/.metadata +++ b/.metadata @@ -15,7 +15,7 @@ migration: - platform: root create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf - - platform: macos + - platform: windows create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf diff --git a/assets/icon/icon-circle.png b/assets/icon/icon-circle.png new file mode 100644 index 0000000000000000000000000000000000000000..5b39396df98f8c660fe3554b2a26708879d600fd GIT binary patch literal 42466 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 toLU&&kykjpr7z1`_$nrih saveServerQuery(Database db, Server server) async { 'port': server.port, 'user': server.user, 'password': server.password, - 'defaultServer': server.defaultServer, + 'defaultServer': convertFromBoolToInt(server.defaultServer), 'authToken': server.authToken, 'runningOnHa': convertFromBoolToInt(server.runningOnHa) } diff --git a/pubspec.lock b/pubspec.lock index 878d2c0..f28102c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -558,10 +558,10 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "067ab48dbc66bae05e18073a604443baa35957101bd3905b94f65e764c6d0688" + sha256: "8453780d1f703ead201a39673deb93decf85d543f359f750e2afc4908b55533f" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.2.8" sqflite_common: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 88ca854..c30c9a1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,7 +36,7 @@ dependencies: sdk: flutter intl: ^0.17.0 provider: ^6.0.3 - sqflite: ^2.1.0 + sqflite: ^2.2.5 package_info_plus: ^1.4.3+1 flutter_displaymode: ^0.4.0 dynamic_color: ^1.5.4 @@ -88,6 +88,9 @@ flutter_icons: macos: generate: true image_path: "assets/icon/icon-macos.png" + windows: + generate: true + image_path: "assets/icon/icon-circle.png" flutter_native_splash: android12: true @@ -112,6 +115,7 @@ flutter: - assets/icon/icon-android.png - assets/icon/icon-splash.png - assets/icon/icon-macos.png + - assets/icon/icon-circle.png - assets/icon/icon1024-white-center.png - assets/other/get_google_play.png - assets/resources/github.svg diff --git a/windows/.gitignore b/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt new file mode 100644 index 0000000..f992491 --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,101 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(adguard_home_manager LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "adguard_home_manager") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..930d207 --- /dev/null +++ b/windows/flutter/CMakeLists.txt @@ -0,0 +1,104 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..208406a --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,20 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + DynamicColorPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); + Sqlite3FlutterLibsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); + WindowSizePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("WindowSizePlugin")); +} diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..69d8901 --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,26 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + dynamic_color + sqlite3_flutter_libs + window_size +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..394917c --- /dev/null +++ b/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc new file mode 100644 index 0000000..a56b12b --- /dev/null +++ b/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "JGeek00" "\0" + VALUE "FileDescription", "AdGuard Home Manager" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "AdGuard Home Manager" "\0" + VALUE "LegalCopyright", "Copyright (C) 2023 JGeek00. All rights reserved." "\0" + VALUE "OriginalFilename", "adguard_home_manager.exe" "\0" + VALUE "ProductName", "AdGuard Home Manager" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..b25e363 --- /dev/null +++ b/windows/runner/flutter_window.cpp @@ -0,0 +1,66 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp new file mode 100644 index 0000000..1c992e7 --- /dev/null +++ b/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"AdGuard Home Manager", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/windows/runner/resource.h b/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2f82038a537862ff2a05645269d432b09c97c5cd GIT binary patch literal 1799 zcmV+i2l)5^0096205C8B0000W0PzL@02TlM0EtjeM-2)Z3IG5A4M|8uQUCw|FaQ7m zFbDR8sF$i9&=QxWo_XLe$SGEK}{W;ydR^E~r6 z<`L!%y%k$^XYOT2>1vuf^ktr4&SHKgl~7IqCaHsIGo)GS01t*y??$3Y`Gu4K zG=3*ZdzZEbCi+TdBXfZiCMHNWg>T>iI!jZp0<@8*Hauk;1^8v#2N1oz5+00Fq>#SwJq#9mKOAUluRa* z@Vu<=(-a*PN~MiD0 zW+@)5J|8rN1|4keXlG^~rFTe_O*=9snf48Nm8PBEPL&O{vg!Q*k>>}@JUqAsgfQo7 zDJ`CRba&><)GItzah`#Z33O=qJj!JeWwjMrs)dV(h^uY^lbJDUOX=S}j`nclJK4ik zw;(ArMi7CKD7<@JZFYFb*O*J)0&>)rFf2NWwx>_0aGPCiRu7`sGr^o@7VM_{ic4y< zqs@YV2vX^Jp6#4U8`CC{-J(Cj2(#L0S5}_jo%UTnt0rp_GX(-hkvK6FVNTLWTGHn! zGP``d5ePC{X+vr@#j>0ItmLSgtfL_yOE#Gc@Anx;^O7F+EKt6vs;{Nv6(v+yb&W3b z_|NbScvd7AcsnOXiS(b$xiWup=-s31GBCeH)**wBs*t5+q{D$r~H_A1w9|Uxl zN)cuarZ3ZTx#yAtrpdp3iGIHIhg@X>nw(A!?uuz>R8lJeZjA3dKnOkZ3U*L+qvV3u z6#_a+rEp|SXOGiEvQeQ{`6<-S5=4X8|HH%pbc_^+vX|SNHIv4l*esPS8Uk7yq!;pU zm(Y#6yPoHXacN{Tw~Vs8*rgY6yV*u-20X{M{e$Nn7C?VEc%#r`hS%#VCCg=4WVe)? zE*)v{{NzLZS_$wqg<0K4u$?E<%(G(nzMV&LbLlax!k1JDcsI5F$2 zx1`*}!L;by0pa&O_8v2M0v;MRm#)=T(%Ry~Ez(ZqsMH`-KtLHYRc}d?T4+XjDxBg>ZsYvtHbuECS>ZZ&W$S&fV0X8dP~B**pQY@&!61tnS`Y^w_Bt! z^M>zJUU7{GL0q^10jG>AEu%wMTFpB$n3BJhbY;o}VLxCX3LxND5|1tP9Q1mS!`n%W z#-gGFRPWk4T6wDpVL6G4qZXw&ibhwFDB=;LN}a^>p;uU}5DvhcHgV*d8P(0G;@!B) zEOPfc9JXNsfHd~=hey6i2S3J6yZ!Bh zxMBj(^UKM{?!6&rA`a$1BrbGqGjjt2*Q_v`9a4#u*!Yi31n{_ANY~#kMZi47HS1}) zgi0rAF>?rsH}p%GhU^FZ0KLA6M4PWsl0l7^ao-d=NDMh}hbwuap#oT4aTkq$0hFo9 zsKrg*B5@>eo0CW4x-pQ%`!%(|$l}i)a2Pi=5+9B8JBi9u~@@ + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp new file mode 100644 index 0000000..f5bf9fa --- /dev/null +++ b/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/windows/runner/utils.h b/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp new file mode 100644 index 0000000..041a385 --- /dev/null +++ b/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h new file mode 100644 index 0000000..c86632d --- /dev/null +++ b/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ From f631780e187a88ab78fc2f376e71c62b031d907a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 29 Apr 2023 01:10:58 +0200 Subject: [PATCH 044/676] Added Linux support --- .metadata | 12 +- debian/compile_deb.txt | 1 + debian/debian.yaml | 14 ++ debian/gui/adguard-home-manager.desktop | 8 ++ debian/gui/adguard-home-manager.png | Bin 0 -> 42466 bytes linux/.gitignore | 1 + linux/CMakeLists.txt | 138 +++++++++++++++++++ linux/flutter/CMakeLists.txt | 88 ++++++++++++ linux/flutter/generated_plugin_registrant.cc | 23 ++++ linux/flutter/generated_plugin_registrant.h | 15 ++ linux/flutter/generated_plugins.cmake | 26 ++++ linux/main.cc | 6 + linux/my_application.cc | 104 ++++++++++++++ linux/my_application.h | 18 +++ 14 files changed, 448 insertions(+), 6 deletions(-) create mode 100644 debian/compile_deb.txt create mode 100644 debian/debian.yaml create mode 100644 debian/gui/adguard-home-manager.desktop create mode 100644 debian/gui/adguard-home-manager.png create mode 100644 linux/.gitignore create mode 100644 linux/CMakeLists.txt create mode 100644 linux/flutter/CMakeLists.txt create mode 100644 linux/flutter/generated_plugin_registrant.cc create mode 100644 linux/flutter/generated_plugin_registrant.h create mode 100644 linux/flutter/generated_plugins.cmake create mode 100644 linux/main.cc create mode 100644 linux/my_application.cc create mode 100644 linux/my_application.h diff --git a/.metadata b/.metadata index 0b30307..656c923 100644 --- a/.metadata +++ b/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled. version: - revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf + revision: f72efea43c3013323d1b95cff571f3c1caa37583 channel: stable project_type: app @@ -13,11 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf - base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf - - platform: windows - create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf - base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf + create_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + base_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + - platform: linux + create_revision: f72efea43c3013323d1b95cff571f3c1caa37583 + base_revision: f72efea43c3013323d1b95cff571f3c1caa37583 # User provided section diff --git a/debian/compile_deb.txt b/debian/compile_deb.txt new file mode 100644 index 0000000..4a18706 --- /dev/null +++ b/debian/compile_deb.txt @@ -0,0 +1 @@ +https://pub.dev/packages/flutter_to_debian \ No newline at end of file diff --git a/debian/debian.yaml b/debian/debian.yaml new file mode 100644 index 0000000..8bbb6a2 --- /dev/null +++ b/debian/debian.yaml @@ -0,0 +1,14 @@ +flutter_app: + command: adguard_home_manager + arch: x64 + parent: /usr/local/lib + +control: + Package: AdGuardHomeManager + Version: 1.2.0 + Architecture: amd64 + Essential: no + Priority: optional + Depends: + Maintainer: JGeek00 + Description: AdGuard Home control app \ No newline at end of file diff --git a/debian/gui/adguard-home-manager.desktop b/debian/gui/adguard-home-manager.desktop new file mode 100644 index 0000000..a011591 --- /dev/null +++ b/debian/gui/adguard-home-manager.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=AdGuard Home Manager +Comment=Manage your AdGuard Home server +Exec=adguard-home-manager +Icon=${SNAP}/meta/gui/adguard-home-manager.png +Terminal=false +Type=Application +Categories=Utilities; diff --git a/debian/gui/adguard-home-manager.png b/debian/gui/adguard-home-manager.png new file mode 100644 index 0000000000000000000000000000000000000000..5b39396df98f8c660fe3554b2a26708879d600fd GIT binary patch literal 42466 zcmXtfcOcc@|NraWYh;&|tf-4@%9hdO8VT15AxTzblX1P%K*Y6oFlqj}u`f+)bR6wnDO@FSQ<^eF`K zL73}Tu)b-FV}42Lb~an9D<0il$$^69_W0z*STB6CGlk}0`#G9Wf&2U~)%EWLnzMzx zVSkJgE@S;+5<$0nrz+p;+7Czbg4_@PRo|`(r@inWT?ijKdg)*)BklyveY{6^V1`Fy z=7N%mp!A=8^`zOx;Mu#(xD0c7ehfami1*?6f-LPr1ShU`GIL<*pVtz3pk{KykWvPb zJlXVUMXhS)%!(|nW`wtV1aNqFU8+|qZ% z&GgeaLjo0a^s4wQMG(WN^8UZ>famdO;UzH$jfpRekSbl7p2Hkw6t|sHZP_w2yEA{{ zXyVnAjESnJCH^GUtNdiA3<+vLbX{{x96E19AvXpcUruFxQEKi?aabs(F>^SvSmcfC zc7?B6lRXz%l$1!6++2093jx%bLYnwq3F-}|rfj6)^Wa4xv7W@u9QGvD{o%w3q#9Sy zLBMv~(U~9>qgOaQdODU8hZYuhJi$_NhDan2l+$GX-Mehazd_#=<=0xg!dG~5o1e@= zdPHjbY^7$_1(rmHq69Gpd3jTFdUp0qM+)jmf9=oD;5T#66<$o9U5 z`(NfsM#(s|um~N5G0<@#T3A2aZu1Mp#Ipou=_lk=y>5x^!qS) zkqkgko@whT!QCf!*H2KdVx}du2Wu~)2CD~(C#Xj;7brICmqq=RFa|9pP&AsY*_2c= zIS|ks8jSX7(2lq6@p_)K^v|hDh!x?3oSV{$tPleJPUA>Cn zbNHhalJ&V*g_kc5F+p`0ahvwC@%}?R;bS@2Hu5K$qzU$vp2VqcEowizM5W-hO*yF( zQWxS1O>hQ{u?VH0g>_+t_6S@{BAun@_vVRN=gnZx%qKADn;JMRVYo_w{qOV6#K)Q}OHXT;!>k9Y=8ft~ZPK#c}= zou@VzSCYwRF@t@Q!ee(rVqaLD?55uq)H{uwKxBlo=;B!;fVhkjLQ9-|d-!d&akaT& zXtrxCB>~%%CGjO!Nu5NK6Y@-pQD7=oj2*&b4_ntZLXWPGewGww4Sq5qM^?UiswC$m zdHxDUzBTf^Fl8;S98jlrE)HQO=zM0|kYIr)TrPv632Ram^|+Gy ztrN}TK^P^|OE0V>h0@r_;v{Y2X&P!;Exf@6#NQe(!$od9A;tkMHfu#w2>DO7#$c}m z>0Usp>J3Ve<{^w04X_QZ*Q-R~P{W4TpY(PFTDDkiB8aokt(wA9ZsIr6fQa)v1&By% z*^+QK|0Z;N*$S!(nJHi)`}Z3XkG*;srHZ*IP8Cs}csC%X`2QS93eBNM*!pZegPk27vI8lW*n}DZL=igf1LZvaiR{Gn(d_M- z!$a?ebOz6ndx%ZY$ZvSYBs+u=$)F;kn}rU95W3(b1J)13i04+X5mtPK^xH_X?-vU^ zb`vJJ#1S`5^am3e;At2KBhXnx7fAb)1J{TeI3|S87kUAV!z@1z z@A*)WS@3`>WG<#$)1YRLhHOJR8)9{{`y3|E7Vvd`K*w}AnAeT<^Mtkl=0-UeFwCH4 z;}DJa*)fE;uU{DXFv2m2Tj+rK4L&zIHaNj$tv4{L|2-LRJ|{yAJ8g7JwWTT zaxrAgQ3UQWI0&EdAu6Zp-WYX&^|qH@*KIsD+!-Sxrqn2oEZ$f8%QfS^< z%skcj!j-}i*gJvw9w11M3wng)B~BCYaSxujj_fi_KG|CYmYYYRP!f-wbHtUOc!4=M zxvi#d{_{GX5a4(|!1V|*`Q+ec^HvZhUjf*uNdJ8jCn>0TtXCUo2hH}0xj7$a#gc(A zgq8Ihm?#!gMsxtixOYtwp#+Xbw|u|iOSKv*J{On5{Ag)V znX2yZGLRpUR6bj28w@?B#1Y)R>B%&tyQF^#JBjF}3Df5C-zK5@e_)7=$z=O~y z%#aeIP1CvWN|g=V8q<3;Pkk8Tc8e(3d`TOxg$G9%$Z`78xt%5ZgsLRr(edwo5c@+t zkVU+QHRyO&z(m$VTCzm5&|xA%9A?6km_j3p2)bc8~V+Vr!~ z&k1OZ)_cz8AxMq#Fw8CM4f+NMetE3isC~N0>qiypa*wz%_%%UP8qMgHYDFT-S>OgR zRN-tp;sCA~sXcWw2AxN`g|@KSlePByBZe1=2K(RB#>Eq>aFPfOm`Q^lJd^>aw)L7X zNr!Q17-WHDfYm8Dq0Q$?$@n_$2A(j;ekvo(2NJS9#g|6}PRaHeL#ztvImNgei^k}s zQU@fE3oY0bBM29Pfbyb^PbSC*@tSe~FT-R#LcA3_0$XG8YaKv8{M?kIjH5SA$1h;; zjHBn8FKu{V7S%A|1wP!7!{3~9V1;7W0N!RWEG~H2P>rc8GVO-J89-4S(*aQC;OhuL&r)Z*nA7MU++25Xig#vtXq?|N6WVH4K zduW9MJ*mv&29QnA-Ebkmb)2_RsQvEI$&6LraZw`$U`aG3h;173gUdHe@dWoiP2bj| zP;!?Z@LD*RVTWdrRj9L6tv7%;@w86dlgUTAmnSsxHQ6BpyLo6FqcC>#^{W{gWAK>g z76+<6LP{_i%P$5II`I69l>0Q~#BCLIJV7fSAwdzO#ldwSPC4|9hglt^N#8e{P!D0- zK*v9qYaS#i6Y*dtwj^-up+AlZY1MWR1dCw?X@yd~&Y`RcXGDXY4#a7c8mhaMC0GE{ z>!A&TlkE%b6Sg!MJD>y+Jq^?Z^?3NeE(T6?6h-{61fs%#`eEak&f@WvBpX@#k6yr| zg{QMoM~tKY%~E6RK7oZyG;WM!TT+0E_g0QwWIp>WON)e;H35=VukvUA&Ff+9F56$>pNkN9M|J`uPO2veDqIa+&|%a zikEmEgV(xtl_Pckgu;2SXU}IqYoH~u4X1}3gTo|xNn0L-#LN@6r!fLw!ABP^+!58U zRz{#OPpBLH%CbA0=X!5B;6E#mdRvBU(_Ep9M`Ij*AOc=WC7fXa=HCEpC~MZ@sz;-e zJ0lR>wNlRNRH@1sED~t4_XqVT)hO~KoWJmKOdmo^zqy2#MiE}Z-`o&y`K?YVzXS$= zDCB$Pb(dTDCAJ-Wsjdy_L9S4x91BH+@Blc{U|VV=;RN{Rdy6s%N&_>&s#EDY9H?|o zu*v~^`RznCP8~qI(jE^anHM3&?tixEzqs&Lz*f_#;*ar1yhH1MKa z#3AFhh?MjrRzN%cB4XR8*)&h^5o=yOVEUOn^|qXw@S(gA2LDm=Otb0SNN8y+0qJ(} z9NR6V#Ve+ZU=gZf_GxScjjb@o59o~Tro0;$+1R2(5QCRtmJOBu>EdhoCe8$?msM&FIX1F;u;1H7#Cm+6ge0IPE|jb`i1v|Io?mA7>%Mn zzyO4AjL_O2C)OYUV z{RAEgzG@iP;E2F*BIuww5nY(Q*qpx8@3Yv@n*jE) z?tuJ2F1meXvKAlkJ@A!Ug8$WIqZUUWh7&}0m60%_CGq#*6>ym6_bBwMxddRY@w9+Q z2O6>?DdK;AhEeiNC%S}6XA~$It%5DzAhs{Ku|95H(9LYY zPRB$Vd@7`Dyuz`EVQWXK$1hWmMnauz!AaQhnUk$SLg1tpYs4EZ?^9%fH!83q(QLZP zlU+FxK!oAnz>-|XZ9X@i<*h{EmDkOhP043zY_H{=Glg<{HxN}Q`!?7H34i67Tb~D( zKGi(l&0WTgT1xVGxA<3n#B`!G`10%lIOj2f%=Sj~e_zsWkvc=A-(xGqAnfu*qAam4 zWF8Klcx-Jxjcu!wTL$6cbkm@SJp)k)rw!-UV=RV?%yUf{bN$W?)hNSg@zd6Z0XpzsL5fD9^Mzv2ZC3s9h);LG=V6Rb@ z2pu~lB9wS)(@7R66L3@Z0}5dF^;+cXeOm_IR{V;nf?PiZ=Li6g52kTrv*}8XNV}o* z@K!>c_c!8fh{yTaXh7SJ^671)4ZTPfKt;XI^q{=@a!eXl`WD~lNm8<*764^g{W_#n zqV+Ll`3fF5*Hf(o14mQnLSz*35q0bTq!}(7B_*h$;b2gSqyTt@#6|T8j)Y z?iaHROi%$FzDCFA_pVo;*gj!HFB;EH2gR4&B&`#7k0~agK1NABcX`Eg-Cq!V$(JLE zhCVR{>=R@ZL!=U1fI|%f`D^Jjk!7v*|F_qbJJ&h-qQbxz5R>& zP4j~AKkm_NnxbU8=0THiP>T<`L&-+>yT1tLa`ZTu;i1B$MVub?#Kh8Coo0GQfzz26=EQ1or zN6ny60D3>!+IqT$@m&XSmV3h#7B6ChfvY&Y4wbq&&Z_*fBa;#rKJ8ALALIv<3Cv!y zHeF(DufX8sHzJqq3t%32tx+x-Tl+k|{Cm{5hw7-R(cUM(7QzB|>9A7?5F1Vu!d{?p zLxK7R>=08MCzY_dC^j7r56eT6uX(Nl(P-tFoTSB>d|`aIHc1PyH6H_i0Q>qoX>6T@ zCB>jPS69lrXOu(1d04@_7!F(Q7hOp89Zy-e$BQSy1_sGB9K}D4c>&i}<1dBcwZPc3 zGMeIFzxaWrtJbquUp^))ugj8g-(~TnmLwg-lW&4_jXFL*|D-EYBAn;y9PqJgs|KXn z|M5%fAxg=Lt^hy>noW;57ALns)#?wZjYx3E!}Agu?1h|%AxNe zcc1|F+}FoO)SH<{t%~AiSAMAlERykyCy7p7``GUAn|YMgY)NOpmqbcjhMpwZ?hSAp zKo_Pbk7b+LhF($yfVvEAAu`)O6>xiW)(uH=@iro36Cj|yKKcO0B(N>4&r``-9G!K~ zOoBn`-NU0)Da8PY0Q>Y_F{9YOG)~F_kl}AKGbxa`3IY)LpoDH?Y2Cyu@`*68L;l&R zxX99L@OVc=BvJX^i`x!>^Kl8(UG`&55$bnEn@z3Qx{>NnoGFTce8E(MD;Cd014Ti{ ziP&%j{<~(qP|^%~IpnL93(JbeJ+$;_aqtT33rcmn1BxS@$a5VQU3)Yp~W6? zyJnvW7I?l+&`Hy`VvtCzb}-CN$BZ$F_CDfv^7zvi!7y3z%f6(B(rdZCU`~%6k?wy6 zi)HQ>>^g--fWgk2%?FuaBK~8WQE1J79ch&6)20;lscuI(U=Y0&bFvZ%%jB66n=&r^ z9xYk%jRX+2!75hBOd`GVm0=q_KDs1zY;QmC$zheA8ac3NXRfIvaI5>AP&_&w$Jv}V zsY#lRDbH0GgF39}COvz)VSj9iiI&PLjcrQvWEI-#dRv-5gFCD}9jTU9X`!;R+cL1T zlNr=B(X5WgRw{+)A+&KC=k4_oXh@~%QF!{bXEBtjbZNjn(Rm8KPZEA?Zv~uE{|0*wk0ua z;PmH;;tdu`Ucw7|?9muz{Ha@q2s}ED>Zy3cMt{XxozT&j1fCIJ$3$CoOg`U1X#5u| z5b1X85VsreA}wIA%p>Q=ip}aN{O8lH9C7BGir=1xz06k0TUY+qk0v^{cz0y$Mw$6A z@qgS%S4cntacb<)^xQ+zdHSOxQH+R{5$5@6J&We)OSDxZ3xB(V4nIy|8n?b4B!J$S zSpvd}dKqYbXHph7ox`+E5e)+$tmzQ?GbPLE)1GThZPS--{r)d3qFs=Y2LPf!xYsN* z93m*ymQHPz$)C6M_7e#gPbVClZC`j$C^r10@lmT*ccvSygeo{=Iihnlt^J6%Zs^<7kxFt(o!aL_-d+8l zVtCLT!2?{#cOZy3+X8}kd`0|w>gu3wPJc)9cY25X&e#6txlHaVI+-f^ z^LcZFn(aP~$7@XK)4wEBh%l0I?PwTAP;A|6%gGjsB`Low=F*#frWDL}g!GH8WSmhB z2WB!1TqJ8}}LYu_|{2dG*UYo)*)FfIXDcc*JaL_sX2( zMJC-XraBY^f!1KMa6b8)5twc`z^vS{?wDUR{jxG_|G~)l{YAZ|2p$bQ*0&s&gDY-h ze220}MBnPfZT+TY#E6&|w9&6+n+f$>O1wii8yA? z`w~9aG#HveZGoIOJ1g{c4n(~ukn=>eFQq>5T}bOQ>y;L$hz-Wg%qt~$>P&v{xMlyq zLvK+5PiUTpRIelz?d{sK550BrCCs>4Uv@=is0| zptK@d%0xeGogTO0%kO3f5*1-TweMmA7xlo!hCF5OxcY@$hx;}Q6wCg9f_VMcN{`tq zhqeXC2ZL8W1{Xn^FOrFM_duGRp0L)IlxO%L+6hdfFSWMD;i0A3hey%qr9NevDpc-u zGbpZ+syQR&80hTCme;&+noYYEY-_T3fpTDCu%#k{h7U7clp*Eg0DO0Eh8@?t6-3&G z^W08fN9$V$g7SKxR zXc{6uC8h&A>@jL#d~=XOw;y;clDQ(6nfZ`Dg||+37BA@QI{&r4ca8er5claLa_r@g zF4~KlKyG_aNFzi`u-G93aXW<*$AqeYQ_|Y|y6iAf`*efV*rSH@@3N8L_p3g-hKm=# zngUAIt4Sld*Q+Vt$c)jaalq87-5iixp9$$N=NEkS%z4^**fU z{duSr$^?Kfgi?KO2&xx`?K$XGp3~&Fa$^sC?9oBW@L)^zuH3TkpS!%}6ww6tOBDO` z)ym!{ff7F8tt~w5@iEf_Mm4DXi7!ft?kk_bG zTk1Sdz>ku9sLI7}Fh7izu9l*%Nj2fqW0!0-Fp=Pg-{&r)jb9b5QJ}L~{Gj=aea+w% zk#tc=tIdcw4D0WOApc~qL#OXf+!SoR-f2GpSNDL|wEm3zof^D<6+NN`G><~$& zRCh3?s%O!JAqY?XyiP(>`XN#Rq#|2K^LuTW56i<3W~!pz*W@R-s_xTyFOBnnPJ*yn z6h$NDD2uXYRvGlNm}{Gv#G{FiyH_#fcvm@)a#mLXKd&PP&h8XELuKyoP*enB;GuxB z_ewYqsQ>;lH^0a{OTqg(E$f^gmAVBD8DZ@SOX;aeY~F9910nb2?el5-v-)0woi$Uh zNnpevHZL6bYuwo};?d{+9{p-0Ur|Iz6O1A}$&MF|>K*69>hJ$%cE4q?E|GelgR@^- zw=&#SZC}*8mRTL&@##KEk0=i$EW-}1cJZg}t~}Jo8|15|PQA+$A}7X1ZN?rUI|R?n zR79OmYLdj-4xoUQUS<=ipFr6VRy8;3EN? z*w)cdKFpjWLXiJ0a62QF@*3BL2SICtPZwLckZ9qSTAH&_L5kkdS~iH=0UD^4W)z2j zuopNg*>?8vXHxQgW}(B<`}k0{u}d{aVJ~)8ZJF*Mz_C1x0c_Rs?or_+^vCLy6FG-< z`dGYyAUM~h>!dtA9NM3cN%;!qM4oY{dydXBPmt1ByR&hQ9A;)Ak7R-4Or(w=#&n_z zm-_ryOVm62YKMnB02EZ8yN2&|LE01%kREjEt7)_ru;)Ac0jT58{7{Z!yO@5PkM7hb z7xV4O1nPSluwB&t`#!3Zq@1S?Pe02qa|cg|Q>gS1vES^TlI=6O9s2YOAh2-OP+4=@91@Tv(1m(BTm+2rc&b~LVrw3|iEG!{`w}g}@5j<>eAK)5c<=u5 z_!_k3I>rrb+Tl+&q6yK+rL3vwjx{uGAbP<>GLD{FimeWEV|eeBYOC?%3a8~r*T1Ju z3hx39;HdJ{Lq$r$`=vX;nWplnC_VvU0ro1r8IW)P7C1%n+<1{&Tok`BTWIrm?+=^= z&JR%3bCEa3E|)_W(mX;=!|*~$3PuZ`Nt~?%RY1&_&sa^gGCT!fC(fV~m-vOzWP{oG z|Gx#$eS3xqaD)S+6YUJmCWaQ`13eQ)83 zIAZXGOV;70jA8ciCKC4pxh>ysR?miNo}5-2UNi4*m^xY=ae3VubsjLE8iF8&3|{H& z*4GPaKnWe;vAu#aAJ;>kN!|nLROpE9LhAjbv5N^zVgWItYG`4VJ2W2RJm)l2cgi1Z zgQmSc%lwGn-gkehl(sKX@4kW`JIV0)6z}-si7OQ zAP`QW=;I4UZtN_ z4mbG2(zGLCvj5juPVL`y_{4)c>Ldo|NFKC{1;Xv&I7J#WtgIfdKb$oIyL6@_%4*)M zSzTQ-yh`p2qcuCK8G}1mINk?3o$sJ$?e~D&LQW+ou&@xeK72h-Cz>2V!br#0&Bwecdh+>u~dMv7)z7=8m*qnbDmK0+I9cx%rSE%> zyk8t`5Cx#6w{ITDOEN5dN(dQ%qPiZ3#tQP-Xc^oG6-PvN#@E{M9nXH57~N51ZZmAG zO;6UORW}!uYYy$LY+eX}`)m9dag}Ite)fW25v1UzNHRVyw(~tf^)aEN7?pTS>G>}U zmE4Fi*IB}w+b9WS;+prngDsDi2Lp=Pz|m2RBpTA@;1#W8N@BvgBmbj_(ebE%Kit@wM5Lh)DkSU4)_x9Y30VfBUl{NFqAO)!v#7rxQIPrxd z?c{;j*VFL_Lbp>tMDb{_6)D9|msHX$j`J8J7t4U_7(}CXaX`)n`C?GUL>RFjL_-6C zf?H+v?~W+$jt5_^(J@+7U_Pmp_jy<-8gnsV)&{nkQ{^~UsOcpSfz=GUT;)je2t7dK z3FovmlWtFR)3r(d{+%b}-`k{hORn9`ckg<}a7FBkN|(tWOC$F*@aRuAzI-HAc%=!_ zz6GZALM&QrDdUscSwDUapN&{wRDl-uYBN5nJ?+w@+u@T=*PUsWU^j6bx}_g+nKnSw zJKA7MLwHY~)7KIfY*-oQIonuywcofIR%mGOF#%7Uh03?`y zy}+NU+VPj;{N*_-VWY$kGx=r(X8o5=f*5R6dzyL18}z=(&NOZ;hvncogL(g@RHp}- zx15Spy;nF zeGe_SDgKA>1NF0Z(aP@ONcU2}z<(c`fat;bE8`+h0JzTcAwayV#GA)0(`WTR79a2J;h{0bNnN#;h zGk-BuvtGrA-@nyqT9jJ;95et*-)r8GeqZxqVW!aL)^RnI$81T9-Iuqf!{s!bDn5uM zyaR}>bL9Ci>G$mmenw^wWFlu=t}TE;E?6`v{>?@!Y~PT4Nt9`4VY&PVe8acxyMMNv zcT3c{8`2e}5kB-E?3Z&JL6*(y#qL+&*r87q>Tm$UEyTaLAWepH~`Rjqq;7OzZ=$j9^hkxX>b?@o_e3dp`z#DMS~KRf`Io+ zQ;`EsqL|xhDFE>?A|~(i7hrqZkoW#!xu7rFdr9S^3*FIr&crHyB`8Uw(qx~(2#=*# zqnd$~?@LA6n7`Iar zZ{W7{!1bIAc6$4TAD3d0hX`iSMR3j!jpiOuj1Nw#ig})I0Wt%2xt7MGIou$RQk|Nd z53|o*0fO(_XS3ymKzH~Iafi&V7wj2&+Fq6*17Vl%QeuB%3ghoU^_*^(^3l`!f|$Rc zWD8uk`fB6Ca<47MUL4;%Ns9ypIwr1RAIz@_5!LkTiJDQ56W_*;;hokDKF zk*MZjQNCT@$7u^W7ez~1HlKtj>}?j#VY6|Sr`hv&g0?}K?{3mEW-5SrmLTAK>Sz{T z-b;%MBB@}Pe^FyP3KHg(ewZ44_7Ov%g(sMsjaOf{G8#OL-@t5J zScA?o9?J-Na&R|oR%s_Oe13FQ!)@+o)=#?vTa6fky9X^>iBUb?7#h7ghy<_WC~9=r zic@QP?T!r4@Xi*NZA-z`FVcDGFJN|LLfotahVtXspf*Spz;nV!ZB1WL4od7Lo>O++ zKLrB^W;|@tX=x|80Wje=>YxRWl*Yk}qZcHAwJl`+QFL=C%Y#Hs{GNN4>Q3wT=x?i^ z#hJbUAU1tZggidTPn#v;jXURyC{Y0ZuT{R@diIlDpUHQu5sPv-p#gM++GCbt^V+eG zI~yk8f~@1ysZhl~E~QUduL=}G+b1WlYk-FFb_7jCjpwjIN`VvL^CJ_;&+L^^_6yxS zqyN4hz{agO=n)t&B)o;R7I4D=ImH>D*0JcycIbTQz9t#}F~wQ-MTM^QLeWyd04U!W z`%S?kiQs$G?N#m)5OZ_R5$KY~5M*lIdi5AI~aqfV1MyFKuCq*F^+2K~ItJL0Yi~^XsOH|v8cAo6& zHSEw?3V%59$b3c92zlzxrVQnH=xC_PCTmsm8;b;k^)T#wxrrHF-(K12X9@lY{3<3@ z=S(`~?I?Rl48;y7N{8rZw}4rhqB9DS%PHBQb;PFbqsuZtpVqpX-lwSv{F3m|?0S-I z!ZUDFdno4(p8Q4FD(}@eTFZ`Ad;%4Jr(s&J4txYQC+v~{UOq9#Fim??5ue~Nu#e`M|5AyqqEG7> ztks84csDbDhrL4g&$tlpOh#MqSy)5urp;y^dB(RWiC0PD@FHO@Q2v+&(!u7_3Id}D zc*Q6ft$T6*u)WRKbMMz+3|g2$5Mc!w1U5M;vO%uY58xsy%hA#Hv}<~x5?33~&Deo` z4BLmi`~+L2z2yGU&s)4TnQE&4d_kg&qv9d9-Fueu9n}=9e5J9yDf$J5WwV2X^F#bVY zxSv7!28@)%mj9(H$JYL;)ylUO^p$}1jeXEN@f-Pm2MmHNhsi3W1$UY!sYRD4)s@}u z!lXOG?Y4v+NzXM&hwET=jol$#!#ONIW5h4C=HWcyfE{OoI1UyDKR{uUo0aI(HAZ~( zU~65Av!**m5H2BeUaNeWQqH^wKtU;Z)Rotc0M98Sc z?k8C>hfE#wB7V?K7TzKozV_HVyE6H1CHOxfZ&fy+)A*DLmTu%Ar}9@#0w|5>9~;e4lcsN{`{(X>TKv6ylK7jHT4jhhuHI&7%J)4yUsyB!qD0Q>q6uZAi* ziV#*giJ~Dpur1Sj4LO1+>-P94EKSb)0w9O&p?}{)f5%im>yh`DYXe39uOoI(>%;&u zNWwcB6;tU1DdYA|m_S+vH}ZOBwikrk*4BjE-~Tu|%q0w4M0a2NtV!k(Ksq~xb9HS@OfRB{#@6JAwBd?d7}o-NJ*m_g znT}$yA#l}^!`%id7YUFP{1cjz-MJ+*-P7b_H1j zmAs?^Vnd9_qRAavkoe7DnMxO)QGVTNpY}!AcBVSV*kE4FnWv}u7mf2oMeJFX%@Gj# z@&@Na^u92bsu`7{xN)V&9XGIU#hmDrUHsGz$e_VoQ zyZYQsfCRvAnPgTFojPMRAIO{{9~lDa{QhlBf1Kt79WX+@L#Hfxey(%qdzBOrwMaJI zg&+N!S$CndaG@h@5fA%U>75|?S!_z?iGgZ<$i1*7t;eSX{Rw+u; zfInT@Tf(Hv0%LOA*v3j(%IaE3dt?dV2wH22rKm-1;nPq#&K7o}0Bz0OTV>9Gf%x)U ztKepX?d|yi_;;IY6Ia0{9nHA=xx7MgO2Ib9Rh_JW6QpV4I{*TOGntv$eRO8BYZe9- zmZj#)Ye3Y^d+1o!&pja-3eDqA!v*F}Wr@pW z*9==(Kayj%u{vJdJnIkPf1j=KF%?EzzF`-D%wj` zl!^i|g+Bs8ec+qo)6XM{W@Qa%Py0M7$Dx2`e3Lh!_LgP9p%!UFNfC-Cv$Z!8qv;s0c{lQU|n(utfUJlVPvnQ8)0bmGZ`^XnlZkDZwip ze$0z}l>s6^zts;m9fCl#qlWJ+2D(%uKMxCn{snx|v^FQ!Y$0E3P)9}9AuR$K&)wE} z_;B_cP=)0Ll4(DdaOz=?tW>cVH{G4K^{3)ZlQB!?wi@8&buKE1eqYKv8vMIV#-!vu z>S)3>>Bh#$s%~$|0yIxyUZf>xIKQi@O^664W0nJdPr@1UY&W$kxAJvi7eo>a1w+9^ zX)kdL_-Vo#-1jU>4pcgB1;!8p6r!YNBlF{EaqAa8Tn5jI!JUZ5*rF_VKe#;rrpl$^ zr88MO|FDhtmD6M2L{8}q@$#^BD1lN5WXlW zA>czwx8dsqxgFD@q#FDu{RS8|4sn@Gw9;7iIppV0@4Y@u`M(l@`aCK?5a5|%Mq@$~i4Ze9K6au0kt4+69kT)bsa=fa06>LQAGsTsyA+fc7Nam5&$IK?v>B@-W*<2u7z*fZy_>S z4U_jB0QG)UP8qo3Ho^!8?8Ol}u<`c?zgI;UP~SSfe&oh*=6T#}c)WOO5zV)Ypuleg z+{s_?{q~U!#3gk>3=Gi16EV!cw!}%Yea7GK0ohqbAq87~rv@pBRL^_(K}zfg$ABoI zV88zkm@lTst$X{1b4q1bJcRE>Bf7&^TTAJ1r*8%YWBhM@sPUK6wd?@bC!kKje>^)I zrS_k$VPbE}x~VWG@3HqQ`A9$ajsWXBU$znn2l?NO%iTAiHt$>0uSz{^+hWivuh#{+ zF`(M9IymUr-hb*-?lQXxOlz)2hngMoVO`g?Wru=xCG*e%==z8IlNQppb|B6ZPAS+f zT7W7eG3ux7s114+{T)JAK3ez09K zUSkFcJ8MCvnY-q~JyxhQME}&d34U{~8Kd!d=;Jhu9au328Fu*4&TR2nFbd`#gB2k%Reth6oA*RANl>cidpL>|wQ3~3ZZCs zgW^~kkLfnLgPSem$ddoa@`9Kja1q93pS}o$Cvw}z<&tZf*Tv2{dpJNok%1&Hv~sc4 zL8gX(wqglt0G-RgHme8vG(b6;;8j31fcyZ;M*yqXywG7$lSHY`Ksq&oe`hu<`?QLo z$O8nhcOWx^Uu_)*UI9a+A)&+FxYVWTaMS9BrzZ69hXZBH$@MM|#Xr>S!iFgDPS&Ic zG;hkfKwb3P>0DPbU4Bv(=n!y-v~pp3d4Vm0d!4V~UB)}{*;Ak&sAiJ-;Q4reDeF9zw&s33TX7KZq_WEdB_V2QE>MG zU)&tc7QJ4(R7?}c+V1)jXv?@(3SggY%=3dG{*0u zN44pu4urX3Tq3^ltdU9z@rWvg?jIFi#2j1+zo^ptoo|*?jWxu_`GEA#{Yxo>Iy2yv zkk68JXOv6nd5lPK1Cim`_EWk*29gaim~EaZ5j#}tl;Yb-%!70I=#l+O;}ju(<=}Nw z&&Q>}#HC0}Ythc-URH`y=p0hyUJJXnn7-?8*#r*VN3U8(t#oACb)|m{YS$-l*yan~ z^k5S{_wrnC!A9Alg!#-?TR0-b&S$18z<#DaUe75&IF8EV zI>X?-jq_t=e<@uYCtQ>maf9-A_;a(aHBeYPzHFl=-A4U3*!VEqC!<)L@cS%u(p@!C zBX-^KA3Ve-(c;Msm9G4}P0u+`Mcg>~nu!?VK4tiCDWy+FJUDmm0tCHCPEf;66e;S~ ztQNXao;2WB#7M?5;0!PU%GA~cqubcP9PgBDHn%4TC`tN*b#9}fa-<-HyPa>Mr|VL1 zTMqKwWg;5ytUA=zdDq_hR&a@j5+b?f%=FJK56^YH)&qa5FP1fAGuol}&`#`-f?=hk zna?ksenLHGpFRZsV^O!G;77WwVf>P|9GL4|7O2;7dnqkm%pu@qD;0@v^-=M2`?&eV zcMo*i3*!4dd}$!4)vQcLpxAh?R{7t?aE-suo=An4S5g!upZ6<6J(q^IBE%Rz&VAgp zu64vUoUp#c%Ze-iQrA%X_&cWd!#rz$4qJ!qGye(j&%?WIc4nMu_=5HtS*_JCbLmS3 zKj&8Dc<9uf$(kwW=dRUJ(f3z5WFMhUXq5@wl4r=s?WB$}N|6tNWnFqXLEB-R!cx_( z@Db-_{q_unz8L5Wqq)<I4 z2`?5ozJkXbiA|5%O!0Ao4&~@#OBC{Dp#5p4fq!f)*n~JcCGelvmF7cbMryl%WK|kw zEP+z5=P+Uv@!nL*(PP?>;LG1<)z!L09Di*s^t{=ohQ1V*5yS$U4(Y#%IKmqDT+7e- z#h5b2fD4m*P0jcGo0xMi6Ib`|muirD*Se|1LCK^T7`q5hEwd|DscZ7mtMt1JNzX6- zp4<&)uuq9XKEIBgFw|NKeaZC*f3dJRFU%c50l5|4*Gqd;obk>h zi3WNTe2dl_Qs#n$h85Ux95QwH-TrTn!i4=VkA6hx*J&QOT#IYX#hc<}K4gJfVm=ggn` zJFeh{`k@p4;z-Gx3rZ__4p+wzF*3>C`ABpF5?|laU|L%UI7shAHUfskR3UKd*h3 zG?a#CS?u9$L+_Y z#Jm5-|C_Rzedzh12JCQ7?>|CJNaIix715Wg6*@T`An`iolGa9Ft4I9lOh+X~2+|jq zR5em_xoq<7jKEsWoL0p;;rk?=j$l#&0#x z-*@}Qod%y&iL~{S%H{shb5j5REr63W4~_bL4xzcakb3FCGY~Jv_CId0k*JR50Lytv zBU^vz7BvWx0~_Z_H<;?Zs>eQ~nS&3ew`C=L-nZt0zTr*((kWo|uRaeN_AQ$4qdhjP zY!FuFbAX&L@P7u3rd zg7hD1Y85TJCS|p5+=I2}MgYHzO-N~9GjIoISa+LJ-tMUr5T35b&2Lj-XZNdoxsPcxvKMAh=-zgyO>^TMo0z!1aA!&5vp z{;_8H{|20&NGPeV!c8J-@g9 zTb&Dfj|w=8J8^n;?eF+*pKN(9=8)`)_DKGwzJLOttEAS%_kLP zD4AWORO(*nWulB24ql!hW@#yX_ekFlX-I{DULqtqdqdMcDG8QafJCl#ce8eX4J;!D zeg0|qzUtp}OGwv>3;qusDG)jr-C5?@Pn_}ubs>lp&`W8MDj#us;)^(axy$!(gMSS5 zBFBY7WT4%OR!IGiySap=id+4oq7<>>PJkpJ=mes;^FwNZ;KF>!)X)U=OWnYtA1E`V zln8DMdMR}`(R_fOySSJ^HB1s@vM&m+r+Wup=)|?T&k1!N6-6yefGjbX(PbyucEg0Uj1cQkqY6n<$~%jnzWfd>?dw|FI@tzO78e+Sm1hjm~L+bB5kYjh3j?~ z^dB&k$1R4zSOentU20M5K)%lKQu~LwdE&zBR8=W>Syar%{*SvqC)$DwkEq{83uxy| z4=gmky#y17tCy&fkUU#(RyHlGZ*9RYj0K6iApcHMa^4m7rl*Y#ddb~K`+R%yG-ww`=9~LH@A| z*zEDN`meX1X6+8QB<=O5GJw>=WRa$c;zT(y86IkN>s@TYRu1AeT3ES64AM!0AzyxS zJ_z3+aA*#X4HYrCC|8uaSrlVt7e^U$q`YOFayE1V^u&@UeyRh`Hl!Z!=Qi^1Je`=jzq4+cdq?9@#qvt z-Lpeq?^|PK)#-mZ2;xRCU$~AaN4~3(p3$R#{J9G_+r__w1+q`7oOBnwKe&v&t@tof z@nEItsJ{ICOGhQzrFrMRqHejs-m;p3fh<23Y+Ur)ccGqaLJ#)$dT7pw-0A|7kk$!9 z*mp+iEjb`fd$kuFkdS_^zT9#2y&eJ(2S6LY02GkH2_4~tuE?2`l(j~1 zZmDaqxkdM-62{1NGcrb5f98@aJSxiU3g$GS-6BlyivN=k0nCnMaD(Ji6-kGif{}VGQQoJs5K1Q(QSL`e@j7F zQ`6ASJu2UD4I7WoN%W0k6UGC3j%T)jwOone>Y^2;Q@mnBPdn*8F0r%cqAg{3M^hO0DTEHPf95{cGl7Jo) zL(^@6W2kY;)pkTee6+@R-KVhsiSmHsWVhFFWpRtASm>2(NepnE{%B*6q|PzuiW>0l z5g?5U{}nmQwdM0&6wteCm4x#}V{=X@(sfL5sU!a<2}0hvTJ8OkDH7JhYUJcdm%5G3N;ZG{J&}fTm#l=v@i&ju z7XJP4k?1t=(rUc+AQIJt>H``|(b< z*B}r|ZH+%V|5#LHa`K}qcp7rzU#NfH*xoR-t!_{em<&;f01u-C@T_D9Io+0%9EA$) ze_omHZ`*nCz@t;h-*(}mi{pr$5;OM&FtP3bF?HSXRDb{fT#_QAMcEB$h{}wNrpn6R zD@it4W!@G_C}l)O3Ar{Q`({?Q>)IDbzPJPK{d`eC}QzNfWN3(iqxvd`l-|K|NIJFZA5EnAs!p{?N_%D4Ntm=!Cnmcr*T z$IPc$fTV%X>F#MG6cvheDHI8l6bgk&LdRoOmFQSCp1(|T>51TqHA%C~-wZCVxy%lB z4*#Lm+$@t{FAMXYA7#H%axnR_tz5t8N;}$f$fjaC7tJdNh-xfKz0Tapxa}k_!aB3f27hrq zQ=|QU_1are7W~{nIY<9P$TwnVR0h9fBW5$ z9B!y1fgSys2ReTF+MqL{HUVp|5Raw~I^qs*Q3ZhvF4$jEX(eO?z@KXWJXUyDQrn9ZG*8BW3`i}mzwHt#QPO}^DVD*jT@I%>_}5T)?u?mjnQaLeEV=4$p!D%2V7IHTbZjCZLd^*hrQ2n9+QzP_sB9e-iR-p zhTwtG`QgHhTKNZyH>SNg*Irc|R299|+H zq2zBun*;`@$x`X5l&bKyT^m7%y-OFyYg^(MM7wi4VaPRc;quG*%9m`s&OX>NAP)!M z;=Z!xb%VMw-luG;!R<|l-gKtLzd)>B_en_(p4HRw-17Kx*!S+R%h4;1FZ*r- zA6^dc{NUJ?ty`8R)YaJL7{5TTAzHgL)iqd&qC9G;-RN>Zh#l-x=3uF+g3)>aP^%Ew zE+ai+{?k1L3Y>k+yQp&sTb(17zlM@kAE@ibNPTkKr5G*_N__4568Ca-O6|l#{@I=E zcE*v(TDR@oYl+{*_a}9@@hFCW$WPK)6j{sXGhB)sKddMmncvz0HAxXdrA* zlHv2TLXvVJS#z~Iht)sIbnsV&U+!vxmy-}_^`3qw&~TBPa~%Gq?aREZw~Z$~ZHdYw zxFrd^u;u097o)kxnA8879X+huCsA$`uG!4({gJaJQha~SJ*4CezPP4Gh9l4IQ?&|D zd&zACvn(I2u15c>Eg5m?s?((^N_6a(VtYNuBSM1bJ7PS^-)1#+u4aw&o04*euems8 zL!8{vOMdf6wySLunp%APPLFl!|3Oxd?HV&btBFC%L~ns1Tc zhbgC$o1e6nCsX-zlN5%X!40L>MOt~?A#d2|S;q#v`{D9b;As#D%9(s^cvx_2OvarA z!+%h1w`5#TERsX=&&5y7zruHqx)-~9XyjLD$UPe2zm#D&@P<+TuBv+Wt8@?!h{7+t z2jA72Q)==Uz(mo{9A#K}Zow24`9F4J(j-$-3aog&mdW=`ih?FR@t94vG#&evpuXEj zz@^lhn{c-y-w-@ezQdvrG!LKt!txl&2bU-c*v;53wl2M+VS3wz7zG+Z9n24~nUNc~ zhq@vcMn<%L=CmB|D=FOA%-u26j&)AsMIRqA7 zKNGt!lo9{-=hGce{P+BB>@9}a<$n9^qpHP z{FH2w_QQQ!*j*3(*w*Pek#f>u2ZWbfE^ghstTrI7`gyOt3={h_D`7gU1DP-SCnl)z zoVeggR@F1O4lD}4Zm5whd{P-2x*pR59<}LPV$Yg5Lfk5inQbNoSonlIjw&~{n-q{F zP8QXnYGs7mpOpu^HVO&20AEM;e*p zC$);SRXcM&>~B`t3=!g+s)ugAMUEvLQ^x6~3O+jN3yu(!1#wt0u8%si;O(z$wRlW- zA#LR0wzZ7$GZOE1zY3*8Xm|^FgdphJHrG?KqE|kGpi9A9n}3JjKIjn1TDd9lV1^6+ zu-M_dc)vk6c?@sC<5+AiF5e|BalJf4#MZuRcBA?m7pe_h+KZ_67v`!1^2LSY0Cq*h zmlop}mo2Id?1|gvSy)hFCDYD!s^a$^Ta~c`FuS>-rB^QBtuwLZ(fFh!9GX`Gq=wJF zLa}K);~5SBqFqhnf|wt*TkuA7DBXp;mf$^HNKsVS03)AhtifCuKHq;*@7n4C!pFaV=!u*AmDyFn8O0hY zgeNZ0N0OH@NIXFbv3hP3h+yRrh49HqTeZ#LBIZ3Jl*snyJ83?Ipe26rv|f>@-<49C zJ`n%?wcD-HN5S0zQq1fInsUEOQrF#{_+QA}6xQOl37y1yZ+%OKA+Y9uu*d$3_q=S^ z&U2w9nbizHm`?d#!5%gpz6BBNmguhAv7ty{v$N<~@mMg~-V^G2DWYG1(mU>SkTyxb z!x1;*oikp4ya8zA1B}c9n;Q?`Y8`MF>)wed8VB1DI!HaUw4vK%BXhiR5MI3HB68?9 zZVTVyj+*-rMFVa_0>1Roo#c1iiiQvGt++5?;CfVjeY@C5zmE+g`{GW$LS#WU< z-2{R-^7!OAzCZKHZJWTskpWZEc2t94Njg&6@rm4w3HCCZ*&QFXzhQyS0zU`N+z8J~ ze=Sf%t@U5K*Zr)jxE|SKQ+#zOb~72>ggpntA9l?*{PyLzUOT z`K7o`VcuJ>zXG)6SVVogk>9{dTLLgo)jqT9n-R|s1;&I7yQ6hls|S7xe)LT_0MHL` z&Lmi#l!rHl?4VWnFgos4f4GL*@k~RaHh*1 z?c6rrci0yr+9RHdI7#}fXs@Xpl?7@Hs8+>GAFH{^*!atXuQRm{S{A>Gb1z(8c}S02^|4{N|w?jqnW zU#)WQieG0EL+rAE$!X0^x;w4yy=w7&zx1Asb^09o#U0WHk)l@?I}`R@@w!{R0@i?A zZBzIDG2&*$fZRQb&%j>>ml6YkcF#hTProN(VpNe6efn-nm#PfeA9x^mrE=(3g^UfI zz_JxjH~K8jLBHi3C`&cIYngq7Lt3l!;hH@knK9}iO+aW?0-CiUq2<5s_E>jz;3g37 z=>slgPLfv{dJ04$z2(ZV$N=9FVC>u(jB zZf#2pvnBl@zt*q?q5gg9?;lnk9RSa~CtF&<8CLSmY#D7M@BVIO5V>ym<(S1~YmPf5kUD$t zRUhYu+U%?`=UeUPf!{0P-Q=%Q4`hH;SQMUk0(h&?tM?BvPAQt^E< zIcBikme7haGds9`k(quTLlTb1t(1~`FQ`)JI0Qr z?fCbfqV7nO*GDRklz$wW9RPOIYxGs|E`41z_sbN>Y-B)o3a)IxfUuXQDAYVdt5Z`sU-V!tfDqNgPLBJThuUu$`lxM#O8 z{&TW7NGZmY#J_2eEO2gE<{zc=@>d>{H#xcJ0?={qYhf9eS+sm}W+INj;9>V*Uol;3_q*mic;Y*X_x%kTEy{<@PR4xomYq$-d~LUddiN zUyduE;-wF|gGC7NW~0i*4vfW`)44e(e_j;DHuC7nJ9{Adv)_h}Yk5mPaj%Vdf9(m& z@-x~fb*uTXZDPO>)4Ln`)?!{OL44Ss9dkE4MDNXVa3r zH~4Z+obBXiD}!Z?YJ;=8H(m4)t)lw4hLX$c$qz zP@4-QXh8=3rW#8b#QxN?D7*dc?5g35+jefG;m241{KZ^1rpde8?Pj>WbX#jTu*iN^ zvdl^AZFiL%y|gx**+A*M`ttV_whsV*LUfQg<%DuJAq_j~po7<~Q6n#_@B39-_zBtC zYS+Sr)cAt^Gw%W3Y>nzByP8_Tz@81s1#DuV_{XB8;FIH#!jT9ijL&QYs=obs23Cb@_tCO?a@&BF7NJ`cI@~Gha@+Rs zELfj`IENI=3mJEc^nyJyyVe>^Nt3Zrw_6ldfM>2>Rq~8lFSB`!{Tn~5@xA;-#T)QL zNGI9P=^VK$j@Zc+I${!(ks;AaNBzG>^33G`%!2Q2k@vGzFoDDl8eP z#d94W!Hok%sx~s$uW*%RZAnY=(R483<(Xn(wTC#oz7k~AcoG8&%7f@QBSH%^|0d-7 zM$D}L(lM&LO*gY04R3?cj))6L*$w7nexj;fW7%=Q&8QCW^ox4U-o|n3jz)E^|F0(( zDOgnruq8lQuyTRO`w91FqRh+;etm#MPTsy(uFhcySto*8XT1h_1nH=Hw{64hshrzL zo|7qknxFx~qRO+nBt;9Xgi`?m=oW&M>wTvOXcz&Qu>9d%d8u#2_~Db)cEu8a|4?ln z5iU1tXq+nvA8@%!t+P{toR`N3+tEP>!;h|+KOM}HXh3(UG&aRr_02C1J#%M9%pgJM zt-NugL0=7We}}_VHz3g1&&>ka>ma}>xzO3GbB8D|%M4YUvb#>cqF-?@8+mIoN&OMy zNu7`JEGV)w+oE+T&}Qkp!}0Z^slKH2F@-e8%Av^Luirf$-$28Az;>)0TvCBt>O&4Y zANnpRh5&r1tz*?|iO%?{MwFrc$k=lTZfJiaAhFaob=>ZOS_j6n=Z|e91JcuUC8_#L zG1<$!yQgsX#(-aCR@}x1$%5HJt23$J1`%q`-7r!~zXiEz6+0}0zHj2`7ecH5HW>{l zkNDuw2>vT1-v|caIDfsLT5x0WQeR!@W}z|N$xkWFKirEQxaTUuHVFRqOWlRPUk7;8 zBWXtF3PjxZbw@r;?H)L)eQ=bL`#g%$(-zfdxXS*+&9h+$HN}aVeENOTRqsKtSn+ z_06dCC&JV7R7b5H_|uThf84vNyUu4QD~VWy6OJ+8T}24oiZmI)7K|Qyav>Yf1HlRemi=x|gBAcw3)vk7nQ}fZzc)-f+MgN^ zsjUQWXsefHes{F*OSa=YBUq`w$e#hF7lpjFTTl=yh&2k_t4croerAah=4G+weJM*$ zK;&ZBwo3gg@f5kZqN9R(knibU7^x%;WgZ)o%L0pQ&)b#ukrUzPK(!;Do7x;^%PS+x zka+0p)7?|-p=w)!6^{UL`(ybNmWs+x%HHzj`HP_yN>~i&g6Z!vyBFz@b3CYS!*Mjs z4)DlTH>Fw9sPi~wrd@DWo&e^WyLkNzJ%QRZp#{{u_8^=Qct-E=u}!rbLz4dQ5`6x6 z_SL%+E)=Q5+u%~5DtjR807lsEJHkwrJzGOWMq=KADugtFUyk$nLw|$z;N!#Dn5z71AzLbW& z&rGlWOs&+CQnk!K7GhkQ4P1>uA%_(P*PEDSS521xlnDX&N?yo~d+H4tf71G9qG{3* zNIAG;SlRZsUm+YCFIkK~nKxGk{>i75Ii2S(cP`j1Ui9-Z{QSiKO36yKo`h%p#IvW< zH~Q%j@s&PcKCId?(P;qCkWRk++Q2>7Wum-p{-ZZ-aFd+OpX*kCcZ3*kT!zdJwV%?u zdjq17jD+L<2M$`w8o)N8K1#J73JHiO@o4zk&dt9z@oA ziGOeL!u!VCzW$WGm$G~lK|#dtb-(-h$p(~A_}*RL*;`w(@oYGs4K){3;&NJOrxWsp z@T_b1UiBAASHQqxEOoK86Bdy1_9j@ivgdZnaoD47>sIW|`yJ<~ed!g3@1H~{0D?s%-TkA?5Dusl3It;0#w@01wr%*I zJ8pn!N=Sa}DYQ$uGcr#J3O;YRn%!TjV`e$vfBE+-Mr7SLgl>spQAf?Yel8fHm$6im z^7U?5I%$Y^!A|I7`EpZGFjRbT{jp1iA%47X=!iDu$+Mf9oau;|i$BqR&1HxD92&L< z!pP&$0qO?1$6t1y^Gt@}ek+6qKd$?RClB(LeailsZr@*6O z3;THZN9{)NEMIY;tHNto8lae} z$Xvj<+1M&i{HXOe(hC%cU5Pf7IUOS1@%J@7ItV@v`ttet?Od#&M#OJX%CIf3_A_-h zEA|Z}WH(C$fW$;KjoCppQmiI#&;Oz@Ki*$^8PU8sl+NNuh?n{nr^yVie4T~9$1N%g zyGA=7G;!WC*Yq%--N^WxuqPmHB*93^Og-z>&Oeihj0r9XkHvWScgr8>A`ab*3EeJ+ zrK&*%yf2_o{#f}!~iAe~XzAbNT{1@a^-#$J+oX-O3d{&IASLD<~0+Tskg>HBC zTm3TW0*{HCooj)-2{z!~6_Q|PA4f=} z^+!%pL@!jjEtO)G1=LSjEO0UndGlbcwWGX#9dgES|BJ~<)!}cFT@x@&{kiJ)xJIyR z<%s}jLV1_;t<6MTi~!sB^+jbsmOjO@=AB&JG$yJJ_RJe!N&yP;6C2q-T9B>`!rkM|~3Xk7|qcfb-!s zhdHGZhu^^|mJd7Pn>|eAXI-W(2P(Id=D1%{Ql2v+>CZpm6nMTeLq&O<*{OE7htZ3l z2}M-W=*9`&12-xPe-#<_R4trK`L!3|*SbSDf%2?v;64yu8k0_5AM}hYdrM3A1WaQ& zK|jt18>MeALdp$utid{5h|k1?o`*x7z54qx=J?M3>2%floTjR{Nw=}^q1e!Gw|qQs zNQnrNLi`q|)BSD}#79q~y9Ni+f(O?^bf-hs%kOx)f0)1&Us5Tgn(D7Qd%NrIE8PG9 zc{0%wd0w%Vh}eVx?JwUNqj93qZJSazxcg(3b9U2|ZabN)#MM8O0goy}9$&fy82$+r zFmIT4eqNs~DvW#fF62-+IMW!c7#%vi2P=RX@#KHpn>vOeXEfw3;QQ}a42b8`%_}Bm z_Q+oHIn4G7N|8EhZeF*TgV?rYz1$j$GGF?=s)_`@3Ww?**lk^sA)5 z_Y!bHB#L_1qc{hwiVUPNj0$Y#(ld**J zYheQ*TJv&eT+CYYc|bi|+;&}&n_REV8@6$v6yfFVyvXGpmRdQVp|dAff}#HR>iJ$GlYI!gfePCog8HXEag5-m@O~; zk$P(E-B2Ni`R)@7Dq4~CnHGgSidUL9U-)4kAXmhUFoK{T!O&^P-On!a%IlaZK za{a#uNZP)ux(%M&K{sr^wr_KyEP-|?gT;~^DefBil4Rgu!dr5yxf*J@jXq~nTaGul z4dqn^tjbXM0wpeii*`7)+htD4!SgvYWhZRDa`t<6`1qb@^Zg}D%d^S;xejGm<HuOvre%J?dtMN-a(rC_CyL}eP{dXjp!Sy#z8wd zzk;*NsZ~9H=qp_7s3%%;%owMp|5Qi=`;whK`O9;>VJ^P4IkfYH;CcT$$BP`fPPNe% zJ3-okCwj6&bgButX^~_6mNJ`Jf2FGOQ$pEHXQ&dM{(lKSXNEToUv@WG+C%epz!;kP z8q(!xYFd9z0(1YB8u1@K%81nu&8J5=@hy1%FQ#aG+^PpDD-*NRG_yQE@$$n6k)J0G z*ShaWxrSEz?5ko<#eW5qDc*~u^E>)hJ%UntReZU20&KdZdKf2zIBF2u`rrG+;Q zCy={c012S6sHYvnKX5=Ogb7s4#=F73V%_kLwt-~P7XNdl5V__;=A?B=@Bqzf6`i+T zhSDDUO%&Tc1J;QVzV~9LkbYa5sk(AOGk+PDFPVOt(ULQtoy z&klBHuGJ?(+TI!rPPC^s+~xqaC3ymT3U)rYPcdcAI!^*Z(rQDnC-Ziji9#cXK}y)O zxTMuaA!!CFrZ;Df80oR_Skqp1BP58S-dbT0cXqfbQlTeR4XNCtKG}`|@O69-!gv3A z>}9+BfXBhRhb{CEgqL0tlBJqr%&}m*_V+ec9SUj6633uASyrP4%=dcO&nuC7bRhN? zq=}wm*A$WhLLmEG_!ijf!~sZYIq9mO1R(q}R_`GUnMrJt9oOj1UAEi@8d0W3ZZ=CY zR+s~c;!OJCOaVINDU4Jwq#r(T#bm)6hom7D02#@w3q@cC1oj^+@m*eT6}#~Tt}`Ka zqmm9NV;i}}f|qoGVi4jXD4QtBw9SKz-Gz_v`DEuQ%<9&}k4~hGvblWNjIWW0RdbtY zdp(7kR7eQy!Losz5q!YLKt$f$04O#?TaJO#49QFbCRBgbZN+V<_0??yl{H56@WM3~ zBuTdkbrXQFMXpB?&jj3cqFpZms+5N6S7Vpf%xfMcC%IvP{YiX|jJ$P@h%hfr_Z2co z(Bogg3JUXYj5D6Mrd5D4v2#EX`kFaK#RHo{GwK~%*n9(2DH;kMFE|d@3=+NstCQv2 z#b7H{BajG$B5^Rlh`le8kQ$(n0X+}eRLFrPlkT3sznOL`jDAZR0BA9$t>!e6QVmP7 z)7s;yH|<6%V#GbX0D(JHusFhV;$A@G;2KnTed>mdj2>Tl_J#r7+Xs+&_m64T2@kXs z#UTp|WqR{_EN5Yow-7k``hGqLYRCxtq!q2eg@sU4yTuAgRCv{Jw+{zGp;Hr2Tw;iA z_@M1OZ*QK2FPOc4Z5iQZyLe!t#aKBKD1Gj0crs%^T$9>(kQa9A2tr|=B}TL*HK}uI z%?9OwX=1+(>R|2dxX%K;V#go2&IbRrS`LRQMnK3k>^v|>bbs@&r<5;xcUH;qeOkVTd@3x_#NX7X_AKB!n!!>yxP0t4lH}Q zIXroV`)1nyBlVEOREMf{ET_@AMvqjw-^Rz3>#doXe>nvr)P2xq74AzkwkKlR2MCd_Uf|`=4L>9V zUK2i11u9ITAOlv!I$82{YfQKvCbPsI?BYQY?pHPfabf=uyIH-X1|Wcw_y<_klIjB? zD3?Nt3AWUANhEpIuxIu#{4Linkj?p$;|k^OP|GQBg#h4~dO+NPsM-{Ngpza#sk#aT z=znm0gYFI+LT4dxn2+7gd8{Goh71#r2uSVF(~r?CM{($RBJFkx{xq(P5h0^pLN_Q; zO`M;xn}GMu-#uRB*W+^!lQB38#qh!LNoLHf1j!_cHBcV}yh^bozVT~4p#@(tU20w_ z@6^eEnch79oiDBoChmJ}(Ea{j;Rw%9tXQ_O>JoNp-A)P1cQz&N(x*>UZNHBO84*4c zu1sx>(dhsU!E;?#BOm*UQPDY(VIr+<<=``rY!^JjZ!!PU4%Z}Gp}d%+!TucsXjiD# zpLfWv)1&=YD{bfCrjoBIyr_8iu8HHC?O%JH)E}=x@9)ux3r{s;NjRPz93q56+f&VA z=NWs^@ImNVgWZ&ZG%q2@q{kv3N_FK<{?YtbG6Xkum#NP3t(%FbuEf&&h=O3l4GOYW zQpGz!sm2cnZ3o_!lbBHc8UiBAfbi8l8S%YkEp!g(ay$3gGEN`@3k2&)2Sjx5gVJYu zYYbU-B_-pGe?gY?^S#5a!0Z2n1R{r?edFcp6-S~sD;B-;$8OA_a}#hxkRAcMap5uCprkzg zcVd)ae?sb^*(kW{wqpg8$9@R4u`Ci~slH*Ma`06pEGkwsW6%y}gnLLdx|SA>+=&5w zVgxs+dY^p9cqCDQj!^r+0X0T^5c&+;*m4>=@I3JcXSO#f-mq-wz5{Z*>Lo^d7HoGc zw5#d-Az1hpm$_$Gpo9;9Yd*!x_O~B%AsBp2d0d1Vq(rC_g4wIH()MIe9u>k+6h(n$ z-_;>M4{_AJg&pp+VYSaiCw3BZp|<);kxtxo5I%J8R4~d^Y)}Cx2OmyhI6UC7G%eo2u1WL-2mN6X4RyZ%x0ETSeNFMD%FEsXo{y_J4Yfn4q(GQE#`gTJ&uBous zBNV&;ysNv>u9*75VvMpH{v11Y^T0$~r&2C7chI2-{;nCS!q5;tK9}cMg_ef-i+>Q@ zWfC(NCZ$ByKC+fKV`J84#i(~(_FT*e9l**d^OHpM2w3^=rX%FoL~A9JtgWXXK)o~~ zie#s!F0e+Mu%O4jaIz;8PbXby;df2G{asT<=`0>T=2uVZ5l$yzcVp4iF1IEJYkEAb z>l?V;0(Bk{5Sqn?-uHvpE0Z&<{3-yYw1pQbFv{ZNSn$c=y4})z06e`scyl7zGP@m9 z-Wsh+P|iS2!t>gcJ%|p!10U!QO9(Z+ygIC81hYHccJb6ge20Dg zIxmPZx#Hn6+j;@W0wT&q5GphAxNJydffOn^U+KwRzDQcSI=qPyDNZfF;C;|NfbOVj z1~yp&$O_ff<5|5nP=ECVD+_0p|DGp|RZw}7)n4@FtsH}7+xDdM?L%<4duGFM=H+}L z_8R+k%nDC10sR+c(amJ&;&ZYrL{hGY;P-0>19N1p(LV&z-$8+AR3W%eHK7 z-GF(#e&L!<{R%6Nhv55a<6-r$oyRP*$dDwY@xi%LFI&65hXh=XQv1+(aY-O=+Nsk@ z{(D?Q)VQu$$z1J_wNZ=!0&wXZ8pG&=KjQR0wXjh2J!l&&u4a8Xq1x(n$@m@E65*)Y zm(=y!29a2?B8JvMF$Po(BI3KD9y#;F+(w|y!*9= zR-5L9i)Y3A8>h;f`76umpR;)DPZlS9qn2ci83vbIDDanOmHRC&&aKX@c($ruQhMd> zd4_T*&bd2DcEqcQ2TaM&Pc~%ht`)X{&vc0sRPNO=dZO`4{2JQ?)zj~e(%@8cQc`2) z0Vj_!Q~$BRMY$DzabT9lV3y(}za(Zf2GQT2g#o+Sc)!w>g;jn(^RAw;zDxD5xUo;K zbvA{Z)S;P*>C&#jr00xc z_3OFZsN|ykkgDSnBc8WAXRj9r1Mv&FN9+zi(m$+l_koe;$o8=D`fUI7HVw)CFtZKa zxH~nL%U`(ry+E5pTU$#twQ^sFmm<%AKxehHWVxG*mXe;!O&2cORF*I7<+UD|F6xrU zzK>gZ%H(kyPZHZ)kojPFg-yU9d;VcWShu(|OOKeXwPKeGV)=W22g(upjK>0!zGuW@ zpS=FvNwfzkk|Ck=DA@dbQELkUN#`#2J{@F69POEGt677$qm&kMX61a|F#c3^n6Mb~ zzT;HfaG;cWZ%6{}7z;ni)^i&AEETPTbGD(@?Jeg-!WnA|y{QUiO>*ATas0ha9KT+! z#+s~@lrJ>1O|v<YDR4k2*ul}zV0PBtM%Kqg`?p2p6zraYr>He?3t>B27@ORONx@1G|*t327 z@+m3FCz!GS$MB#_jioF+kOIaO&XdyPbeNBA%tP;GZr05*BIR#H-z;*zlYgbD@8|O+ z<2yp2hpFthf)$cX7c5dX52=o1+Gts9tBR<*yvh+=j=ae0GvoY1MQXDD6;t<=PywB z{L@PvC@BSy{3GN& zw!N}^ALDOcfO;n5VA)~iqw0mTrry~r32f-t%w!W~VS`Hx85@^75@G)Kk|o?w4|XE{ zuJvX!%U#P0a_e(h{+Uj*PBVWS$|s%$y3Ns7xbp6xLwet+s$zdso&u|yo}~D~9@qLq zW?B^ns4jApn+m-t9&68tz;tJ&R@&Cbv%)6F9Nhw0E^k4`pH!^BYcLRH3EA7coRGe4 zSC8jLyh~}qba&~Qx3WBL-{aP2XPjF@WEVujD0_=mdb09o*SVwF(XE)r>aRz+Lysbn z1`|*+Z)Wbas>&?1DlJU)4Q0>v&*FL4y@!g2aB?dPi<8~w`Ny9rpy)U~@uoU4F#>w; zwM1OpjE~6aN>P;?KE$|~#qaG?=`nY{&zm$FwO%eYP0k)zZ5^aqhRx!nPJb+yoL+`F z(!8k2=g{Cs>&+(lTIuS#MSM_xsaxfbE!v}RWu6#2mbqb>`C-WG?8N zXLBe%?Ky)Yxq+at_cgpyhdnd(9t#WsA2EF<`M{vt4-PybDZStmVCl$Qx0B25&>)3w zc!=Q1(hMyq|Bt$A{;x(*jRaG18LXx8^H7-A_q&HtXqsdgE5t*H+uoJ5?M%&?T_`ra z>*>FyDG8QU}`01ay=r@$&+Pg*-^7$tRP}8@H8lAWmIT z-v1hhq=W)D9Hg=t6nj7+A>#GkULM}{qJcAKRev}E;gyq!!TMoUeLcWM5?$_5dJJ{i*mgbUEUb$x-*TgwrX~teMUte_~ zHOh2xq@nlA{^UphPEV3kvWej8)W(E&B}9eL&Y`a?!$vpGJ6IQWxaCvHO4*vpJJd>a54uxg zD>TtFxA4tbu5a7dNy_5@;p6{Dqbj%!*>l@Q*baBi-JV+UZ(-82b}>hyzMkTQep>%t z{&uE7aAm$SvJ}0ysjNHlkCrFYY`!e4I~7eaC>BG+h468U9c?(tuSa(wr?f#ingqJe z4ycO#&@_AmhQ(8f5j*9XwLuEvw$Wk2zaV`7w@1hFa<6&{JFSr*RP-=a8Yr7161hy; zFwCR_ZcYEUjG3}rY|GpZ5uhy;-h)(NXH}eA;PsWlo}XjOKpg*1t(=fDHSoRT7G$7b z05gZB2mhPsqcUNLpZB`1F37(RNC>8ZPV~G}T#{aMk^2I6Riv79Sy zxXyumf*1^^iu={HUM6Gtud#{qkA+h*`k2R@KJ<@{?sKK8Mo2fFZrG^2%&Ub)hN;{| zao%+$CVYCHuAFTjCZ-%DL#olM>GcU?eT3c&Z>`ifx`*h}AzQxM}w0S9>|1~Y1sl<3Phi_q^Aq$=)dAQ6qt@_G4Bacbx%_!l<~w> z^mOG|{Q5%MNpra~sWyi!IS-?SMt;2n;K79&<>ou;sZQ%(DSNAdiM24Z}1j@KQMtB}P$lM;73(d8*{a&gE$2XnD2mm6jK#AUWj6%XBt zsqMbVgqK?^oJdYOPn;=%@#21s`cHRc`#M5AVNSm`E)+W1z!}$NWml+@-)gE^?(Po}+d^_jWZj(Lvl)0G~;nx_zgZ^V zX_-w^Sp}WT^FQ;w7mGLK!9&hz7U{ojGka!bUSy!e3UDB;N}V_{nVS7tC?mnLu-tr~ zNnv5Z#@d(fvOk&m_rMJLLQ#$b?ce2ZtMIQbk0~kLlcUy6M8LL7%F|hWh!#n%!oe>H z2h#1rSm{bF=d3tAzZNGB^_+FV!dX@oo06@D3C4J z^$!ib_sjWHHsSsjbwh3Zx*w(h@C?*n6L*1ZJJoUB(n>l`G!18tE6?;=r?59%!sX=h z#lHZs9C_4A5jG-xHzw7ft@%Bl6sFCHba#zO!nHD5$i9qI*NNulnB&TdZ33>-A4Zac zhSX;h{cUGKl7Ds=le5PUh;DNxe2+|#m-E60XzCE>mXo$lX?jR!zM%Gg{hy+89nOxu zdGMwp?nK=SLKw|0IMG_4E)>d|dvzDGG}f2PDY@Z>c{Vr^o0!KUJiIp|4x_rIYt$8* zh;RGFs4BKy>>b)O+0!!%W+fxCNVkQH_xkQ5sLn8*Puuq{?d`pPZ&TCnp6Z3asr|dz z_9$)@egz6e_ADr^$4N-nf7L{df!|{bG0#gl-CD0cgf;i;E;RRjG5wzp?LVuQ@qklLl%Mzh zV>)wrIl}S}T0igM7i6bU)=#4_kBuwoF5>(*D7T1hj1BneRoH{c2V_f{w(VvKvx%{Z zKEQ-uS}02q!+c_n+BVhvZLXJaCpP$WeXrBFBktGZl)V9`-=S##*z^@W&ZpQqoh3wW z#h6U3Bxo_=Yk#$+SX)D5W4e-flStzc2I9yamxVSMZ*Kgqsu;7Y3NA;V&m>NU#xA?d zvTbxNn&Ic_8wAOs+GDiwTE%1g|JU5I7sTdx(gS$^n1eD^A?D^T4m_Rt$+&BBR@jQn zljV|SfO9?K>C9c^l4Neu8U=Yt;xBR(ccEarOs{L;#R~vyUOk=Zdn7$IjzvqQ|;W`5p>CaFl@Cn3#GFpv&5z-^~YZBP~4!h9K*!!u|oXF(e|O)l4F z!TjtI6j`5u(HuJJUscirN8r9(64Do8%alKX?JP%I{@U6yg?;KY1Mzlo;&RW#6vp=W zWM>c38-Ji%RlF7wPH53v%of?p3oq#3iV|<)u!aZA*TAg5APmu*a{XIjwlT-`cQD~c zsrM&d(Rh-1+<-i%6lm@XtLS@?E=99s!Y`$CD`jOiO{(K^`U|xyHNnlntnEIZcQygt zr)0KZ4^~Cq&*;RR#6Em3e8{IqeA2tv^EE zc;9)65qRO}S3{~o`eG<+Rh=eCK$isXHjHuuFVee!!|FgU#w(szlQ!u;x`$hmmdx4^-PShmfG@Q$?+J%hUHk!l~amc)9)qvWSbpAv<9sZd2?HD)^eGXA4!|xC1@J<#^ zKrZ3HX=~ri5Y{T6YsgurFo6|3NQ`$JPfMt;jDW_N`V8wNsPSV*)-9NjHPiDUC2->% z8lHGI>3ka&{{@ObBR>P``q4NsvxEainVXrK;3JPIF@VProkrgJdIXcx+eQg|N^b{r^}W-XanY*BOs>8q<}#Ea3|UX6)o z7FdKGM*2=++3Pe_qQArc`GX<@AtoeQWtm<{V|I>yGs(G?}woGSdj z($-Kb8xG|U>`9}OP_Ny>i|vV{(KWWSJ;1*+f({?@q0_CQJzoj970>W{Dn;VMw*>c8 zWX|E2x;%tQ4e_=2O;Yb($%k}!gS(p4dCXfgS6j2;qtKZyxBAXUrc68`b8Y^vM9kX`JaJ_ey$wTNfhPceMnA1<{!GW7qdX=z&0eim&m^G=!7d1 z;M`lu0|eMBoDTO7JF>c7J!t9)O>{zZ&}2>Dy>l3T5;$kD+17A!yk3w4yqEqKeEbZZuuQ+wUKweK0F8S(Qwk<5V>`1>MD0St z;gy$@m=MvY$FF|E3>1FX1sw71T~#WH+=VF{^HJYS8;9kXwzKBez%Unt^aAxjEkYjm zt4xxOs@ETiKu$gkLkQCe)aA#vfsdGbo>D-mzr=XY~Is&=iS z@OJ4{m_#;v`PIbxPp9ET{gfm! zNZW{o?|U27rFGayIc!ANS~9MAIe<2lw3Dr&GRVu83?X>M-jzB>&j0tyne^qJl!Al8 zK-~sMJLY7HPFYhn^eLLmXdD{TA2Ry3&DOL#?4S8A>hPz=x@$)3nx`EX|LoH^%w&-u>W znR}b*H>(yXR@T@%Aj#NftcOguVU2fvb0gDbwjAct3(rzDQu4%+P*fmFjh~X{=7*t_ zet#43%#DIJy6nAETyp-QJ(S?jc(L_ov%X}lC`v0<9g*d}C>^8WpDMZkt7C>v{!)hoD} z1K%Ltms3Odw}N0#c?odkvB!8F>7ZSCsBJR3u~tEwn%XtDOaWzI!{ zF{e^}`UnnatXwPct}S(k3lqF74w>_{mhbZZ|EMef*JTBF+_U1=4G5s9Jh@e4pwZvN*W3w~ke8oV+Xc#y5Ln?V8td1&0#@!K;y&mNb zh;h9pp(k@Ms~|0VDHU%0P@}FW#oZ1F;E6v%CnHtSN6B=Ny|(Kz$K| zIx^%CV)r%z@_61&$|G*6QXR`)3YI%^*eE{jQiXUW^}V^P)hjXPsd{iiF(maEO+v8? zJf~#lDLx`_?(gk{16QMu0LPCzNh}`*kankONtCD>70fl8K zW2A+5!qT%{p-^R$Idk~GIyW=^20f-VlG2*O_ON{0@QWdAojv;-LWsc5(eqZRxfAcR z88q#scUkXN8I&yw__WJ>gfoFxF*^vn7e`Y}ay*5^TEXaokn&D>_@C3>Q4oY`$4%|b z+9`l3;|h#lSRSWuGb?bGZ8|mQWTCZe<33kn2^zyWyr7Q#% zOcxpH^V?$X!z)VdwX)vzGd)~~(W^wX^lns8Fup<5>j>b5H1Ou1g5dAMm)fW85D{u)AyEbs$T%a7Ism>#ol7eo%b$cD3XU79GeR`&qjRJ{;^2?Ox46q zk6%1lS{Dc5^;#oP+>M`FY47`q1M+R(6~g}DSS&{~;)~Qr!h{fPf9*fJz!@;sy>E`N zrBPIRZ{Pa%Gu!)) zD|=ufugfOu3ad6_0+w|SEbSNz$B%Zso44RIQ+-cmPj?DPb3q4PF1v`URd`YNEkq;t+Q|{E<|@1ikigUDBx@D#RvxeMwxylEA1)?F z)sLI%Y@&*s|9>@e7sea?o`{-O-%V(gSrQ{Z2Pl|s3s{QqS)S)^2&4Th(=9>7=^|=H zXoxG4KL`~ILul3X9|KSDBvrP>^(gF4TKCQ$cZH7)$N9t8#|pAc(Z|1YlmB%IQX4l3 zxyf3g%ZA^CE+}CAwS)~dnY0L{fxk!|58@k}>bZwFgE)3v8h|o>R0vq(YzbW!85QCx z{}$xjSu)Vai{z}2A+KD0aG0d)qo=DziDOG0ko-nutiD>sGHn3#sBg_(6R_}}AliPy z^tUk61wM&+BIBM48%lin@nzDgJf=!OtZ{~pKRij+i&S~0b}$3HH`OIP@9kV0pehUw#1rmUap`WfOa1!azM-a`_)ELGr$_6sdizlf1}J$ZZHTA5(|EW}k^YHM=j zu(lsHN{vYsK`_7dW8**ur)Q&NszVu{@K^$%xsQ7B66|7d#O9F~*zHg42=c%9i!D-B zf%d#5>)vG+&*2s{($7h(k8)qV2o&dZbrBdJ6o|~H1oQK5q8JYkC&tVg#5?f%4E{UG z$K%WQ072Roaq+sN=mY~RH-sjSD>Z$4v=)EzmzGj zw>79z53S;He(re*MgQf$*s=+x>cEt)vA_)_PM^UYFlYEF&mAJ5n&J)QBC@{5{3ky9 z$$-5&*KbpmVIX@-z&i8Po4OYacO^rVlBjPp#1;44t2&7!FU#?MlCIeLB$q9xEuwOv zNkV~&yN&Z)AYAZns&5mzuZ~Kz)*B95CxU3sh;o()q#QOqWUef(bc&w%hbzfm%?)cb z9Gr6tp06p|qwOi=U8zQ>X^4qci#-xLsBO*6L4+HxUZGEj{ybuJ@bIXwgpPy;{kj0iZJoOmW}%T&aV-2 zVDH%eIr&30oSLKU8Epxfud!TSWJQTP2uPmOE52N2bZmO6l=)=MaZp-!PbyE(uvM2q z3sW11`HATwuUP%jQLA;=dM-VrUBeSr%=3*QTY z;=~Y_d2dLQjH+fk#F#&EZ1B|%(nUUZE0EN1(3-lH&JO$5^b)5vE4&%BCTO&OJZXML zz$VVrx-N%6$gH5ZRT-9ApG$V$?IKVkjj)WRUZdR2%=e7d*Bhj~e6r5#CufFNa%@|( zL2D_>fW5xH6$=rse{%=dq|_aaXh20jZBIqsWF~)7e}n*f?@f;!$$JK_1=S z*C4biupRwcw}A355Mfj&z(?>%tc~v#xFDb>^6}dpRu4&h4mV1j90x?Dv@G-rVMbbd zXBzN%(_a*0d{bqu2b^Uq;Bejr!(f@lr70h1(aiTHb~Tqakh4Uktbv}6-l27N#uRiipeJ$Nub)L7_zsAzs?PPIFOgguk$oR$PRYgsL_s}#qjZ-U#cJYdX zcxzxf6XeMuiPp!t-&n!lFI$csT7}Xyo)DFfA~CnT<14eNoQDs$tBtc)5#Q}AZ#7L!OO+R8hE!XCL{l{FH zqb2^$*O90fE+6qqvPYG=SJFvVD4T2l)RXV(-uhfgKb64wN-MXX^dC;o>3X;w`3A!( zz5Ym-Qs*I?Wa-%Jh{|QeyhCC8)z^u>m;FeCX_5bVVP|!c|>o>l7Zig%HhxdMf|0&4u3vrj9m_HKPFqf11KW-S6A zw;_RO`RtSAo}X&F#YHT4qg7$pZrK&&@@|)E(s=N~orWlUI>`E=M~db`Msd{=<-7mUvYyBJa2k2>I9brD;&bL5_^j4~Wj{r!F6 z1-|C?Y@=uEmUK7XZOH13>uhOc>o_MN^Wody{_T+%%39};nXFG8oC&?JI1)#r6o{B= z>j`cA+DLkVvb%Ek>nm|j5ySq1JEHU_D%&FEr-p}Hm>!)E_}`tJ$Xw@=Nu^o;K0ML! zXrD+BxJr}hZtOU6d!i@ZeJrYRe9rIGMxr_y%C)+bEozsKb4ack>+CWgk{4uHE#cx* zM<-Ppb9Bm@KN9G}ov&D=FXpfD&%(Q`7C&!v^fGJ$^xh4HK^4x{2Pw1^$K<*-n{FCT z6x)?avEjJ!!CXP7C2=Z$kS5G3OnpYc3d64({)xX^|8DB4;PZl(2iR?ro%sOCTDBqG toLU&&kykjpr7z1`_$nrih>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/linux/flutter/CMakeLists.txt b/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..d5bd016 --- /dev/null +++ b/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..8492786 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,23 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) dynamic_color_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); + dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); + g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); + sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); + g_autoptr(FlPluginRegistrar) window_size_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin"); + window_size_plugin_register_with_registrar(window_size_registrar); +} diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..163e042 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,26 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + dynamic_color + sqlite3_flutter_libs + window_size +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/linux/main.cc b/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/my_application.cc b/linux/my_application.cc new file mode 100644 index 0000000..1f79b20 --- /dev/null +++ b/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "AdGuard Home Manager"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "AdGuard Home Manager"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/linux/my_application.h b/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ From 33125e543c327a3da95b57c1e63f3c0eb524b267 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 30 Apr 2023 20:18:29 +0200 Subject: [PATCH 045/676] Adapted servers list and connection screen --- lib/screens/connect/connect.dart | 1 + lib/screens/connect/fab.dart | 23 +- lib/screens/servers/servers.dart | 33 +- lib/widgets/add_server_modal.dart | 460 ++++++++++-------- lib/widgets/process_dialog.dart | 1 + lib/widgets/servers_list/servers_list.dart | 43 +- .../servers_list/servers_list_item.dart | 26 +- .../servers_list/servers_tile_item.dart | 381 +++++++++++++++ 8 files changed, 743 insertions(+), 225 deletions(-) create mode 100644 lib/widgets/servers_list/servers_tile_item.dart diff --git a/lib/screens/connect/connect.dart b/lib/screens/connect/connect.dart index ff55daf..0e19480 100644 --- a/lib/screens/connect/connect.dart +++ b/lib/screens/connect/connect.dart @@ -66,6 +66,7 @@ class _ConnectState extends State { controllers: expandableControllerList, onChange: expandOrContract, scrollController: scrollController, + breakingWidth: 700, ), AnimatedPositioned( duration: const Duration(milliseconds: 100), diff --git a/lib/screens/connect/fab.dart b/lib/screens/connect/fab.dart index 0c3204d..c20cafc 100644 --- a/lib/screens/connect/fab.dart +++ b/lib/screens/connect/fab.dart @@ -6,12 +6,27 @@ class FabConnect extends StatelessWidget { @override Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + void openAddServerModal() async { await Future.delayed(const Duration(seconds: 0), (() => { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => const AddServerModal() - )) + if (width > 700) { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => const AddServerModal( + window: true, + ), + ) + } + else { + Navigator.push(context, MaterialPageRoute( + fullscreenDialog: true, + builder: (BuildContext context) => const AddServerModal( + window: false, + ) + )) + } })); } diff --git a/lib/screens/servers/servers.dart b/lib/screens/servers/servers.dart index 9e98e29..ba1e7b3 100644 --- a/lib/screens/servers/servers.dart +++ b/lib/screens/servers/servers.dart @@ -13,7 +13,12 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class Servers extends StatefulWidget { - const Servers({Key? key}) : super(key: key); + final double? breakingWidth; + + const Servers({ + Key? key, + this.breakingWidth + }) : super(key: key); @override State createState() => _ServersState(); @@ -55,16 +60,31 @@ class _ServersState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + for (var i = 0; i < serversProvider.serversList.length; i++) { expandableControllerList.add(ExpandableController()); } void openAddServerModal() async { await Future.delayed(const Duration(seconds: 0), (() => { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => const AddServerModal() - )) + if (width > 700) { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => const AddServerModal( + window: true, + ), + ) + } + else { + Navigator.push(context, MaterialPageRoute( + fullscreenDialog: true, + builder: (BuildContext context) => const AddServerModal( + window: false, + ) + )) + } })); } @@ -79,7 +99,8 @@ class _ServersState extends State { context: context, controllers: expandableControllerList, onChange: expandOrContract, - scrollController: scrollController + scrollController: scrollController, + breakingWidth: widget.breakingWidth ?? 700, ), AnimatedPositioned( duration: const Duration(milliseconds: 100), diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 7fc830d..a332c58 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -16,10 +16,12 @@ enum ConnectionType { http, https} class AddServerModal extends StatefulWidget { final Server? server; + final bool window; const AddServerModal({ Key? key, this.server, + required this.window }) : super(key: key); @override @@ -429,15 +431,227 @@ class _AddServerModalState extends State { } } - return Stack( - children: [ - Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.createConnection), - actions: [ + List form() { + return [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + margin: const EdgeInsets.only( + top: 24, + left: 24, + right: 24 + ), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withOpacity(0.05), + borderRadius: BorderRadius.circular(30), + border: Border.all( + color: Theme.of(context).colorScheme.primary + ) + ), + child: Text( + "${connectionType.name}://${ipDomainController.text}${portController.text != '' ? ':${portController.text}' : ""}${pathController.text}", + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w500 + ), + ), + ), + sectionLabel(AppLocalizations.of(context)!.general), + textField( + label: AppLocalizations.of(context)!.name, + controller: nameController, + icon: Icons.badge_rounded, + error: nameError, + onChanged: (value) { + if (value != '') { + setState(() => nameError = null); + } + else { + setState(() => nameError = AppLocalizations.of(context)!.nameNotEmpty); + } + checkDataValid(); + } + ), + sectionLabel(AppLocalizations.of(context)!.connection), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: SegmentedButton( + segments: const [ + ButtonSegment( + value: ConnectionType.http, + label: Text("HTTP") + ), + ButtonSegment( + value: ConnectionType.https, + label: Text("HTTPS") + ), + ], + selected: {connectionType}, + onSelectionChanged: (value) => setState(() => connectionType = value.first), + ), + ), + const SizedBox(height: 30), + textField( + label: AppLocalizations.of(context)!.ipDomain, + controller: ipDomainController, + icon: Icons.link_rounded, + error: ipDomainError, + keyboardType: TextInputType.url, + onChanged: validateAddress + ), + const SizedBox(height: 20), + textField( + label: AppLocalizations.of(context)!.path, + controller: pathController, + icon: Icons.route_rounded, + error: pathError, + onChanged: validateSubroute, + hintText: AppLocalizations.of(context)!.examplePath, + helperText: AppLocalizations.of(context)!.helperPath, + ), + const SizedBox(height: 20), + textField( + label: AppLocalizations.of(context)!.port, + controller: portController, + icon: Icons.numbers_rounded, + error: portError, + keyboardType: TextInputType.number, + onChanged: validatePort + ), + sectionLabel(AppLocalizations.of(context)!.authentication), + textField( + label: AppLocalizations.of(context)!.username, + controller: userController, + icon: Icons.person_rounded, + ), + const SizedBox(height: 20), + textField( + label: AppLocalizations.of(context)!.password, + controller: passwordController, + icon: Icons.lock_rounded, + keyboardType: TextInputType.visiblePassword, + obscureText: true + ), + sectionLabel(AppLocalizations.of(context)!.other), + Material( + color: Colors.transparent, + child: InkWell( + onTap: widget.server == null + ? () => setState(() => defaultServer = !defaultServer) + : null, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.defaultServer, + style: const TextStyle( + fontSize: 15, + ), + ), + Switch( + value: defaultServer, + onChanged: widget.server == null + ? (value) => setState(() => defaultServer = value) + : null, + ) + ], + ), + ), + ), + ), + const SizedBox(height: 20), + Material( + color: Colors.transparent, + child: InkWell( + onTap: () => setState(() => homeAssistant = !homeAssistant), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.runningHomeAssistant, + style: const TextStyle( + fontSize: 15, + ), + ), + Switch( + value: homeAssistant, + onChanged: (value) => setState(() => homeAssistant = value), + ) + ], + ), + ), + ), + ), + const SizedBox(height: 20), + ]; + } + + if (widget.window == true) { + return Dialog( + child: SizedBox( + width: 400, + child: Column( + children: [ Padding( - padding: const EdgeInsets.only(right: 10), - child: IconButton( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded) + ), + const SizedBox(width: 8), + Text( + AppLocalizations.of(context)!.createConnection, + style: const TextStyle( + fontSize: 20 + ), + ), + ], + ), + IconButton( + tooltip: widget.server == null + ? AppLocalizations.of(context)!.connect + : AppLocalizations.of(context)!.save, + onPressed: allDataValid == true + ? widget.server == null + ? () => connect() + : () => edit() + : null, + icon: Icon( + widget.server == null + ? Icons.login_rounded + : Icons.save_rounded + ) + ), + ], + ), + ), + Expanded( + child: ListView( + children: form() + ), + ) + ], + ), + ), + ); + } + else { + return Stack( + children: [ + Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.createConnection), + actions: [ + IconButton( tooltip: widget.server == null ? AppLocalizations.of(context)!.connect : AppLocalizations.of(context)!.save, @@ -452,203 +666,49 @@ class _AddServerModalState extends State { : Icons.save_rounded ) ), - ), - ], - toolbarHeight: 70, + const SizedBox(width: 10) + ], + toolbarHeight: 70, + ), + body: ListView( + children: form(), + ) ), - body: ListView( - children: [ - Container( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), - margin: const EdgeInsets.only( - top: 24, - left: 24, - right: 24 - ), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withOpacity(0.05), - borderRadius: BorderRadius.circular(30), - border: Border.all( - color: Theme.of(context).colorScheme.primary - ) - ), - child: Text( - "${connectionType.name}://${ipDomainController.text}${portController.text != '' ? ':${portController.text}' : ""}${pathController.text}", - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.w500 - ), - ), - ), - sectionLabel(AppLocalizations.of(context)!.general), - textField( - label: AppLocalizations.of(context)!.name, - controller: nameController, - icon: Icons.badge_rounded, - error: nameError, - onChanged: (value) { - if (value != '') { - setState(() => nameError = null); - } - else { - setState(() => nameError = AppLocalizations.of(context)!.nameNotEmpty); - } - checkDataValid(); - } - ), - sectionLabel(AppLocalizations.of(context)!.connection), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: SegmentedButton( - segments: const [ - ButtonSegment( - value: ConnectionType.http, - label: Text("HTTP") - ), - ButtonSegment( - value: ConnectionType.https, - label: Text("HTTPS") - ), - ], - selected: {connectionType}, - onSelectionChanged: (value) => setState(() => connectionType = value.first), - ), - ), - const SizedBox(height: 30), - textField( - label: AppLocalizations.of(context)!.ipDomain, - controller: ipDomainController, - icon: Icons.link_rounded, - error: ipDomainError, - keyboardType: TextInputType.url, - onChanged: validateAddress - ), - const SizedBox(height: 20), - textField( - label: AppLocalizations.of(context)!.path, - controller: pathController, - icon: Icons.route_rounded, - error: pathError, - onChanged: validateSubroute, - hintText: AppLocalizations.of(context)!.examplePath, - helperText: AppLocalizations.of(context)!.helperPath, - ), - const SizedBox(height: 20), - textField( - label: AppLocalizations.of(context)!.port, - controller: portController, - icon: Icons.numbers_rounded, - error: portError, - keyboardType: TextInputType.number, - onChanged: validatePort - ), - sectionLabel(AppLocalizations.of(context)!.authentication), - textField( - label: AppLocalizations.of(context)!.username, - controller: userController, - icon: Icons.person_rounded, - ), - const SizedBox(height: 20), - textField( - label: AppLocalizations.of(context)!.password, - controller: passwordController, - icon: Icons.lock_rounded, - keyboardType: TextInputType.visiblePassword, - obscureText: true - ), - sectionLabel(AppLocalizations.of(context)!.other), - Material( - color: Colors.transparent, - child: InkWell( - onTap: widget.server == null - ? () => setState(() => defaultServer = !defaultServer) - : null, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.defaultServer, - style: const TextStyle( - fontSize: 15, - ), - ), - Switch( - value: defaultServer, - onChanged: widget.server == null - ? (value) => setState(() => defaultServer = value) - : null, - ) - ], - ), - ), - ), - ), - const SizedBox(height: 20), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => setState(() => homeAssistant = !homeAssistant), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.runningHomeAssistant, - style: const TextStyle( - fontSize: 15, - ), - ), - Switch( - value: homeAssistant, - onChanged: (value) => setState(() => homeAssistant = value), - ) - ], - ), - ), - ), - ), - const SizedBox(height: 20), - ], - ), - ), - AnimatedOpacity( - opacity: isConnecting == true ? 1 : 0, - duration: const Duration(milliseconds: 250), - curve: Curves.easeInOut, - child: IgnorePointer( - ignoring: isConnecting == true ? false : true, - child: Scaffold( - backgroundColor: Colors.transparent, - body: Container( - width: mediaQuery.size.width, - height: mediaQuery.size.height, - color: const Color.fromRGBO(0, 0, 0, 0.7), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const CircularProgressIndicator( - color: Colors.white, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.connecting, - style: const TextStyle( + AnimatedOpacity( + opacity: isConnecting == true ? 1 : 0, + duration: const Duration(milliseconds: 250), + curve: Curves.easeInOut, + child: IgnorePointer( + ignoring: isConnecting == true ? false : true, + child: Scaffold( + backgroundColor: Colors.transparent, + body: Container( + width: mediaQuery.size.width, + height: mediaQuery.size.height, + color: const Color.fromRGBO(0, 0, 0, 0.7), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const CircularProgressIndicator( color: Colors.white, - fontWeight: FontWeight.w500, - fontSize: 26 ), - ) - ], + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.connecting, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w500, + fontSize: 26 + ), + ) + ], + ), ), ), ), - ), - ) - ], - ); + ) + ], + ); + } } } \ No newline at end of file diff --git a/lib/widgets/process_dialog.dart b/lib/widgets/process_dialog.dart index 84c1185..d8794d8 100644 --- a/lib/widgets/process_dialog.dart +++ b/lib/widgets/process_dialog.dart @@ -20,6 +20,7 @@ class ProcessDialog extends StatelessWidget { horizontal: 30 ), child: Row( + mainAxisSize: MainAxisSize.min, children: [ const CircularProgressIndicator(), const SizedBox(width: 40), diff --git a/lib/widgets/servers_list/servers_list.dart b/lib/widgets/servers_list/servers_list.dart index c69f5ed..d4cd9cf 100644 --- a/lib/widgets/servers_list/servers_list.dart +++ b/lib/widgets/servers_list/servers_list.dart @@ -5,6 +5,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/servers_list/servers_list_item.dart'; +import 'package:adguard_home_manager/widgets/servers_list/servers_tile_item.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -13,6 +14,7 @@ class ServersList extends StatelessWidget { final List controllers; final Function(int) onChange; final ScrollController scrollController; + final double breakingWidth; const ServersList({ Key? key, @@ -20,23 +22,44 @@ class ServersList extends StatelessWidget { required this.controllers, required this.onChange, required this.scrollController, + required this.breakingWidth }) : super(key: key); @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; if (serversProvider.serversList.isNotEmpty) { - return ListView.builder( - controller: scrollController, - itemCount: serversProvider.serversList.length, - itemBuilder: (context, index) => ServersListItem( - expandableController: controllers[index], - server: serversProvider.serversList[index], - index: index, - onChange: onChange - ) - ); + if (width > breakingWidth) { + return ListView( + children: [ + Wrap( + children: serversProvider.serversList.asMap().entries.map( + (s) => ServersTileItem( + server: serversProvider.serversList[s.key], + index: s.key, + onChange: onChange + ) + ).toList(), + ), + const SizedBox(height: 8) + ], + ); + } + else { + return ListView.builder( + controller: scrollController, + itemCount: serversProvider.serversList.length, + itemBuilder: (context, index) => ServersListItem( + expandableController: controllers[index], + server: serversProvider.serversList[index], + index: index, + onChange: onChange + ) + ); + } } else { return SizedBox( diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 919a680..20b9551 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -71,6 +71,8 @@ class _ServersListItemState extends State with SingleTickerProv final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void showDeleteModal(Server server) async { await Future.delayed(const Duration(seconds: 0), () => { showDialog( @@ -85,10 +87,25 @@ class _ServersListItemState extends State with SingleTickerProv void openAddServerBottomSheet({Server? server}) async { await Future.delayed(const Duration(seconds: 0), (() => { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => AddServerModal(server: server) - )) + if (width > 700) { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => AddServerModal( + server: server, + window: true, + ), + ) + } + else { + Navigator.push(context, MaterialPageRoute( + fullscreenDialog: true, + builder: (BuildContext context) => AddServerModal( + server: server, + window: false, + ) + )) + } })); } @@ -356,7 +373,6 @@ class _ServersListItemState extends State with SingleTickerProv ); } - return Container( decoration: BoxDecoration( border: Border( diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart new file mode 100644 index 0000000..bf67b6f --- /dev/null +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -0,0 +1,381 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/add_server_modal.dart'; +import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/app_log.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/models/server.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class ServersTileItem extends StatefulWidget { + final Server server; + final int index; + final void Function(int) onChange; + + const ServersTileItem({ + Key? key, + required this.server, + required this.index, + required this.onChange + }) : super(key: key); + + @override + State createState() => _ServersTileItemState(); +} + +class _ServersTileItemState extends State with SingleTickerProviderStateMixin { + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; + + void showDeleteModal(Server server) async { + await Future.delayed(const Duration(seconds: 0), () => { + showDialog( + context: context, + builder: (context) => DeleteModal( + serverToDelete: server, + ), + barrierDismissible: false + ) + }); + } + + void openAddServerBottomSheet({Server? server}) async { + await Future.delayed(const Duration(seconds: 0), (() => { + if (width > 700) { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => AddServerModal( + server: server, + window: true, + ), + ) + } + else { + Navigator.push(context, MaterialPageRoute( + fullscreenDialog: true, + builder: (BuildContext context) => AddServerModal( + server: server, + window: false, + ) + )) + } + })); + } + + void connectToServer(Server server) async { + final ProcessModal process = ProcessModal(context: context); + process.open(AppLocalizations.of(context)!.connecting); + + final result = server.runningOnHa == true + ? await loginHA(server) + : await login(server); + + if (result['result'] == 'success') { + serversProvider.setSelectedServer(server); + + serversProvider.setServerStatusLoad(0); + final serverStatus = await getServerStatus(server); + if (serverStatus['result'] == 'success') { + serversProvider.setServerStatusData(serverStatus['data']); + serversProvider.checkServerUpdatesAvailable(server); + serversProvider.setServerStatusLoad(1); + } + else { + appConfigProvider.addLog(serverStatus['log']); + serversProvider.setServerStatusLoad(2); + } + + process.close(); + } + else { + process.close(); + appConfigProvider.addLog(result['log']); + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.cannotConnect, + color: Colors.red + ); + } + } + + void setDefaultServer(Server server) async { + final result = await serversProvider.setDefaultServer(server); + if (result == null) { + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, + color: Colors.green + ); + } + else { + appConfigProvider.addLog( + AppLog( + type: 'set_default_server', + dateTime: DateTime.now(), + message: result.toString() + ) + ); + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionDefaultFailed, + color: Colors.red + ); + } + } + + Widget leadingIcon(Server server) { + if (server.defaultServer == true) { + return Stack( + alignment: Alignment.center, + children: [ + Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? serversProvider.serverStatus.data != null + ? Colors.green + : Colors.orange + : null, + ), + SizedBox( + width: 25, + height: 25, + child: Stack( + alignment: Alignment.bottomRight, + children: [ + Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(20) + ), + child: Icon( + Icons.star, + color: Theme.of(context).colorScheme.onPrimaryContainer, + size: 10, + ), + ), + ], + ), + ) + ], + ); + } + else { + return Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? serversProvider.serverStatus.data != null + ? Colors.green + : Colors.orange + : null, + ); + } + } + + Widget topRow(Server server, int index) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 16), + child: leadingIcon(server), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", + textAlign: TextAlign.left, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Column( + children: [ + const SizedBox(height: 3), + Text( + server.name, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ) + ], + ), + ), + ], + ), + ), + ], + ); + } + + Widget bottomRow(Server server, int index) { + return Column( + children: [ + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + PopupMenuButton( + // color: Theme.of(context).dialogBackgroundColor, + itemBuilder: (context) => [ + PopupMenuItem( + enabled: server.defaultServer == false + ? true + : false, + onTap: server.defaultServer == false + ? (() => setDefaultServer(server)) + : null, + child: SizedBox( + child: Row( + children: [ + const Icon(Icons.star), + const SizedBox(width: 15), + Text( + server.defaultServer == true + ? AppLocalizations.of(context)!.defaultConnection + : AppLocalizations.of(context)!.setDefault, + ) + ], + ), + ) + ), + PopupMenuItem( + onTap: (() => openAddServerBottomSheet(server: server)), + child: Row( + children: [ + const Icon(Icons.edit), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.edit) + ], + ) + ), + PopupMenuItem( + onTap: (() => showDeleteModal(server)), + child: Row( + children: [ + const Icon(Icons.delete), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.delete) + ], + ) + ), + ] + ), + SizedBox( + child: serversProvider.selectedServer != null && + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null && + serversProvider.selectedServer?.id == server.id + ? Container( + margin: const EdgeInsets.only(right: 12), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + decoration: BoxDecoration( + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null + ? Colors.green + : Colors.orange, + borderRadius: BorderRadius.circular(30) + ), + child: Row( + children: [ + Icon( + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null + ? Icons.check + : Icons.warning, + color: Colors.white, + ), + const SizedBox(width: 10), + Text( + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null + ? AppLocalizations.of(context)!.connected + : AppLocalizations.of(context)!.selectedDisconnected, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w500 + ), + ) + ], + ), + ) + : Container( + margin: const EdgeInsets.only(right: 10), + child: TextButton( + onPressed: () => connectToServer(server), + child: Text(AppLocalizations.of(context)!.connect), + ), + ), + ) + ], + ) + ], + ); + } + + EdgeInsets generateMargins(int index) { + if (index == 0) { + return const EdgeInsets.only(top: 16, left: 16, right: 8, bottom: 8); + } + if (index == 1) { + return const EdgeInsets.only(top: 16, left: 8, right: 16, bottom: 8); + } + else if (index == serversProvider.serversList.length-1 && (index+1)%2 == 0) { + return const EdgeInsets.only(top: 8, left: 8, right: 16, bottom: 16); + } + else if (index == serversProvider.serversList.length-1 && (index+1)%2 == 1) { + return const EdgeInsets.only(top: 8, left: 16, right: 8, bottom: 16); + } + else { + if ((index+1)%2 == 0) { + return const EdgeInsets.only(top: 8, left: 8, right: 16, bottom: 8); + } + else { + return const EdgeInsets.only(top: 8, left: 16, right: 8, bottom: 8); + } + } + } + + return FractionallySizedBox( + widthFactor: 0.5, + child: Card( + margin: generateMargins(widget.index), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + topRow(widget.server, widget.index), + bottomRow(widget.server, widget.index) + ], + ), + ), + ), + ); + } +} \ No newline at end of file From aefdac565068416d68e64255dbde9071d7aba9e2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 30 Apr 2023 20:26:10 +0200 Subject: [PATCH 046/676] Added navigation rail --- lib/base.dart | 34 ++++++++++------ lib/widgets/navigation_rail.dart | 67 ++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 lib/widgets/navigation_rail.dart diff --git a/lib/base.dart b/lib/base.dart index 509df8e..c4c3c68 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -12,6 +12,7 @@ import 'package:flutter/services.dart'; import 'package:adguard_home_manager/widgets/bottom_nav_bar.dart'; import 'package:adguard_home_manager/widgets/update_modal.dart'; +import 'package:adguard_home_manager/widgets/navigation_rail.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/github_release.dart'; @@ -110,6 +111,8 @@ class _BaseState extends State with WidgetsBindingObserver { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + List screens = serversProvider.selectedServer != null ? screensServerConnected : screensSelectServer; @@ -129,18 +132,27 @@ class _BaseState extends State with WidgetsBindingObserver { : Brightness.light, ), child: Scaffold( - body: PageTransitionSwitcher( - duration: const Duration(milliseconds: 200), - transitionBuilder: ( - (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( - animation: primaryAnimation, - secondaryAnimation: secondaryAnimation, - child: child, - ) - ), - child: screens[appConfigProvider.selectedScreen].body, + body: Row( + children: [ + if (width > 900) const SideNavigationRail(), + Expanded( + child: PageTransitionSwitcher( + duration: const Duration(milliseconds: 200), + transitionBuilder: ( + (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( + animation: primaryAnimation, + secondaryAnimation: secondaryAnimation, + child: child, + ) + ), + child: screens[appConfigProvider.selectedScreen].body, + ), + ), + ], ), - bottomNavigationBar: const BottomNavBar(), + bottomNavigationBar: width <= 900 + ? const BottomNavBar() + : null, ) ); } diff --git a/lib/widgets/navigation_rail.dart b/lib/widgets/navigation_rail.dart new file mode 100644 index 0000000..a63b18e --- /dev/null +++ b/lib/widgets/navigation_rail.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/config/app_screens.dart'; +import 'package:adguard_home_manager/models/app_screen.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class SideNavigationRail extends StatelessWidget { + const SideNavigationRail({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + List screens = serversProvider.selectedServer != null + ? screensServerConnected + : screensSelectServer; + + String translatedName(String key) { + switch (key) { + case 'home': + return AppLocalizations.of(context)!.home; + + case 'settings': + return AppLocalizations.of(context)!.settings; + + case 'connect': + return AppLocalizations.of(context)!.connect; + + case 'clients': + return AppLocalizations.of(context)!.clients; + + case 'logs': + return AppLocalizations.of(context)!.logs; + + case 'filters': + return AppLocalizations.of(context)!.filters; + + default: + return ''; + } + } + + return NavigationRail( + selectedIndex: appConfigProvider.selectedScreen, + destinations: screens.map((screen) => NavigationRailDestination( + icon: Icon( + screen.icon, + color: screens[appConfigProvider.selectedScreen] == screen + ? Theme.of(context).colorScheme.onSecondaryContainer + : Theme.of(context).colorScheme.onSurfaceVariant, + ), + label: Text(translatedName(screen.name)) + )).toList(), + onDestinationSelected: (value) { + appConfigProvider.setSelectedScreen(value); + }, + labelType: NavigationRailLabelType.all, + useIndicator: true, + groupAlignment: 0, + backgroundColor: Theme.of(context).colorScheme.primary.withOpacity(0.05), + ); + } +} \ No newline at end of file From ef43f8b5dd50d4af672b208eb539566bca2fb9d8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 30 Apr 2023 22:54:39 +0200 Subject: [PATCH 047/676] Responsive navigation settings --- lib/providers/app_config_provider.dart | 11 ++ .../access_settings/access_settings.dart | 2 +- lib/screens/settings/dhcp/dhcp.dart | 2 +- .../settings/safe_search_settings.dart | 36 ++-- lib/screens/settings/settings.dart | 180 +++++++++--------- lib/widgets/bottom_nav_bar.dart | 4 + lib/widgets/custom_settings_tile.dart | 120 ++++++++++++ lib/widgets/navigation_rail.dart | 14 ++ lib/widgets/servers_list/delete_modal.dart | 8 + pubspec.lock | 8 + pubspec.yaml | 1 + 11 files changed, 273 insertions(+), 113 deletions(-) create mode 100644 lib/widgets/custom_settings_tile.dart diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 1952d9b..0dc8ac3 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -17,6 +17,8 @@ class AppConfigProvider with ChangeNotifier { int _selectedScreen = 0; + int? _selectedSettingsScreen; + bool _showingSnackbar = false; int _selectedTheme = 0; @@ -119,6 +121,10 @@ class AppConfigProvider with ChangeNotifier { return _doNotRememberVersion; } + int? get selectedSettingsScreen { + return _selectedSettingsScreen; + } + void setDbInstance(Database db) { _dbInstance = db; } @@ -160,6 +166,11 @@ class AppConfigProvider with ChangeNotifier { notifyListeners(); } + void setSelectedSettingsScreen(int? screen) { + _selectedSettingsScreen = screen; + notifyListeners(); + } + Future setOverrideSslCheck(bool status) async { final updated = await updateConfigQuery( db: _dbInstance!, diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index 9fc8a86..aed54f0 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -60,7 +60,7 @@ class _AccessSettingsWidgetState extends State with Ticker @override void initState() { - fetchClients(); + if (mounted) fetchClients(); super.initState(); tabController = TabController( initialIndex: 0, diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index a4a8319..5546398 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -204,7 +204,7 @@ class _DhcpWidgetState extends State { @override void initState() { - loadDhcpStatus(); + if (mounted) loadDhcpStatus(); super.initState(); } diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index cefd757..fe428fa 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -52,24 +52,26 @@ class _SafeSearchSettingsScreenWidgetState extends State(context); final serversProvider = Provider.of(context); - void navigateServers() { - Future.delayed(const Duration(milliseconds: 0), (() { - Navigator.of(context).push( - MaterialPageRoute(builder: (context) => const Servers()) + final width = MediaQuery.of(context).size.width; + + Widget settingsTile({ + required String title, + required String subtitle, + required IconData icon, + Widget? trailing, + required Widget screenToNavigate, + required int thisItem + }) { + if (width > 900) { + return CustomSettingsTile( + title: title, + subtitle: subtitle, + icon: icon, + trailing: trailing, + thisItem: thisItem, + selectedItem: appConfigProvider.selectedSettingsScreen, + onTap: () { + appConfigProvider.setSelectedSettingsScreen(thisItem); + SplitView.of(context).setSecondary(screenToNavigate); + }, ); - })); - } + } + else { + return CustomListTile( + title: title, + subtitle: subtitle, + icon: icon, + trailing: trailing, + onTap: () { + appConfigProvider.setSelectedSettingsScreen(thisItem); + SplitView.of(context).setSecondary(screenToNavigate); + }, + ); + } + } return Scaffold( appBar: AppBar( @@ -55,79 +97,49 @@ class Settings extends StatelessWidget { currentVersion: serversProvider.serverStatus.data!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' - ) == true) CustomListTile( + ) == true) settingsTile( icon: Icons.search_rounded, title: AppLocalizations.of(context)!.safeSearch, subtitle: AppLocalizations.of(context)!.safeSearchSettings, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const SafeSearchSettingsScreen() - ) - ) - }, + thisItem: 0, + screenToNavigate: const SafeSearchSettingsScreen(), ), - CustomListTile( + settingsTile( icon: Icons.lock_rounded, title: AppLocalizations.of(context)!.accessSettings, subtitle: AppLocalizations.of(context)!.accessSettingsDescription, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const AccessSettings() - ) - ) - }, + thisItem: 1, + screenToNavigate: const AccessSettings(), ), - CustomListTile( + settingsTile( icon: Icons.install_desktop_rounded, title: AppLocalizations.of(context)!.dhcpSettings, subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const Dhcp() - ) - ) - }, + thisItem: 2, + screenToNavigate: const Dhcp(), ), - CustomListTile( + settingsTile( icon: Icons.dns_rounded, title: AppLocalizations.of(context)!.dnsSettings, subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const DnsSettings() - ) - ) - }, + thisItem: 3, + screenToNavigate: const DnsSettings(), ), - CustomListTile( + settingsTile( icon: Icons.security_rounded, title: AppLocalizations.of(context)!.encryptionSettings, subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const EncryptionSettings() - ) - ) - }, + thisItem: 4, + screenToNavigate: const EncryptionSettings(), ), - CustomListTile( + settingsTile( icon: Icons.route_rounded, title: AppLocalizations.of(context)!.dnsRewrites, subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const DnsRewrites() - ) - ) - }, + thisItem: 5, + screenToNavigate: const DnsRewrites(), ), - if (serversProvider.updateAvailable.data != null) CustomListTile( + if (serversProvider.updateAvailable.data != null) settingsTile( icon: Icons.system_update_rounded, title: AppLocalizations.of(context)!.updates, subtitle: AppLocalizations.of(context)!.updatesDescription, @@ -144,37 +156,26 @@ class Settings extends StatelessWidget { ), ) : null, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const UpdateScreen() - ) - ) - }, + thisItem: 6, + screenToNavigate: const UpdateScreen(), ), - CustomListTile( + settingsTile( icon: Icons.info_rounded, title: AppLocalizations.of(context)!.serverInformation, subtitle: AppLocalizations.of(context)!.serverInformationDescription, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const ServerInformation() - ) - ) - }, + thisItem: 7, + screenToNavigate: const ServerInformation(), ), ], SectionLabel(label: AppLocalizations.of(context)!.appSettings), - CustomListTile( + settingsTile( icon: Icons.palette_rounded, title: AppLocalizations.of(context)!.customization, subtitle: AppLocalizations.of(context)!.customizationDescription, - onTap: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => const Customization() - )) + thisItem: 8, + screenToNavigate: const Customization(), ), - CustomListTile( + settingsTile( icon: Icons.storage_rounded, title: AppLocalizations.of(context)!.servers, subtitle: serversProvider.selectedServer != null @@ -182,31 +183,22 @@ class Settings extends StatelessWidget { ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" : AppLocalizations.of(context)!.noServerSelected, - onTap: navigateServers, + thisItem: 9, + screenToNavigate: const Servers(), ), - CustomListTile( + settingsTile( icon: Icons.settings, title: AppLocalizations.of(context)!.generalSettings, subtitle: AppLocalizations.of(context)!.generalSettingsDescription, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const GeneralSettings() - ) - ) - }, + thisItem: 10, + screenToNavigate: const GeneralSettings(), ), - CustomListTile( + settingsTile( icon: Icons.build_outlined, title: AppLocalizations.of(context)!.advancedSettings, subtitle: AppLocalizations.of(context)!.advancedSetupDescription, - onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const AdvancedSettings() - ) - ) - }, + thisItem: 11, + screenToNavigate: const AdvancedSettings(), ), SectionLabel(label: AppLocalizations.of(context)!.aboutApp), CustomListTile( diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index 5793442..b5511c1 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -89,6 +89,10 @@ class BottomNavBar extends StatelessWidget { if (value != 2) { logsProvider.resetFilters(); } + // Reset settings selected screen + if (value != screens.length-1) { + appConfigProvider.setSelectedSettingsScreen(null); + } appConfigProvider.setSelectedScreen(value); }, ); diff --git a/lib/widgets/custom_settings_tile.dart b/lib/widgets/custom_settings_tile.dart new file mode 100644 index 0000000..276d517 --- /dev/null +++ b/lib/widgets/custom_settings_tile.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; + +class CustomSettingsTile extends StatelessWidget { + final String title; + final String? subtitle; + final Widget? subtitleWidget; + final void Function()? onTap; + final IconData? icon; + final Widget? trailing; + final EdgeInsets? padding; + final int thisItem; + final int? selectedItem; + + const CustomSettingsTile({ + Key? key, + required this.title, + this.subtitle, + this.subtitleWidget, + this.onTap, + this.icon, + this.trailing, + this.padding, + required this.thisItem, + required this.selectedItem, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + + Widget tileBody = Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (icon != null) ...[ + Icon( + icon, + size: 24, + color: Theme.of(context).listTileTheme.iconColor, + ), + const SizedBox(width: 16), + ], + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + if (subtitle != null || subtitleWidget != null) ...[ + const SizedBox(height: 5), + if (subtitle == null && subtitleWidget != null) subtitleWidget!, + if (subtitle != null && subtitleWidget == null) Text( + subtitle!, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 14, + fontWeight: FontWeight.w400 + ), + ), + ] + ], + ), + ) + ], + ), + ), + if (trailing != null) ...[ + const SizedBox(width: 10), + trailing! + ] + ], + ); + + if (width < 700) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: tileBody, + ) + ), + ); + } + else { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + borderRadius: BorderRadius.circular(28), + onTap: onTap, + child: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: thisItem == selectedItem + ? Theme.of(context).colorScheme.primaryContainer + : null + ), + child: tileBody + ), + ), + ), + ); + } + } +} \ No newline at end of file diff --git a/lib/widgets/navigation_rail.dart b/lib/widgets/navigation_rail.dart index a63b18e..4837e0f 100644 --- a/lib/widgets/navigation_rail.dart +++ b/lib/widgets/navigation_rail.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; import 'package:adguard_home_manager/models/app_screen.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -14,6 +15,7 @@ class SideNavigationRail extends StatelessWidget { Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final logsProvider = Provider.of(context); List screens = serversProvider.selectedServer != null ? screensServerConnected @@ -56,6 +58,18 @@ class SideNavigationRail extends StatelessWidget { label: Text(translatedName(screen.name)) )).toList(), onDestinationSelected: (value) { + // Reset clients tab to 0 when changing screen + if (value != 1) { + appConfigProvider.setSelectedClientsTab(0); + } + // Reset logs filters when changing screen + if (value != 2) { + logsProvider.resetFilters(); + } + // Reset settings selected screen + if (value != screens.length-1) { + appConfigProvider.setSelectedSettingsScreen(null); + } appConfigProvider.setSelectedScreen(value); }, labelType: NavigationRailLabelType.all, diff --git a/lib/widgets/servers_list/delete_modal.dart b/lib/widgets/servers_list/delete_modal.dart index 2cc9809..9d51fe3 100644 --- a/lib/widgets/servers_list/delete_modal.dart +++ b/lib/widgets/servers_list/delete_modal.dart @@ -23,9 +23,17 @@ class DeleteModal extends StatelessWidget { final appConfigProvider = Provider.of(context); void removeServer() async { + final previouslySelectedServer = serversProvider.selectedServer; + final deleted = await serversProvider.removeServer(serverToDelete); + Navigator.pop(context); + if (deleted == true) { + if (previouslySelectedServer != null && previouslySelectedServer.id == serverToDelete.id) { + appConfigProvider.setSelectedScreen(0); + } + showSnacbkar( context: context, appConfigProvider: appConfigProvider, diff --git a/pubspec.lock b/pubspec.lock index f28102c..3718b7c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -291,6 +291,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.17" + flutter_split_view: + dependency: "direct main" + description: + name: flutter_split_view + sha256: "0fb1f3aa6a6f2031d936ae5596fc5178affacdc7d793b27cdbc191a1ae8e56bf" + url: "https://pub.dev" + source: hosted + version: "0.1.2" flutter_svg: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index c30c9a1..ba3e38e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,6 +60,7 @@ dependencies: git: url: https://github.com/google/flutter-desktop-embedding path: plugins/window_size + flutter_split_view: ^0.1.2 dev_dependencies: flutter_test: From bc8e74be6d8037f6695054e6d9c8e72ea65d5d3a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 30 Apr 2023 23:36:02 +0200 Subject: [PATCH 048/676] Optimized access settings --- .../access_settings/access_settings.dart | 182 ++++++++------ .../access_settings/add_client_modal.dart | 114 +++++---- .../access_settings/clients_list.dart | 36 ++- lib/widgets/tab_content_list.dart | 225 +++++++++++------- 4 files changed, 350 insertions(+), 207 deletions(-) diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index aed54f0..9f03328 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -60,7 +62,7 @@ class _AccessSettingsWidgetState extends State with Ticker @override void initState() { - if (mounted) fetchClients(); + fetchClients(); super.initState(); tabController = TabController( initialIndex: 0, @@ -72,78 +74,114 @@ class _AccessSettingsWidgetState extends State with Ticker @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); - return Scaffold( - body: DefaultTabController( - length: 3, - child: NestedScrollView( - controller: scrollController, - headerSliverBuilder: ((context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverSafeArea( - top: false, - sliver: SliverAppBar( - title: Text(AppLocalizations.of(context)!.accessSettings), - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - bottom: TabBar( - controller: tabController, - isScrollable: true, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - icon: const Icon(Icons.check), - text: AppLocalizations.of(context)!.allowedClients, - ), - Tab( - icon: const Icon(Icons.block), - text: AppLocalizations.of(context)!.disallowedClients, - ), - Tab( - icon: const Icon(Icons.link_rounded), - text: AppLocalizations.of(context)!.disallowedDomains, - ), - ] - ) + + Widget body() { + return TabBarView( + controller: tabController, + children: [ + ClientsList( + type: 'allowed', + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == LoadStatus.loaded + ? serversProvider.clients.data!.clientsAllowedBlocked!.allowedClients : [], + fetchClients: fetchClients + ), + ClientsList( + type: 'disallowed', + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == LoadStatus.loaded + ? serversProvider.clients.data!.clientsAllowedBlocked!.disallowedClients : [], + fetchClients: fetchClients + ), + ClientsList( + type: 'domains', + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == LoadStatus.loaded + ? serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts : [], + fetchClients: fetchClients + ), + ] + ); + } + + PreferredSizeWidget tabBar() { + return TabBar( + controller: tabController, + isScrollable: true, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + child: Row( + children: [ + const Icon(Icons.check), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.allowedClients) + ], + ), + ), + Tab( + child: Row( + children: [ + const Icon(Icons.block), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.disallowedClients) + ], + ), + ), + Tab( + child: Row( + children: [ + const Icon(Icons.link_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.disallowedDomains) + ], + ), + ), + ] + ); + } + + if (Platform.isAndroid || Platform.isIOS) { + return Scaffold( + body: DefaultTabController( + length: 3, + child: NestedScrollView( + controller: scrollController, + headerSliverBuilder: ((context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverSafeArea( + top: false, + sliver: SliverAppBar( + title: Text(AppLocalizations.of(context)!.accessSettings), + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + bottom: tabBar() + ), ), - ), - ) - ]; - }), - body: TabBarView( - controller: tabController, - children: [ - ClientsList( - type: 'allowed', - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clientsAllowedBlocked!.allowedClients : [], - fetchClients: fetchClients - ), - ClientsList( - type: 'disallowed', - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clientsAllowedBlocked!.disallowedClients : [], - fetchClients: fetchClients - ), - ClientsList( - type: 'domains', - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts : [], - fetchClients: fetchClients - ), - ] + ) + ]; + }), + body: body() ) - ) - ), - ); + ), + ); + } + else { + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.accessSettings), + centerTitle: false, + bottom: tabBar() + ), + body: body(), + ); + } } } \ No newline at end of file diff --git a/lib/screens/settings/access_settings/add_client_modal.dart b/lib/screens/settings/access_settings/add_client_modal.dart index 385409b..2fbdd17 100644 --- a/lib/screens/settings/access_settings/add_client_modal.dart +++ b/lib/screens/settings/access_settings/add_client_modal.dart @@ -6,11 +6,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class AddClientModal extends StatefulWidget { final String type; final void Function(String, String) onConfirm; + final bool dialog; const AddClientModal({ Key? key, required this.type, - required this.onConfirm + required this.onConfirm, + required this.dialog, }) : super(key: key); @override @@ -65,32 +67,26 @@ class _AddClientModalState extends State { } } - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - height: Platform.isIOS ? 321 : 305, + Widget content() { + return Padding( padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ) - ), - child: Column( + child: Wrap( children: [ - Expanded( - child: ListView( - physics: (Platform.isIOS ? 338 : 322) < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + icon(), + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - icon(), - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(height: 16), Text( title(), textAlign: TextAlign.center, @@ -99,27 +95,26 @@ class _AddClientModalState extends State { color: Theme.of(context).colorScheme.onSurface ), ), - const SizedBox(height: 16), - TextFormField( - controller: fieldController, - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - helperText: widget.type == 'allowed' || widget.type == 'disallowed' - ? AppLocalizations.of(context)!.addClientFieldDescription : null, - labelText: widget.type == 'allowed' || widget.type == 'disallowed' - ? AppLocalizations.of(context)!.clientIdentifier - : AppLocalizations.of(context)!.domain, - ), - ), ], ), ), + TextFormField( + controller: fieldController, + onChanged: (_) => checkValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + helperText: widget.type == 'allowed' || widget.type == 'disallowed' + ? AppLocalizations.of(context)!.addClientFieldDescription : null, + labelText: widget.type == 'allowed' || widget.type == 'disallowed' + ? AppLocalizations.of(context)!.clientIdentifier + : AppLocalizations.of(context)!.domain, + ), + ), Padding( padding: const EdgeInsets.only(top: 24), child: Row( @@ -129,7 +124,7 @@ class _AddClientModalState extends State { onPressed: () => Navigator.pop(context), child: Text(AppLocalizations.of(context)!.cancel) ), - const SizedBox(width: 20), + const SizedBox(width: 16), TextButton( onPressed: validData == true ? () { @@ -152,7 +147,36 @@ class _AddClientModalState extends State { if (Platform.isIOS) const SizedBox(height: 16) ], ), - ), - ); + ); + } + + if (widget.dialog == true) { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: content() + ), + ), + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).dialogBackgroundColor, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ) + ), + child: content() + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 6e561db..d66e193 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; @@ -68,6 +70,8 @@ class _ClientsListState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void confirmRemoveItem(String client, String type) async { Map> body = { "allowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.allowedClients ?? [], @@ -209,6 +213,7 @@ class _ClientsListState extends State { } return CustomTabContentList( + noSliver: !(Platform.isAndroid || Platform.isIOS) ? true : false, loadingGenerator: () => SizedBox( width: double.maxFinite, height: MediaQuery.of(context).size.height-171, @@ -362,15 +367,28 @@ class _ClientsListState extends State { refreshIndicatorOffset: 0, fab: FloatingActionButton( onPressed: () { - showModalBottomSheet( - context: context, - builder: (context) => AddClientModal( - type: widget.type, - onConfirm: confirmAddItem - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ); + if (width > 900) { + showDialog( + context: context, + builder: (context) => AddClientModal( + type: widget.type, + onConfirm: confirmAddItem, + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => AddClientModal( + type: widget.type, + onConfirm: confirmAddItem, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ); + } }, child: const Icon(Icons.add), ), diff --git a/lib/widgets/tab_content_list.dart b/lib/widgets/tab_content_list.dart index 5171081..9603c95 100644 --- a/lib/widgets/tab_content_list.dart +++ b/lib/widgets/tab_content_list.dart @@ -15,6 +15,7 @@ class CustomTabContentList extends StatelessWidget { final double? refreshIndicatorOffset; final Widget? fab; final bool? fabVisible; + final bool? noSliver; const CustomTabContentList({ Key? key, @@ -27,7 +28,8 @@ class CustomTabContentList extends StatelessWidget { required this.onRefresh, this.refreshIndicatorOffset, this.fab, - this.fabVisible + this.fabVisible, + this.noSliver }) : super(key: key); @override @@ -36,95 +38,156 @@ class CustomTabContentList extends StatelessWidget { switch (loadStatus) { case LoadStatus.loading: - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (BuildContext context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverFillRemaining( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: loadingGenerator() + if (noSliver == true) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: loadingGenerator() + ); + } + else { + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (BuildContext context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), - ) - ], - ), - ) - ); + SliverFillRemaining( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: loadingGenerator() + ), + ) + ], + ), + ) + ); + } case LoadStatus.loaded: - return Stack( - children: [ - SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (BuildContext context) { - return RefreshIndicator( - onRefresh: onRefresh, - edgeOffset: refreshIndicatorOffset ?? 95, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (itemsCount > 0) SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) => contentWidget(index), - childCount: itemsCount + if (noSliver == true) { + if (itemsCount > 0) { + return Stack( + children: [ + ListView.builder( + itemCount: itemsCount, + itemBuilder: (context, index) => contentWidget(index), + ), + if (fab != null) AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: fabVisible != null && fabVisible == true ? + appConfigProvider.showingSnackbar + ? 70 : 20 + : -70, + right: 20, + child: fab! + ), + ], + ); + } + else { + return Stack( + children: [ + noData, + if (fab != null) AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: fabVisible != null && fabVisible == true ? + appConfigProvider.showingSnackbar + ? 70 : 20 + : -70, + right: 20, + child: fab! + ), + ], + ); + } + } + else { + return Stack( + children: [ + SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (BuildContext context) { + return RefreshIndicator( + onRefresh: onRefresh, + edgeOffset: refreshIndicatorOffset ?? 95, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), - ), - if (itemsCount == 0) SliverFillRemaining( - child: noData, - ) - ], - ), - ); - }, + if (itemsCount > 0) SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) => contentWidget(index), + childCount: itemsCount + ), + ), + if (itemsCount == 0) SliverFillRemaining( + child: noData, + ) + ], + ), + ); + }, + ), ), - ), - if (fab != null) AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: fabVisible != null && fabVisible == true ? - appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, - right: 20, - child: fab! - ), - ], - ); + if (fab != null) AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: fabVisible != null && fabVisible == true ? + appConfigProvider.showingSnackbar + ? 70 : 20 + : -70, + right: 20, + child: fab! + ), + ], + ); + } case LoadStatus.error: - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (BuildContext context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverFillRemaining( - child: Padding( - padding: const EdgeInsets.only( - top: 95, - left: 16, - right: 16 - ), - child: errorGenerator() - ), - ) - ], + if (noSliver == true) { + return Padding( + padding: const EdgeInsets.only( + top: 95, + left: 16, + right: 16 ), - ) - ); + child: errorGenerator() + ); + } + else { + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (BuildContext context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverFillRemaining( + child: Padding( + padding: const EdgeInsets.only( + top: 95, + left: 16, + right: 16 + ), + child: errorGenerator() + ), + ) + ], + ), + ) + ); + } default: return const SizedBox(); From 4c86727b5d404c385dadec96869c52001ce7d5a8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 30 Apr 2023 23:39:56 +0200 Subject: [PATCH 049/676] Improvements settings screen --- .../access_settings/clients_list.dart | 2 +- lib/screens/settings/settings.dart | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index d66e193..5b495a1 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -367,7 +367,7 @@ class _ClientsListState extends State { refreshIndicatorOffset: 0, fab: FloatingActionButton( onPressed: () { - if (width > 900) { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { showDialog( context: context, builder: (context) => AddClientModal( diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 472a154..eef0b7f 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -32,10 +34,15 @@ class Settings extends StatelessWidget { @override Widget build(BuildContext context) { - return const SplitView.material( - breakpoint: 900, - child: SettingsWidget(), - ); + if (!(Platform.isAndroid || Platform.isIOS)) { + return const SplitView.material( + breakpoint: 900, + child: SettingsWidget(), + ); + } + else { + return const SettingsWidget(); + } } } class SettingsWidget extends StatelessWidget { @@ -78,7 +85,9 @@ class SettingsWidget extends StatelessWidget { trailing: trailing, onTap: () { appConfigProvider.setSelectedSettingsScreen(thisItem); - SplitView.of(context).setSecondary(screenToNavigate); + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => screenToNavigate) + ); }, ); } From 5d23f3c3e7a45e377f3a330d0377fdf09fd5337b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 02:50:42 +0200 Subject: [PATCH 050/676] Dhcp and dns settings optimizations --- .../settings/dhcp/add_static_lease_modal.dart | 280 ++++--- lib/screens/settings/dhcp/dhcp.dart | 730 ++++++++++-------- lib/screens/settings/dhcp/dhcp_leases.dart | 32 +- .../settings/dhcp/select_interface_modal.dart | 89 ++- lib/screens/settings/dns/bootstrap_dns.dart | 4 +- .../settings/dns/private_reverse_servers.dart | 4 +- lib/screens/settings/dns/upstream_dns.dart | 10 +- lib/widgets/custom_radio_list_tile.dart | 42 +- 8 files changed, 676 insertions(+), 515 deletions(-) diff --git a/lib/screens/settings/dhcp/add_static_lease_modal.dart b/lib/screens/settings/dhcp/add_static_lease_modal.dart index 2c8e316..87dd861 100644 --- a/lib/screens/settings/dhcp/add_static_lease_modal.dart +++ b/lib/screens/settings/dhcp/add_static_lease_modal.dart @@ -5,10 +5,12 @@ import 'package:adguard_home_manager/models/dhcp.dart'; class AddStaticLeaseModal extends StatefulWidget { final void Function(Lease) onConfirm; + final bool dialog; const AddStaticLeaseModal({ Key? key, required this.onConfirm, + required this.dialog }) : super(key: key); @override @@ -65,145 +67,171 @@ class _AddStaticLeaseModalState extends State { @override Widget build(BuildContext context) { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - height: 510, - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ) - ), - child: Column( - children: [ - Expanded( - child: ListView( - physics: 550 < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.add, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.addStaticLease, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 28), - child: TextFormField( - controller: macController, - onChanged: validateMac, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.smartphone_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: macError, - labelText: AppLocalizations.of(context)!.macAddress, + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SingleChildScrollView( + child: Wrap( + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.add, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.addStaticLease, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], ), - ), + ], ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 28), - child: TextFormField( - controller: ipController, - onChanged: validateIp, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipError, - labelText: AppLocalizations.of(context)!.ipAddress, + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, bottom: 12 + ), + child: TextFormField( + controller: macController, + onChanged: validateMac, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.smartphone_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) ), + errorText: macError, + labelText: AppLocalizations.of(context)!.macAddress, ), ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 28), - child: TextFormField( - controller: hostNameController, - onChanged: (value) { - if (value != '') { - setState(() => hostNameError = null); - } - else { - setState(() => hostNameError = AppLocalizations.of(context)!.hostNameError); - } - validateData(); - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.badge_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: hostNameError, - labelText: AppLocalizations.of(context)!.hostName, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + child: TextFormField( + controller: ipController, + onChanged: validateIp, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) ), + errorText: ipError, + labelText: AppLocalizations.of(context)!.ipAddress, ), ), - ], - ), - ), - Padding( - padding: const EdgeInsets.all(20), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel), + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, top: 12 ), - const SizedBox(width: 20), - TextButton( - onPressed: validData == true - ? () { - Navigator.pop(context); - widget.onConfirm( - Lease( - mac: macController.text, - hostname: hostNameController.text, - ip: ipController.text - ) - ); + child: TextFormField( + controller: hostNameController, + onChanged: (value) { + if (value != '') { + setState(() => hostNameError = null); } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: validData == true - ? Theme.of(context).colorScheme.primary - : Colors.grey + else { + setState(() => hostNameError = AppLocalizations.of(context)!.hostNameError); + } + validateData(); + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.badge_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) ), + errorText: hostNameError, + labelText: AppLocalizations.of(context)!.hostName, ), ), - ], - ), - ) - ], + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel), + ), + const SizedBox(width: 20), + TextButton( + onPressed: validData == true + ? () { + Navigator.pop(context); + widget.onConfirm( + Lease( + mac: macController.text, + hostname: hostNameController.text, + ip: ipController.text + ) + ); + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, + style: TextStyle( + color: validData == true + ? Theme.of(context).colorScheme.primary + : Colors.grey + ), + ), + ), + ], + ), + ) + ], + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: content(), ), - ), - ); + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).dialogBackgroundColor, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ) + ), + child: content() + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 5546398..b48245f 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:bottom_sheet/bottom_sheet.dart'; @@ -213,6 +215,8 @@ class _DhcpWidgetState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void saveSettings() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingSettings); @@ -354,24 +358,32 @@ class _DhcpWidgetState extends State { void selectInterface() { ScaffoldMessenger.of(context).clearSnackBars(); Future.delayed(const Duration(seconds: 0), () { - showFlexibleBottomSheet( - minHeight: 0.6, - initHeight: 0.6, - maxHeight: 0.95, - isCollapsible: true, - duration: const Duration(milliseconds: 250), - anchors: [0.95], - context: context, - builder: (ctx, controller, offset) => SelectInterfaceModal( - interfaces: serversProvider.dhcp.data!.networkInterfaces, - scrollController: controller, - onSelect: (interface) => setState(() { - clearAll(); - selectedInterface = interface; - }) - ), - bottomSheetColor: Colors.transparent - ); + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => SelectInterfaceModal( + interfaces: serversProvider.dhcp.data!.networkInterfaces, + onSelect: (interface) => setState(() { + clearAll(); + selectedInterface = interface; + }), + dialog: true, + ) + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => SelectInterfaceModal( + interfaces: serversProvider.dhcp.data!.networkInterfaces, + onSelect: (i) => setState(() { + clearAll(); + selectedInterface = i; + }), + dialog: false, + ), + ); + } }); } @@ -399,333 +411,409 @@ class _DhcpWidgetState extends State { case 1: if (selectedInterface != null) { - return ListView( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - left: 16, - right: 16 - ), - child: Material( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: selectedInterface != null - ? () => setState(() => enabled = !enabled) - : null, + return SingleChildScrollView( + child: Wrap( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + left: 16, + right: 16 + ), + child: Material( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12 + child: InkWell( + onTap: selectedInterface != null + ? () => setState(() => enabled = !enabled) + : null, + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.enableDhcpServer, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + if (selectedInterface != null) ...[ + Text( + selectedInterface!.name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).listTileTheme.textColor + ), + ) + ] + ], + ), + Switch( + value: enabled, + onChanged: selectedInterface != null + ? (value) => setState(() => enabled = value) + : null, + ), + ], + ), ), + ), + ), + ), + if (selectedInterface!.ipv4Addresses.isNotEmpty) ...[ + SectionLabel( + label: AppLocalizations.of(context)!.ipv4settings, + padding: const EdgeInsets.only( + top: 24, left: 16, right: 16, bottom: 8 + ) + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4StartRangeController, + onChanged: (value) => validateIpV4(value, 'ipv4StartRangeError', AppLocalizations.of(context)!.ipNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_previous_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4StartRangeError, + labelText: AppLocalizations.of(context)!.startOfRange, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4EndRangeController, + onChanged: (value) => validateIpV4(value, 'ipv4EndRangeError', AppLocalizations.of(context)!.ipNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_next_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4EndRangeError, + labelText: AppLocalizations.of(context)!.endOfRange, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4SubnetMaskController, + onChanged: (value) => validateIpV4(value, 'ipv4SubnetMaskError', AppLocalizations.of(context)!.subnetMaskNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.hub_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4SubnetMaskError, + labelText: AppLocalizations.of(context)!.subnetMask, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4GatewayController, + onChanged: (value) => validateIpV4(value, 'ipv4GatewayError', AppLocalizations.of(context)!.gatewayNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.router_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4GatewayError, + labelText: AppLocalizations.of(context)!.gateway, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: 1, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4LeaseTimeController, + onChanged: (value) { + if (int.tryParse(value).runtimeType == int) { + setState(() => ipv4LeaseTimeError = null); + } + else { + setState(() => ipv4LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); + } + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.timer), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4LeaseTimeError, + labelText: AppLocalizations.of(context)!.leaseTime, + ), + keyboardType: TextInputType.number, + ), + ), + ), + ], + if (selectedInterface!.ipv6Addresses.isNotEmpty) ...[ + SectionLabel( + label: AppLocalizations.of(context)!.ipv6settings, + padding: const EdgeInsets.all(16) + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 8, bottom: 12, left: 16, right: 8) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv6StartRangeController, + onChanged: (value) => validateIpV4(value, 'ipv6StartRangeError', AppLocalizations.of(context)!.ipNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_next_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv6StartRangeError, + labelText: AppLocalizations.of(context)!.startOfRange, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 8, bottom: 12, left: 8, right: 16) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv6EndRangeController, + onChanged: (value) => validateIpV4(value, 'ipv6EndRangeError', AppLocalizations.of(context)!.ipNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_previous_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv6EndRangeError, + labelText: AppLocalizations.of(context)!.endOfRange, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: 1, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv6LeaseTimeController, + onChanged: (value) { + if (int.tryParse(value).runtimeType == int) { + setState(() => ipv6LeaseTimeError = null); + } + else { + setState(() => ipv6LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); + } + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.timer), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv6LeaseTimeError, + labelText: AppLocalizations.of(context)!.leaseTime, + ), + keyboardType: TextInputType.number, + ), + ), + ), + ], + const SizedBox(height: 20), + SectionLabel( + label: AppLocalizations.of(context)!.dhcpLeases, + padding: const EdgeInsets.all(16), + ), + if (width <= 900) Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: serversProvider.dhcp.data!.dhcpStatus.leases, + staticLeases: false, + ) + )); + }, + child: Container( + padding: const EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.enableDhcpServer, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - if (selectedInterface != null) ...[ - Text( - selectedInterface!.name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).listTileTheme.textColor - ), - ) - ] - ], - ), - Switch( - value: enabled, - onChanged: selectedInterface != null - ? (value) => setState(() => enabled = value) - : null, + Text( + AppLocalizations.of(context)!.dhcpLeases, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface, + ), ), + Icon( + Icons.arrow_forward_rounded, + color: Theme.of(context).colorScheme.onSurface, + ) ], ), ), ), ), - ), - if (selectedInterface!.ipv4Addresses.isNotEmpty) ...[ - SectionLabel( - label: AppLocalizations.of(context)!.ipv4settings, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: ipv4StartRangeController, - onChanged: (value) => validateIpV4(value, 'ipv4StartRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_previous_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) + if (width <= 900) Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + staticLeases: true, ) - ), - errorText: ipv4StartRangeError, - labelText: AppLocalizations.of(context)!.startOfRange, - ), - keyboardType: TextInputType.number, - ), - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: ipv4EndRangeController, - onChanged: (value) => validateIpV4(value, 'ipv4EndRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_next_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4EndRangeError, - labelText: AppLocalizations.of(context)!.endOfRange, - ), - keyboardType: TextInputType.number, - ), - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: ipv4SubnetMaskController, - onChanged: (value) => validateIpV4(value, 'ipv4SubnetMaskError', AppLocalizations.of(context)!.subnetMaskNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.hub_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4SubnetMaskError, - labelText: AppLocalizations.of(context)!.subnetMask, - ), - keyboardType: TextInputType.number, - ), - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: ipv4GatewayController, - onChanged: (value) => validateIpV4(value, 'ipv4GatewayError', AppLocalizations.of(context)!.gatewayNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.router_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4GatewayError, - labelText: AppLocalizations.of(context)!.gateway, - ), - keyboardType: TextInputType.number, - ), - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: ipv4LeaseTimeController, - onChanged: (value) { - if (int.tryParse(value).runtimeType == int) { - setState(() => ipv4LeaseTimeError = null); - } - else { - setState(() => ipv4LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); - } + )); }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.timer), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4LeaseTimeError, - labelText: AppLocalizations.of(context)!.leaseTime, - ), - keyboardType: TextInputType.number, - ), - ), - ], - if (selectedInterface!.ipv6Addresses.isNotEmpty) ...[ - SectionLabel( - label: AppLocalizations.of(context)!.ipv6settings, - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: ipv6StartRangeController, - onChanged: (value) => validateIpV4(value, 'ipv6StartRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_next_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv6StartRangeError, - labelText: AppLocalizations.of(context)!.startOfRange, - ), - keyboardType: TextInputType.number, - ), - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: ipv6EndRangeController, - onChanged: (value) => validateIpV4(value, 'ipv6EndRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_previous_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv6EndRangeError, - labelText: AppLocalizations.of(context)!.endOfRange, - ), - keyboardType: TextInputType.number, - ), - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: ipv6LeaseTimeController, - onChanged: (value) { - if (int.tryParse(value).runtimeType == int) { - setState(() => ipv6LeaseTimeError = null); - } - else { - setState(() => ipv6LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); - } - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.timer), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv6LeaseTimeError, - labelText: AppLocalizations.of(context)!.leaseTime, - ), - keyboardType: TextInputType.number, - ), - ), - ], - const SizedBox(height: 20), - SectionLabel( - label: AppLocalizations.of(context)!.dhcpLeases, - ), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.leases, - staticLeases: false, - ) - )); - }, - child: Container( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.dhcpLeases, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface, + child: Container( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.dhcpStatic, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface, + ), ), - ), - Icon( - Icons.arrow_forward_rounded, - color: Theme.of(context).colorScheme.onSurface, - ) - ], - ), - ), - ), - ), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, - staticLeases: true, - ) - )); - }, - child: Container( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.dhcpStatic, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, + Icon( + Icons.arrow_forward_rounded, color: Theme.of(context).colorScheme.onSurface, - ), - ), - Icon( - Icons.arrow_forward_rounded, - color: Theme.of(context).colorScheme.onSurface, - ) - ], + ) + ], + ), ), ), ), - ), - const SizedBox(height: 10) - ], + if (width > 900) Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () => Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: serversProvider.dhcp.data!.dhcpStatus.leases, + staticLeases: false, + ) + )), + child: Row( + children: [ + Text(AppLocalizations.of(context)!.dhcpLeases), + const SizedBox(width: 8), + const Icon(Icons.arrow_forward_rounded) + ], + ) + ), + ElevatedButton( + onPressed: () => Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + staticLeases: true, + ) + )), + child: Row( + children: [ + Text(AppLocalizations.of(context)!.dhcpStatic), + const SizedBox(width: 8), + const Icon(Icons.arrow_forward_rounded) + ], + ) + ), + ], + ), + const SizedBox(height: 10) + ], + ), ); } else { - return Column( - mainAxisSize: MainAxisSize.max, + return Row( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.neededSelectInterface, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5) + Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.neededSelectInterface, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5) + ), + ), ), - ), - ), - const SizedBox(height: 30), - ElevatedButton( - onPressed: selectInterface, - child: Text(AppLocalizations.of(context)!.selectInterface) + const SizedBox(height: 30), + ElevatedButton( + onPressed: selectInterface, + child: Text(AppLocalizations.of(context)!.selectInterface) + ), + ], ), ], ); diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index aed4f47..79f478a 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:animations/animations.dart'; @@ -30,6 +32,8 @@ class DhcpLeases extends StatelessWidget { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void deleteLease(Lease lease) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deleting); @@ -119,14 +123,26 @@ class DhcpLeases extends StatelessWidget { } void openAddStaticLease() { - showModalBottomSheet( - context: context, - builder: (context) => AddStaticLeaseModal( - onConfirm: createLease - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ); + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => AddStaticLeaseModal( + onConfirm: createLease, + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => AddStaticLeaseModal( + onConfirm: createLease, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ); + } } return Scaffold( diff --git a/lib/screens/settings/dhcp/select_interface_modal.dart b/lib/screens/settings/dhcp/select_interface_modal.dart index 202281c..b89f379 100644 --- a/lib/screens/settings/dhcp/select_interface_modal.dart +++ b/lib/screens/settings/dhcp/select_interface_modal.dart @@ -7,48 +7,50 @@ import 'package:adguard_home_manager/models/dhcp.dart'; class SelectInterfaceModal extends StatelessWidget { final List interfaces; - final ScrollController scrollController; final void Function(NetworkInterface) onSelect; + final bool dialog; const SelectInterfaceModal({ Key? key, required this.interfaces, - required this.scrollController, required this.onSelect, + required this.dialog }) : super(key: key); @override Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ) - ), - child: Column( + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, children: [ - Expanded( - child: ListView( - controller: scrollController, + SingleChildScrollView( + child: Wrap( children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.settings_ethernet_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.selectInterface, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.settings_ethernet_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.selectInterface, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ], ), const SizedBox(height: 16), ListView.builder( @@ -190,7 +192,30 @@ class SelectInterfaceModal extends StatelessWidget { ), if (Platform.isIOS) const SizedBox(height: 16) ], - ), - ); + ); + } + + if (dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: content() + ), + ); + } + else { + return Container( + decoration: BoxDecoration( + color: Theme.of(context).dialogBackgroundColor, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ) + ), + child: content() + ); + } } } \ No newline at end of file diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index 32f02ed..7658c4d 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -182,8 +182,7 @@ class _BootstrapDnsScreenState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - SizedBox( - width: MediaQuery.of(context).size.width-74, + Expanded( child: TextFormField( controller: c['controller'], onChanged: (value) => validateIp(c, value), @@ -199,6 +198,7 @@ class _BootstrapDnsScreenState extends State { ) ), ), + const SizedBox(width: 8), IconButton( onPressed: () { setState(() => bootstrapControllers = bootstrapControllers.where((con) => con != c).toList()); diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index a6c29bf..a4f8131 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -229,8 +229,7 @@ class _PrivateReverseDnsServersScreenState extends State validateAddress(c, value), @@ -246,6 +245,7 @@ class _PrivateReverseDnsServersScreenState extends State reverseResolversControllers = reverseResolversControllers.where((con) => con != c).toList()); diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 0005252..f32983f 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -185,13 +185,12 @@ class _UpstreamDnsScreenState extends State { ), ...dnsServers.map((item) => Padding( padding: const EdgeInsets.only( - left: 16, right: 6, bottom: 20 + left: 16, right: 6, bottom: 24 ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if (item['controller'] != null) SizedBox( - width: MediaQuery.of(context).size.width-74, + if (item['controller'] != null) Expanded( child: TextFormField( controller: item['controller'], onChanged: (_) => checkValidValues(), @@ -206,6 +205,7 @@ class _UpstreamDnsScreenState extends State { ) ), ), + const SizedBox(width: 8), if (item['comment'] != null) Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -232,10 +232,12 @@ class _UpstreamDnsScreenState extends State { }, icon: const Icon(Icons.remove_circle_outline), tooltip: AppLocalizations.of(context)!.remove, - ) + ), + const SizedBox(width: 4), ], ), )).toList(), + const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.min, diff --git a/lib/widgets/custom_radio_list_tile.dart b/lib/widgets/custom_radio_list_tile.dart index b800aa3..4d59b3c 100644 --- a/lib/widgets/custom_radio_list_tile.dart +++ b/lib/widgets/custom_radio_list_tile.dart @@ -41,33 +41,35 @@ class CustomRadioListTile extends StatelessWidget { backgroundColor: radioBackgroundColor, ), const SizedBox(width: 24), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: MediaQuery.of(context).size.width-110, - child: Text( - title, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - if (subtitle != null) ...[ - const SizedBox(height: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ SizedBox( width: MediaQuery.of(context).size.width-110, child: Text( - subtitle!, + title, style: TextStyle( - color: Theme.of(context).listTileTheme.textColor, - fontSize: 14 + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface ), ), ), - ] - ], + if (subtitle != null) ...[ + const SizedBox(height: 5), + SizedBox( + width: MediaQuery.of(context).size.width-110, + child: Text( + subtitle!, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 14 + ), + ), + ), + ] + ], + ), ), ], ), From 129a77d979cbe6e782d3a3f2e42a2080cb89bb4d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 03:48:23 +0200 Subject: [PATCH 051/676] More improvements --- lib/screens/settings/dhcp/dhcp.dart | 50 +++-- lib/screens/settings/dns/comment_modal.dart | 210 +++++++++++--------- lib/screens/settings/dns/dns.dart | 44 ++-- lib/screens/settings/dns/upstream_dns.dart | 89 ++++++--- 4 files changed, 247 insertions(+), 146 deletions(-) diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index b48245f..461fd73 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -3,8 +3,8 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; -import 'package:bottom_sheet/bottom_sheet.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; @@ -752,12 +752,24 @@ class _DhcpWidgetState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ElevatedButton( - onPressed: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.leases, - staticLeases: false, - ) - )), + onPressed: () { + if (!(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push( + DhcpLeases( + items: serversProvider.dhcp.data!.dhcpStatus.leases, + staticLeases: false, + ) + ); + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: serversProvider.dhcp.data!.dhcpStatus.leases, + staticLeases: false, + ) + )); + } + }, child: Row( children: [ Text(AppLocalizations.of(context)!.dhcpLeases), @@ -767,12 +779,24 @@ class _DhcpWidgetState extends State { ) ), ElevatedButton( - onPressed: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, - staticLeases: true, - ) - )), + onPressed: () { + if (!(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push( + DhcpLeases( + items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + staticLeases: true, + ) + ); + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + staticLeases: true, + ) + )); + } + }, child: Row( children: [ Text(AppLocalizations.of(context)!.dhcpStatic), diff --git a/lib/screens/settings/dns/comment_modal.dart b/lib/screens/settings/dns/comment_modal.dart index 20ad859..51f5395 100644 --- a/lib/screens/settings/dns/comment_modal.dart +++ b/lib/screens/settings/dns/comment_modal.dart @@ -4,11 +4,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class CommentModal extends StatefulWidget { final String? comment; final void Function(String) onConfirm; + final bool dialog; const CommentModal({ Key? key, this.comment, - required this.onConfirm + required this.onConfirm, + required this.dialog }) : super(key: key); @override @@ -30,103 +32,125 @@ class _CommentModalState extends State { @override Widget build(BuildContext context) { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - height: 310, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor - ), - child: Column( - children: [ - Expanded( - child: ListView( - physics: MediaQuery.of(context).size.height >= 330 == true - ? const NeverScrollableScrollPhysics() - : null, - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.comment_rounded, - size: 24, - color: Theme.of(context).colorScheme.secondary, - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.comment, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: commentController, - onChanged: (value) { - if (value != '') { - setState(() => validData = true); - } - else { - setState(() => validData = false); - } - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.comment_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.comment_rounded, + size: 24, + color: Theme.of(context).colorScheme.secondary, + ), ), - labelText: AppLocalizations.of(context)!.comment, - helperText: AppLocalizations.of(context)!.commentsDescription, - helperMaxLines: 3 - ) + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.comment, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ), - const SizedBox(width: 20), - TextButton( - onPressed: validData == true - ? () { - Navigator.pop(context); - widget.onConfirm("# ${commentController.text}"); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: validData == true - ? Theme.of(context).colorScheme.primary - : Colors.grey + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: commentController, + onChanged: (value) { + if (value != '') { + setState(() => validData = true); + } + else { + setState(() => validData = false); + } + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.comment_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) ), + labelText: AppLocalizations.of(context)!.comment, + helperText: AppLocalizations.of(context)!.commentsDescription, + helperMaxLines: 3 ) ), - ], - ), - ) - ], + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + const SizedBox(width: 20), + TextButton( + onPressed: validData == true + ? () { + Navigator.pop(context); + widget.onConfirm("# ${commentController.text}"); + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, + style: TextStyle( + color: validData == true + ? Theme.of(context).colorScheme.primary + : Colors.grey + ), + ) + ), + ], + ), + ) + ], + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: content() ), - ), - ); + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: content() + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 229c167..63982b1 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -1,6 +1,9 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -76,6 +79,17 @@ class _DnsSettingsWidgetState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + void navigate(Widget widget) { + if (!(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push(widget); + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => widget + )); + } + } + Widget generateBody() { switch (widget.serversProvider.dnsInfo.loadStatus) { case 0: @@ -105,51 +119,51 @@ class _DnsSettingsWidgetState extends State { CustomListTile( title: AppLocalizations.of(context)!.upstreamDns, subtitle: AppLocalizations.of(context)!.upstreamDnsDescription, - onTap: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => UpstreamDnsScreen( + onTap: () => navigate( + UpstreamDnsScreen( serversProvider: serversProvider ) - )), + ), icon: Icons.upload_rounded, ), CustomListTile( title: AppLocalizations.of(context)!.bootstrapDns, subtitle: AppLocalizations.of(context)!.bootstrapDnsDescription, - onTap: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => BootstrapDnsScreen( + onTap: () => navigate( + BootstrapDnsScreen( serversProvider: serversProvider ) - )), + ), icon: Icons.dns_rounded, ), CustomListTile( title: AppLocalizations.of(context)!.privateReverseDnsServers, subtitle: AppLocalizations.of(context)!.privateReverseDnsDescription, - onTap: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => PrivateReverseDnsServersScreen( + onTap: () => navigate( + PrivateReverseDnsServersScreen( serversProvider: serversProvider ) - )), + ), icon: Icons.person_rounded, ), CustomListTile( title: AppLocalizations.of(context)!.dnsServerSettings, subtitle: AppLocalizations.of(context)!.dnsServerSettingsDescription, - onTap: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => DnsServerSettingsScreen( + onTap: () => navigate( + DnsServerSettingsScreen( serversProvider: serversProvider ) - )), + ), icon: Icons.settings, ), CustomListTile( title: AppLocalizations.of(context)!.dnsCacheConfig, subtitle: AppLocalizations.of(context)!.dnsCacheConfigDescription, - onTap: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => CacheConfigDnsScreen( + onTap: () => navigate( + CacheConfigDnsScreen( serversProvider: serversProvider ) - )), + ), icon: Icons.storage_rounded, ), ], diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index f32983f..66d8b8c 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -71,36 +73,73 @@ class _UpstreamDnsScreenState extends State { Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; void openAddCommentModal() { - showModalBottomSheet( - context: context, - builder: (context) => CommentModal( - onConfirm: (value) { - dnsServers.add({ - 'comment': value - }); - }, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true, - isDismissible: true - ); + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => CommentModal( + onConfirm: (value) { + setState(() { + dnsServers.add({ + 'comment': value + }); + }); + }, + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => CommentModal( + onConfirm: (value) { + setState(() { + dnsServers.add({ + 'comment': value + }); + }); + }, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + isDismissible: true + ); + } } void openEditCommentModal(Map item, int position) { - showModalBottomSheet( - context: context, - builder: (context) => CommentModal( - comment: item['comment'], - onConfirm: (value) { - setState(() => dnsServers[position] = { 'comment': value }); - }, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true, - isDismissible: true - ); + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => CommentModal( + comment: item['comment'], + onConfirm: (value) { + setState(() => dnsServers[position] = { 'comment': value }); + }, + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => CommentModal( + comment: item['comment'], + onConfirm: (value) { + setState(() => dnsServers[position] = { 'comment': value }); + }, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + isDismissible: true + ); + } } void saveData() async { From fb9fbbd35e35c01545c7868187e65d7be2684fda Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 04:23:55 +0200 Subject: [PATCH 052/676] Optimizations dns rewrites, encryption and updater --- lib/screens/settings/advanced_setings.dart | 18 +- .../dns_rewrites/add_dns_rewrite_modal.dart | 243 ++++++++++-------- .../settings/dns_rewrites/dns_rewrites.dart | 32 ++- .../encryption/custom_text_field.dart | 6 +- .../settings/encryption/encryption.dart | 92 ++++--- lib/screens/settings/settings.dart | 4 +- .../settings/update_server/update.dart | 177 ++----------- 7 files changed, 253 insertions(+), 319 deletions(-) diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 987d406..0012259 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -1,6 +1,9 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -15,6 +18,8 @@ class AdvancedSettings extends StatelessWidget { @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; Future updateSslCheck(bool newStatus) async { final result = await appConfigProvider.setOverrideSslCheck(newStatus); @@ -64,11 +69,16 @@ class AdvancedSettings extends StatelessWidget { title: AppLocalizations.of(context)!.logs, subtitle: AppLocalizations.of(context)!.checkAppLogs, onTap: () => { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const AppLogs() + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push(const AppLogs()) + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const AppLogs() + ) ) - ) + } }, padding: const EdgeInsets.only( top: 10, diff --git a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart index 53bc3b2..6ac5ee6 100644 --- a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart @@ -7,10 +7,12 @@ import 'package:adguard_home_manager/models/rewrite_rules.dart'; class AddDnsRewriteModal extends StatefulWidget { final void Function(RewriteRulesData) onConfirm; + final bool dialog; const AddDnsRewriteModal({ Key? key, - required this.onConfirm + required this.onConfirm, + required this.dialog }) : super(key: key); @override @@ -50,118 +52,143 @@ class _AddDnsRewriteModalState extends State { @override Widget build(BuildContext context) { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - height: Platform.isIOS ? 416 : 400, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.add, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.addDnsRewrite, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, bottom: 12 + ), + child: TextFormField( + controller: domainController, + onChanged: validateDomain, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: domainError, + labelText: AppLocalizations.of(context)!.domain, + ), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, top: 12 + ), + child: TextFormField( + controller: answerController, + onChanged: (_) => checkValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.system_update_alt_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.answer, + ), + ), + ), + ], + ), ), - color: Theme.of(context).dialogBackgroundColor, - ), - child: Column( - children: [ - Expanded( - child: ListView( - physics: (Platform.isIOS ? 426 : 410) < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.add, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.addDnsRewrite, - textAlign: TextAlign.center, + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel), + ), + const SizedBox(width: 20), + TextButton( + onPressed: validData == true + ? () { + Navigator.pop(context); + widget.onConfirm( + RewriteRulesData( + domain: domainController.text, + answer: answerController.text + ) + ); + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface + color: validData == true + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) ), ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: domainController, - onChanged: validateDomain, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: domainError, - labelText: AppLocalizations.of(context)!.domain, - ), - ), - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: answerController, - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.system_update_alt_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.answer, - ), - ), - ), - ], - ), + ), + ], ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel), - ), - const SizedBox(width: 20), - TextButton( - onPressed: validData == true - ? () { - Navigator.pop(context); - widget.onConfirm( - RewriteRulesData( - domain: domainController.text, - answer: answerController.text - ) - ); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: validData == true - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - ), - ), - ), - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: content() ), - ), - ); + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor, + ), + child: content() + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 119da4c..d9fe68f 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -70,6 +72,8 @@ class _DnsRewritesWidgetState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void deleteDnsRewrite(RewriteRulesData rule) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deleting); @@ -288,14 +292,26 @@ class _DnsRewritesWidgetState extends State { body: generateBody(), floatingActionButton: FloatingActionButton( onPressed: () => { - showModalBottomSheet( - context: context, - builder: (context) => AddDnsRewriteModal( - onConfirm: addDnsRewrite, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ) + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => AddDnsRewriteModal( + onConfirm: addDnsRewrite, + dialog: true, + ), + ) + } + else { + showModalBottomSheet( + context: context, + builder: (context) => AddDnsRewriteModal( + onConfirm: addDnsRewrite, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ) + } }, child: const Icon(Icons.add), ), diff --git a/lib/screens/settings/encryption/custom_text_field.dart b/lib/screens/settings/encryption/custom_text_field.dart index c149873..6a1cac8 100644 --- a/lib/screens/settings/encryption/custom_text_field.dart +++ b/lib/screens/settings/encryption/custom_text_field.dart @@ -26,8 +26,12 @@ class EncryptionTextField extends StatelessWidget { @override Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: width > 900 + ? const EdgeInsets.symmetric(horizontal: 8) + : const EdgeInsets.symmetric(horizontal: 16), child: ConstrainedBox( constraints: const BoxConstraints( maxHeight: 200 diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index e1f3686..2392287 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -234,6 +234,8 @@ class _EncryptionSettingsWidgetState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void saveData() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); @@ -343,43 +345,59 @@ class _EncryptionSettingsWidgetState extends State { disabled: !enabled, ), const SizedBox(height: 10), - EncryptionTextField( - enabled: enabled, - controller: httpsPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => httpsPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: httpsPortError, - label: AppLocalizations.of(context)!.httpsPort, - keyboardType: TextInputType.number, - ), - const SizedBox(height: 30), - EncryptionTextField( - enabled: enabled, - controller: tlsPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => tlsPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: tlsPortError, - label: AppLocalizations.of(context)!.tlsPort, - keyboardType: TextInputType.number, - ), - const SizedBox(height: 30), - EncryptionTextField( - enabled: enabled, - controller: dnsOverQuicPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => dnsOverQuicPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: dnsOverQuicPortError, - label: AppLocalizations.of(context)!.dnsOverQuicPort, - keyboardType: TextInputType.number, + Wrap( + children: [ + FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: httpsPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => httpsPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: httpsPortError, + label: AppLocalizations.of(context)!.httpsPort, + keyboardType: TextInputType.number, + ), + ), + Padding( + padding: width <= 900 + ? const EdgeInsets.symmetric(vertical: 24) + : const EdgeInsets.all(0), + child: FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: tlsPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => tlsPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: tlsPortError, + label: AppLocalizations.of(context)!.tlsPort, + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: dnsOverQuicPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => dnsOverQuicPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: dnsOverQuicPortError, + label: AppLocalizations.of(context)!.dnsOverQuicPort, + keyboardType: TextInputType.number, + ), + ), + ], ), SectionLabel( label: AppLocalizations.of(context)!.certificates, diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index eef0b7f..8981f86 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -34,7 +34,9 @@ class Settings extends StatelessWidget { @override Widget build(BuildContext context) { - if (!(Platform.isAndroid || Platform.isIOS)) { + final width = MediaQuery.of(context).size.width; + + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { return const SplitView.material( breakpoint: 900, child: SettingsWidget(), diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index 5fa898e..f92292a 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -65,16 +65,18 @@ class UpdateScreen extends StatelessWidget { Widget headerPortrait() { return Column( children: [ + const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - IconButton( + if (Navigator.canPop(context)) IconButton( icon: Icon( Icons.arrow_back, color: Theme.of(context).colorScheme.onSurfaceVariant, ), onPressed: () => Navigator.pop(context), ), + if (!Navigator.canPop(context)) const SizedBox(), IconButton( icon: Icon( Icons.refresh_rounded, @@ -170,120 +172,6 @@ class UpdateScreen extends StatelessWidget { ); } - Widget headerLandscape() { - return Column( - mainAxisSize: MainAxisSize.max, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - IconButton( - icon: Icon( - Icons.arrow_back, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - onPressed: () => Navigator.pop(context), - ), - IconButton( - icon: Icon( - Icons.refresh_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - tooltip: AppLocalizations.of(context)!.checkUpdates, - onPressed: () => serversProvider.checkServerUpdatesAvailable(serversProvider.selectedServer!) - ), - ], - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only( - top: 8, bottom: 16, left: 16, right: 16 - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? Column( - children: const [ - CircularProgressIndicator(), - SizedBox(height: 4) - ], - ) - : Icon( - serversProvider.updateAvailable.data!.updateAvailable != null - ? serversProvider.updateAvailable.data!.updateAvailable == true - ? Icons.system_update_rounded - : Icons.system_security_update_good_rounded - : Icons.system_security_update_warning_rounded, - size: 40, - color: Theme.of(context).colorScheme.primary, - ), - const SizedBox(height: 16), - Text( - serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? AppLocalizations.of(context)!.checkingUpdates - : serversProvider.updateAvailable.data!.updateAvailable != null - ? serversProvider.updateAvailable.data!.updateAvailable == true - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.serverUpdated - : AppLocalizations.of(context)!.unknownStatus, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400 - ), - ), - const SizedBox(height: 40), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (serversProvider.updateAvailable.loadStatus == LoadStatus.loaded) Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true - ? AppLocalizations.of(context)!.newVersion - : AppLocalizations.of(context)!.currentVersion, - style: const TextStyle( - fontSize: 16, - ), - ), - const SizedBox(height: 4), - Text( - serversProvider.updateAvailable.data!.updateAvailable != null - ? serversProvider.updateAvailable.data!.updateAvailable == true - ? serversProvider.updateAvailable.data!.newVersion ?? 'N/A' - : serversProvider.updateAvailable.data!.currentVersion - : "N/A", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w700, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ) - ], - ), - if (serversProvider.updateAvailable.loadStatus != LoadStatus.loaded) const SizedBox(), - FilledButton.icon( - icon: const Icon(Icons.download_rounded), - label: Text(AppLocalizations.of(context)!.updateNow), - onPressed: serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true - ? serversProvider.updateAvailable.data!.canAutoupdate == true - ? () => update() - : () => showAutoUpdateUnavailableModal() - : null - ) - ], - ), - ), - ], - ), - ), - ), - ], - ); - } - final changelog = serversProvider.updateAvailable.loadStatus == LoadStatus.loaded && serversProvider.updateAvailable.data!.changelog != null ? ListView( children: [ @@ -313,51 +201,20 @@ class UpdateScreen extends StatelessWidget { : null; return Scaffold( - body: MediaQuery.of(context).size.width > 700 - ? Row( - children: [ - Expanded( - flex: 2, - child: Container( - color: Theme.of(context).colorScheme.surfaceVariant, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Container( - height: MediaQuery.of(context).size.height, - padding: EdgeInsets.only( - top: MediaQuery.of(context).viewPadding.top - ), - child: headerLandscape(), - ) - ], - ), - ), - ), - Expanded( - flex: 3, - child: SafeArea( - child: SizedBox( - width: MediaQuery.of(context).size.width*0.6, - child: changelog ?? const SizedBox(), - ), - ), - ) - ], - ) - : Column( - children: [ - Container( - color: Theme.of(context).colorScheme.surfaceVariant, - child: SafeArea( - child: headerPortrait() - ) - ), - changelog != null - ? Expanded(child: changelog) - : const SizedBox(), - ] - ) + body: Column( + children: [ + Container( + color: Theme.of(context).colorScheme.surfaceVariant, + child: SafeArea( + child: headerPortrait() + ) + ), + const SizedBox(height: 16), + changelog != null + ? Expanded(child: changelog) + : const SizedBox(), + ] + ) ); } } \ No newline at end of file From 42f589793c5c90993b29f10c779d36e6e61cb540 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 04:33:31 +0200 Subject: [PATCH 053/676] Unlocked landscape orientation and small bugs fixed --- lib/main.dart | 3 --- lib/screens/settings/dhcp/dhcp.dart | 42 +++++++++++++++-------------- lib/screens/settings/dns/dns.dart | 4 ++- lib/screens/settings/settings.dart | 11 +++++--- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 94a44e9..6e8f4bf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -25,9 +25,6 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown] - ); if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { setWindowMinSize(const Size(500, 500)); diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 461fd73..e9b35fb 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -816,28 +816,30 @@ class _DhcpWidgetState extends State { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.neededSelectInterface, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5) + Flexible( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.neededSelectInterface, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5) + ), ), ), - ), - const SizedBox(height: 30), - ElevatedButton( - onPressed: selectInterface, - child: Text(AppLocalizations.of(context)!.selectInterface) - ), - ], + const SizedBox(height: 30), + ElevatedButton( + onPressed: selectInterface, + child: Text(AppLocalizations.of(context)!.selectInterface) + ), + ], + ), ), ], ); diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 63982b1..55cfa19 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -79,8 +79,10 @@ class _DnsSettingsWidgetState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void navigate(Widget widget) { - if (!(Platform.isAndroid || Platform.isIOS)) { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { SplitView.of(context).push(widget); } else { diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 8981f86..3875293 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -87,9 +87,14 @@ class SettingsWidget extends StatelessWidget { trailing: trailing, onTap: () { appConfigProvider.setSelectedSettingsScreen(thisItem); - Navigator.of(context).push( - MaterialPageRoute(builder: (context) => screenToNavigate) - ); + if (!(Platform.isIOS || Platform.isAndroid)) { + SplitView.of(context).setSecondary(screenToNavigate); + } + else { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => screenToNavigate) + ); + } }, ); } From 7d5d802aeab0854c71bc9bf509a9a6ab5883a892 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 04:49:40 +0200 Subject: [PATCH 054/676] Fixes --- .../access_settings/add_client_modal.dart | 90 +++--- .../settings/dhcp/add_static_lease_modal.dart | 174 +++++------ lib/screens/settings/dhcp/dhcp.dart | 1 + .../settings/dhcp/select_interface_modal.dart | 274 +++++++++--------- lib/screens/settings/dns/cache_config.dart | 3 +- lib/screens/settings/dns/comment_modal.dart | 106 +++---- .../dns_rewrites/add_dns_rewrite_modal.dart | 122 ++++---- 7 files changed, 394 insertions(+), 376 deletions(-) diff --git a/lib/screens/settings/access_settings/add_client_modal.dart b/lib/screens/settings/access_settings/add_client_modal.dart index 2fbdd17..c7e4012 100644 --- a/lib/screens/settings/access_settings/add_client_modal.dart +++ b/lib/screens/settings/access_settings/add_client_modal.dart @@ -70,49 +70,58 @@ class _AddClientModalState extends State { Widget content() { return Padding( padding: const EdgeInsets.all(24), - child: Wrap( + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - icon(), - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - title(), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + icon(), + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ], ), - ), - ], - ), - ), - TextFormField( - controller: fieldController, - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + title(), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ), + TextFormField( + controller: fieldController, + onChanged: (_) => checkValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + helperText: widget.type == 'allowed' || widget.type == 'disallowed' + ? AppLocalizations.of(context)!.addClientFieldDescription : null, + labelText: widget.type == 'allowed' || widget.type == 'disallowed' + ? AppLocalizations.of(context)!.clientIdentifier + : AppLocalizations.of(context)!.domain, + ), + ), + ], ), - helperText: widget.type == 'allowed' || widget.type == 'disallowed' - ? AppLocalizations.of(context)!.addClientFieldDescription : null, - labelText: widget.type == 'allowed' || widget.type == 'disallowed' - ? AppLocalizations.of(context)!.clientIdentifier - : AppLocalizations.of(context)!.domain, ), ), Padding( @@ -144,7 +153,6 @@ class _AddClientModalState extends State { ], ), ), - if (Platform.isIOS) const SizedBox(height: 16) ], ), ); diff --git a/lib/screens/settings/dhcp/add_static_lease_modal.dart b/lib/screens/settings/dhcp/add_static_lease_modal.dart index 87dd861..a7f2f5f 100644 --- a/lib/screens/settings/dhcp/add_static_lease_modal.dart +++ b/lib/screens/settings/dhcp/add_static_lease_modal.dart @@ -71,102 +71,104 @@ class _AddStaticLeaseModalState extends State { return Column( mainAxisSize: MainAxisSize.min, children: [ - SingleChildScrollView( - child: Wrap( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.add, - size: 24, - color: Theme.of(context).listTileTheme.iconColor + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.add, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.addStaticLease, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.addStaticLease, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - ], - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only( - left: 24, right: 24, bottom: 12 - ), - child: TextFormField( - controller: macController, - onChanged: validateMac, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.smartphone_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: macError, - labelText: AppLocalizations.of(context)!.macAddress, + ], + ), + ], ), ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - child: TextFormField( - controller: ipController, - onChanged: validateIp, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, bottom: 12 + ), + child: TextFormField( + controller: macController, + onChanged: validateMac, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.smartphone_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: macError, + labelText: AppLocalizations.of(context)!.macAddress, ), - errorText: ipError, - labelText: AppLocalizations.of(context)!.ipAddress, ), ), - ), - Padding( - padding: const EdgeInsets.only( - left: 24, right: 24, top: 12 - ), - child: TextFormField( - controller: hostNameController, - onChanged: (value) { - if (value != '') { - setState(() => hostNameError = null); - } - else { - setState(() => hostNameError = AppLocalizations.of(context)!.hostNameError); - } - validateData(); - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.badge_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + child: TextFormField( + controller: ipController, + onChanged: validateIp, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipError, + labelText: AppLocalizations.of(context)!.ipAddress, ), - errorText: hostNameError, - labelText: AppLocalizations.of(context)!.hostName, ), ), - ), - ], + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, top: 12 + ), + child: TextFormField( + controller: hostNameController, + onChanged: (value) { + if (value != '') { + setState(() => hostNameError = null); + } + else { + setState(() => hostNameError = AppLocalizations.of(context)!.hostNameError); + } + validateData(); + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.badge_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: hostNameError, + labelText: AppLocalizations.of(context)!.hostName, + ), + ), + ), + ], + ), ), ), Padding( diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index e9b35fb..a12fe81 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -382,6 +382,7 @@ class _DhcpWidgetState extends State { }), dialog: false, ), + isScrollControlled: true ); } }); diff --git a/lib/screens/settings/dhcp/select_interface_modal.dart b/lib/screens/settings/dhcp/select_interface_modal.dart index b89f379..9827f11 100644 --- a/lib/screens/settings/dhcp/select_interface_modal.dart +++ b/lib/screens/settings/dhcp/select_interface_modal.dart @@ -23,159 +23,161 @@ class SelectInterfaceModal extends StatelessWidget { return Column( mainAxisSize: MainAxisSize.min, children: [ - SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.settings_ethernet_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.selectInterface, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ], - ), - const SizedBox(height: 16), - ListView.builder( - primary: false, - shrinkWrap: true, - itemCount: interfaces.length, - itemBuilder: (context, index) => Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Navigator.pop(context); - onSelect(interfaces[index]); - }, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - interfaces[index].name, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.settings_ethernet_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor ), - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.hardwareAddress}: ", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.selectInterface, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ], + ), + const SizedBox(height: 16), + ListView.builder( + primary: false, + shrinkWrap: true, + itemCount: interfaces.length, + itemBuilder: (context, index) => Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Navigator.pop(context); + onSelect(interfaces[index]); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + interfaces[index].name, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface ), - Text( - interfaces[index].hardwareAddress, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant + ), + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.hardwareAddress}: ", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), ), + Text( + interfaces[index].hardwareAddress, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ], + ), + const SizedBox(height: 5), + if (interfaces[index].flags.isNotEmpty) ...[ + Row( + children: [ + Text( + "Flags: ", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + Text( + interfaces[index].flags.join(', '), + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ], ), + const SizedBox(height: 5), ], - ), - const SizedBox(height: 5), - if (interfaces[index].flags.isNotEmpty) ...[ - Row( - children: [ - Text( - "Flags: ", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - Text( - interfaces[index].flags.join(', '), - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ], - ), - const SizedBox(height: 5), - ], - if (interfaces[index].gatewayIp != '') ...[ - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.gatewayIp}: ", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - Text( - interfaces[index].gatewayIp, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ], - ), - const SizedBox(height: 5), - ], - if (interfaces[index].ipv4Addresses.isNotEmpty) ...[ - Row( - children: [ - Flexible( - child: Text( - "${AppLocalizations.of(context)!.ipv4addresses}: ${interfaces[index].ipv4Addresses.join(', ')}", + if (interfaces[index].gatewayIp != '') ...[ + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.gatewayIp}: ", style: TextStyle( fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant ), ), - ) - ], - ), - const SizedBox(height: 5), - ], - if (interfaces[index].ipv6Addresses.isNotEmpty) ...[ - Row( - children: [ - Flexible( - child: Text( - "${AppLocalizations.of(context)!.ipv6addresses}: ${interfaces[index].ipv6Addresses.join(', ')}", + Text( + interfaces[index].gatewayIp, style: TextStyle( fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant ), ), - ) - ], - ), - ] - ], + ], + ), + const SizedBox(height: 5), + ], + if (interfaces[index].ipv4Addresses.isNotEmpty) ...[ + Row( + children: [ + Flexible( + child: Text( + "${AppLocalizations.of(context)!.ipv4addresses}: ${interfaces[index].ipv4Addresses.join(', ')}", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), + const SizedBox(height: 5), + ], + if (interfaces[index].ipv6Addresses.isNotEmpty) ...[ + Row( + children: [ + Flexible( + child: Text( + "${AppLocalizations.of(context)!.ipv6addresses}: ${interfaces[index].ipv6Addresses.join(', ')}", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), + ] + ], + ), ), ), - ), - ) - ), - ], + ) + ), + ], + ), ), ), Padding( diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index 16090fb..713f837 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -257,7 +257,8 @@ class _CacheConfigDnsScreenState extends State { label: Text(AppLocalizations.of(context)!.clearDnsCache), ), ], - ) + ), + const SizedBox(height: 16) ], ), ); diff --git a/lib/screens/settings/dns/comment_modal.dart b/lib/screens/settings/dns/comment_modal.dart index 51f5395..a9dd60d 100644 --- a/lib/screens/settings/dns/comment_modal.dart +++ b/lib/screens/settings/dns/comment_modal.dart @@ -36,62 +36,64 @@ class _CommentModalState extends State { return Column( mainAxisSize: MainAxisSize.min, children: [ - SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.comment_rounded, - size: 24, - color: Theme.of(context).colorScheme.secondary, + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.comment_rounded, + size: 24, + color: Theme.of(context).colorScheme.secondary, + ), ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.comment, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.comment, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - const SizedBox(height: 16), - ], - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: commentController, - onChanged: (value) { - if (value != '') { - setState(() => validData = true); - } - else { - setState(() => validData = false); - } - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.comment_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + const SizedBox(height: 16), + ], ), - labelText: AppLocalizations.of(context)!.comment, - helperText: AppLocalizations.of(context)!.commentsDescription, - helperMaxLines: 3 - ) + ], ), - ), - ], + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: commentController, + onChanged: (value) { + if (value != '') { + setState(() => validData = true); + } + else { + setState(() => validData = false); + } + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.comment_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.comment, + helperText: AppLocalizations.of(context)!.commentsDescription, + helperMaxLines: 3 + ) + ), + ), + ], + ), ), ), Padding( diff --git a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart index 6ac5ee6..edff851 100644 --- a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart @@ -54,76 +54,78 @@ class _AddDnsRewriteModalState extends State { Widget build(BuildContext context) { Widget content() { return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: MainAxisSize.min, children: [ - SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.add, - size: 24, - color: Theme.of(context).listTileTheme.iconColor + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.add, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.addDnsRewrite, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.addDnsRewrite, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), ), + const SizedBox(height: 16), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, bottom: 12 + ), + child: TextFormField( + controller: domainController, + onChanged: validateDomain, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) ), - const SizedBox(height: 16), - ], - ), - ], - ), - Padding( - padding: const EdgeInsets.only( - left: 24, right: 24, bottom: 12 - ), - child: TextFormField( - controller: domainController, - onChanged: validateDomain, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + errorText: domainError, + labelText: AppLocalizations.of(context)!.domain, ), - errorText: domainError, - labelText: AppLocalizations.of(context)!.domain, ), ), - ), - Padding( - padding: const EdgeInsets.only( - left: 24, right: 24, top: 12 - ), - child: TextFormField( - controller: answerController, - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.system_update_alt_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, top: 12 + ), + child: TextFormField( + controller: answerController, + onChanged: (_) => checkValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.system_update_alt_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.answer, ), - labelText: AppLocalizations.of(context)!.answer, ), ), - ), - ], + ], + ), ), ), Padding( From 4531e15566d56ad5a63582c3aa909998f1653515 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 13:16:31 +0200 Subject: [PATCH 055/676] Changed flutter_split_view package source and hide divider --- lib/screens/settings/settings.dart | 1 + pubspec.lock | 9 +++++---- pubspec.yaml | 5 ++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 3875293..9d983d2 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -39,6 +39,7 @@ class Settings extends StatelessWidget { if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { return const SplitView.material( breakpoint: 900, + hideDivider: true, child: SettingsWidget(), ); } diff --git a/pubspec.lock b/pubspec.lock index 3718b7c..c1e392f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -294,10 +294,11 @@ packages: flutter_split_view: dependency: "direct main" description: - name: flutter_split_view - sha256: "0fb1f3aa6a6f2031d936ae5596fc5178affacdc7d793b27cdbc191a1ae8e56bf" - url: "https://pub.dev" - source: hosted + path: "." + ref: hide-divider + resolved-ref: e22dd0bf64e7d61a64eb99fcd9a4e111e177ccf3 + url: "https://github.com/JGeek00/flutter_split_view" + source: git version: "0.1.2" flutter_svg: dependency: "direct main" diff --git a/pubspec.yaml b/pubspec.yaml index ba3e38e..135c7b6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,7 +60,10 @@ dependencies: git: url: https://github.com/google/flutter-desktop-embedding path: plugins/window_size - flutter_split_view: ^0.1.2 + flutter_split_view: + git: + url: https://github.com/JGeek00/flutter_split_view + ref: hide-divider dev_dependencies: flutter_test: From aacf68569d7e41fdbe3307af006cd23f63bc4882 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 14:38:46 +0200 Subject: [PATCH 056/676] Adapted home screen --- lib/l10n/app_en.arb | 8 +- lib/l10n/app_es.arb | 8 +- lib/screens/home/chart.dart | 15 +- lib/screens/home/fab.dart | 26 +- lib/screens/home/home.dart | 190 +++++++++----- lib/screens/home/management_modal.dart | 183 +++++++++----- lib/screens/home/server_status.dart | 12 +- lib/screens/home/status_box.dart | 16 +- lib/screens/home/top_items.dart | 40 ++- lib/screens/top_items/top_items_modal.dart | 276 +++++++++++++++++++++ 10 files changed, 612 insertions(+), 162 deletions(-) create mode 100644 lib/screens/top_items/top_items_modal.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 2b66b5e..45b4526 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -45,10 +45,10 @@ "save": "Save", "serverStatus": "Server status", "connectionNotUpdated": "Connection not updated", - "ruleFilteringWidget": "Rule\nfiltering", - "safeBrowsingWidget": "Safe\nbrowsing", - "parentalFilteringWidget": "Parental\nfiltering", - "safeSearchWidget": "Safe\nsearch", + "ruleFilteringWidget": "Rule filtering", + "safeBrowsingWidget": "Safe browsing", + "parentalFilteringWidget": "Parental filtering", + "safeSearchWidget": "Safe search", "ruleFiltering": "Rule filtering", "safeBrowsing": "Safe browsing", "parentalFiltering": "Parental filtering", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 76cff1b..97967c8 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -45,10 +45,10 @@ "save": "Guardar", "connectionNotUpdated": "Conexión no actualizada", "serverStatus": "Estado del servidor", - "ruleFilteringWidget": "Bloqueo por\nfiltros", - "safeBrowsingWidget": "Navegación\nsegura", - "parentalFilteringWidget": "Control\nparental", - "safeSearchWidget": "Búsqueda\nsegura", + "ruleFilteringWidget": "Bloqueo por filtros", + "safeBrowsingWidget": "Navegación segura", + "parentalFilteringWidget": "Control parental", + "safeSearchWidget": "Búsqueda segura", "ruleFiltering": "Bloqueo por filtros", "safeBrowsing": "Navegación segura", "parentalFiltering": "Control parental", diff --git a/lib/screens/home/chart.dart b/lib/screens/home/chart.dart index 315d421..2ea4535 100644 --- a/lib/screens/home/chart.dart +++ b/lib/screens/home/chart.dart @@ -48,12 +48,15 @@ class HomeChart extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - label, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface + Flexible( + child: Text( + label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), ), ), !isEmpty diff --git a/lib/screens/home/fab.dart b/lib/screens/home/fab.dart index ce5f8a9..1369535 100644 --- a/lib/screens/home/fab.dart +++ b/lib/screens/home/fab.dart @@ -12,13 +12,27 @@ class HomeFab extends StatelessWidget { Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void openManagementBottomSheet() { - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (context) => const ManagementModal(), - backgroundColor: Colors.transparent, - ); + if (width > 700) { + showDialog( + context: context, + builder: (context) => const ManagementModal( + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => const ManagementModal( + dialog: false, + ), + backgroundColor: Colors.transparent, + ); + } } return serversProvider.serverStatus.loadStatus == 1 diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 932ddfe..541f732 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -55,6 +55,8 @@ class _HomeState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + Widget status() { switch (serversProvider.serverStatus.loadStatus) { case 0: @@ -92,72 +94,138 @@ class _HomeState extends State { ), const SizedBox(height: 20), - HomeChart( - data: serversProvider.serverStatus.data!.stats.dnsQueries, - label: AppLocalizations.of(context)!.dnsQueries, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), - secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", - color: Colors.blue, - ), - - HomeChart( - data: serversProvider.serverStatus.data!.stats.blockedFiltering, - label: AppLocalizations.of(context)!.blockedFilters, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", - color: Colors.red, + Wrap( + children: [ + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: serversProvider.serverStatus.data!.stats.dnsQueries, + label: AppLocalizations.of(context)!.dnsQueries, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + color: Colors.blue, + ), + ), + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: serversProvider.serverStatus.data!.stats.blockedFiltering, + label: AppLocalizations.of(context)!.blockedFilters, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + color: Colors.red, + ), + ), + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing, + label: AppLocalizations.of(context)!.malwarePhisingBlocked, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + color: Colors.green, + ), + ), + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: serversProvider.serverStatus.data!.stats.replacedParental, + label: AppLocalizations.of(context)!.blockedAdultWebsites, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + color: Colors.orange, + ), + ), + + ], ), - HomeChart( - data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing, - label: AppLocalizations.of(context)!.malwarePhisingBlocked, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", - color: Colors.green, - ), - - HomeChart( - data: serversProvider.serverStatus.data!.stats.replacedParental, - label: AppLocalizations.of(context)!.blockedAdultWebsites, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", - color: Colors.orange, - ), - - TopItems( - label: AppLocalizations.of(context)!.topQueriedDomains, - data: serversProvider.serverStatus.data!.stats.topQueriedDomains, - type: 'topQueriedDomains', - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + if (width <= 700) ...[ + TopItems( + label: AppLocalizations.of(context)!.topQueriedDomains, + data: serversProvider.serverStatus.data!.stats.topQueriedDomains, + type: 'topQueriedDomains', ), - ), - const SizedBox(height: 20), - - TopItems( - label: AppLocalizations.of(context)!.topBlockedDomains, - data: serversProvider.serverStatus.data!.stats.topBlockedDomains, - type: 'topBlockedDomains', - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), ), - ), - const SizedBox(height: 20), - TopItems( - label: AppLocalizations.of(context)!.topClients, - data: serversProvider.serverStatus.data!.stats.topClients, - type: 'topClients', - clients: true, - ), + const SizedBox(height: 20), + + TopItems( + label: AppLocalizations.of(context)!.topBlockedDomains, + data: serversProvider.serverStatus.data!.stats.topBlockedDomains, + type: 'topBlockedDomains', + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + ), + const SizedBox(height: 20), + + TopItems( + label: AppLocalizations.of(context)!.topClients, + data: serversProvider.serverStatus.data!.stats.topClients, + type: 'topClients', + clients: true, + ), + ], + if (width > 700) Column( + children: [ + const SizedBox(height: 16), + Wrap( + alignment: WrapAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: TopItems( + label: AppLocalizations.of(context)!.topQueriedDomains, + data: serversProvider.serverStatus.data!.stats.topQueriedDomains, + type: 'topQueriedDomains', + ), + ), + ), + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: TopItems( + label: AppLocalizations.of(context)!.topBlockedDomains, + data: serversProvider.serverStatus.data!.stats.topBlockedDomains, + type: 'topBlockedDomains', + ), + ), + ), + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: TopItems( + label: AppLocalizations.of(context)!.topBlockedDomains, + data: serversProvider.serverStatus.data!.stats.topBlockedDomains, + type: 'topBlockedDomains', + ), + ), + ), + ], + ), + ], + ) ], ); diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index e36fbc7..15eac57 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -15,7 +15,12 @@ import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class ManagementModal extends StatefulWidget { - const ManagementModal({Key? key}) : super(key: key); + final bool dialog; + + const ManagementModal({ + Key? key, + required this.dialog + }) : super(key: key); @override State createState() => _ManagementModalState(); @@ -364,8 +369,112 @@ class _ManagementModalState extends State with SingleTickerProv ); } - return SafeArea( - child: Container( + Widget header() { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Text( + AppLocalizations.of(context)!.manageServer, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ), + ], + ), + ], + ); + } + + List toggles() { + return [ + mainSwitch(), + Container(height: 10), + smallSwitch( + AppLocalizations.of(context)!.ruleFiltering, + Icons.filter_list_rounded, + serversProvider.serverStatus.data!.filteringEnabled, + (value) => updateBlocking(value: value, filter: 'filtering'), + serversProvider.protectionsManagementProcess.contains('filtering') + ), + smallSwitch( + AppLocalizations.of(context)!.safeBrowsing, + Icons.vpn_lock_rounded, + serversProvider.serverStatus.data!.safeBrowsingEnabled, + (value) => updateBlocking(value: value, filter: 'safeBrowsing'), + serversProvider.protectionsManagementProcess.contains('safeBrowsing') + ), + smallSwitch( + AppLocalizations.of(context)!.parentalFiltering, + Icons.block, + serversProvider.serverStatus.data!.parentalControlEnabled, + (value) => updateBlocking(value: value, filter: 'parentalControl'), + serversProvider.protectionsManagementProcess.contains('parentalControl') + ), + smallSwitch( + AppLocalizations.of(context)!.safeSearch, + Icons.search_rounded, + serversProvider.serverStatus.data!.safeSearchEnabled, + (value) => updateBlocking(value: value, filter: 'safeSearch'), + serversProvider.protectionsManagementProcess.contains('safeSearch') + ), + ]; + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + header(), + ...toggles() + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close), + ), + ], + ), + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ), + ), + ); + } + else { + return Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.only( @@ -373,66 +482,18 @@ class _ManagementModalState extends State with SingleTickerProv topRight: Radius.circular(28) ) ), - child: Wrap( + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, + Flexible( + child: SingleChildScrollView( + child: Wrap( children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Text( - AppLocalizations.of(context)!.manageServer, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ), + header(), + ...toggles() ], ), - ], - ), - mainSwitch(), - const SizedBox(height: 10), - smallSwitch( - AppLocalizations.of(context)!.ruleFiltering, - Icons.filter_list_rounded, - serversProvider.serverStatus.data!.filteringEnabled, - (value) => updateBlocking(value: value, filter: 'filtering'), - serversProvider.protectionsManagementProcess.contains('filtering') - ), - smallSwitch( - AppLocalizations.of(context)!.safeBrowsing, - Icons.vpn_lock_rounded, - serversProvider.serverStatus.data!.safeBrowsingEnabled, - (value) => updateBlocking(value: value, filter: 'safeBrowsing'), - serversProvider.protectionsManagementProcess.contains('safeBrowsing') - ), - smallSwitch( - AppLocalizations.of(context)!.parentalFiltering, - Icons.block, - serversProvider.serverStatus.data!.parentalControlEnabled, - (value) => updateBlocking(value: value, filter: 'parentalControl'), - serversProvider.protectionsManagementProcess.contains('parentalControl') - ), - smallSwitch( - AppLocalizations.of(context)!.safeSearch, - Icons.search_rounded, - serversProvider.serverStatus.data!.safeSearchEnabled, - (value) => updateBlocking(value: value, filter: 'safeSearch'), - serversProvider.protectionsManagementProcess.contains('safeSearch') + ), ), Padding( padding: const EdgeInsets.all(24), @@ -449,7 +510,7 @@ class _ManagementModalState extends State with SingleTickerProv if (Platform.isIOS) const SizedBox(height: 16) ], ), - ), - ); + ); + } } } \ No newline at end of file diff --git a/lib/screens/home/server_status.dart b/lib/screens/home/server_status.dart index c4d8d97..1df9767 100644 --- a/lib/screens/home/server_status.dart +++ b/lib/screens/home/server_status.dart @@ -15,8 +15,12 @@ class ServerStatus extends StatelessWidget { @override Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + return Container( - padding: const EdgeInsets.all(20), + padding: width > 700 + ? const EdgeInsets.only(left: 20, right: 20, bottom: 20) + : const EdgeInsets.all(20), child: Column( children: [ Text( @@ -29,11 +33,11 @@ class ServerStatus extends StatelessWidget { ), const SizedBox(height: 20), SizedBox( - height: 140, + height: width > 700 ? 70 : 140, child: GridView( physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: width > 700 ? 4 : 2, crossAxisSpacing: 10, mainAxisSpacing: 10, mainAxisExtent: 65 diff --git a/lib/screens/home/status_box.dart b/lib/screens/home/status_box.dart index 62d4279..2f57106 100644 --- a/lib/screens/home/status_box.dart +++ b/lib/screens/home/status_box.dart @@ -44,13 +44,15 @@ class StatusBox extends StatelessWidget { : Colors.grey.computeLuminance() > 0.5 ? Colors.black : Colors.white, ), const SizedBox(width: 12), - Text( - label, - style: TextStyle( - color: appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary.computeLuminance() > 0.5 ? Colors.black : Colors.white - : Colors.grey.computeLuminance() > 0.5 ? Colors.black : Colors.white, - fontWeight: FontWeight.w500 + Flexible( + child: Text( + label, + style: TextStyle( + color: appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary.computeLuminance() > 0.5 ? Colors.black : Colors.white + : Colors.grey.computeLuminance() > 0.5 ? Colors.black : Colors.white, + fontWeight: FontWeight.w500 + ), ), ) ], diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 5883523..0bf85d2 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -1,5 +1,9 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + +import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; +import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; @@ -35,6 +39,8 @@ class TopItems extends StatelessWidget { final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + bool? getIsBlocked() { if (type == 'topBlockedDomains') { return true; @@ -266,16 +272,32 @@ class TopItems extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( - onPressed: () => Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => TopItemsScreen( - type: type, - title: label, - isClient: clients, - data: generateData(), + onPressed: () => { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => TopItemsModal( + type: type, + title: label, + isClient: clients, + data: generateData(), + ) ) - ) - ), + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => TopItemsScreen( + type: type, + title: label, + isClient: clients, + data: generateData(), + ) + ) + ) + } + }, child: Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/screens/top_items/top_items_modal.dart b/lib/screens/top_items/top_items_modal.dart new file mode 100644 index 0000000..55aae09 --- /dev/null +++ b/lib/screens/top_items/top_items_modal.dart @@ -0,0 +1,276 @@ +// ignore_for_file: use_build_context_synchronously + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:percent_indicator/percent_indicator.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/home/top_items_options_modal.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + +import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/functions/copy_clipboard.dart'; +import 'package:adguard_home_manager/providers/logs_provider.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/functions/block_unblock_domain.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class TopItemsModal extends StatefulWidget { + final String type; + final String title; + final bool? isClient; + final List> data; + + const TopItemsModal({ + Key? key, + required this.type, + required this.title, + this.isClient, + required this.data, + }) : super(key: key); + + @override + State createState() => _TopItemsModalState(); +} + +class _TopItemsModalState extends State { + bool searchActive = false; + final TextEditingController searchController = TextEditingController(); + + List> data = []; + List> screenData = []; + + void search(String value) { + List> newValues = widget.data.where((item) => item.keys.toList()[0].contains(value)).toList(); + setState(() => screenData = newValues); + } + + @override + void initState() { + data = widget.data; + screenData = widget.data; + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + final logsProvider = Provider.of(context); + + int total = 0; + for (var element in data) { + total = total + int.parse(element.values.toList()[0].toString()); + } + + bool? getIsBlocked() { + if (widget.type == 'topBlockedDomains') { + return true; + } + else if (widget.type == 'topQueriedDomains') { + return false; + } + else { + return null; + } + } + + void changeBlockStatus(String status, String domain) async { + final result = await blockUnblock(context, domain, status); + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: result['message'], + color: result['success'] == true ? Colors.green : Colors.red + ); + } + + void openOptionsModal(String domain, String type) { + showDialog( + context: context, + builder: (context) => TopItemsOptionsModal( + isBlocked: getIsBlocked(), + changeStatus: (String status) => changeBlockStatus(status, domain), + copyToClipboard: () => copyToClipboard( + context: context, + value: domain, + successMessage: AppLocalizations.of(context)!.domainCopiedClipboard + ), + type: type, + ) + ); + } + + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 1, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, + ), + ], + ), + ), + Expanded( + flex: 1, + child: TextField( + controller: searchController, + onChanged: search, + decoration: InputDecoration( + filled: true, + fillColor: Theme.of(context).colorScheme.primary.withOpacity(0.1), + hintText: AppLocalizations.of(context)!.search, + prefixIcon: const Icon(Icons.search_rounded), + contentPadding: const EdgeInsets.only(left: 14, bottom: 9, top: 11), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + borderRadius: BorderRadius.circular(25.7), + ), + enabledBorder: UnderlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + borderRadius: BorderRadius.circular(25.7), + ), + ), + ), + ) + ], + ), + ), + if (screenData.isNotEmpty) Flexible( + child: ListView.builder( + padding: const EdgeInsets.only(top: 0), + itemCount: screenData.length, + itemBuilder: (context, index) { + String? name; + if (widget.isClient != null && widget.isClient == true) { + try { + name = serversProvider.serverStatus.data!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; + } catch (e) { + // ---- // + } + } + + return CustomListTile( + onTap: () { + if (widget.type == 'topQueriedDomains' || widget.type == 'topBlockedDomains') { + logsProvider.setSearchText(screenData[index].keys.toList()[0]); + logsProvider.setSelectedClients(null); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: screenData[index].keys.toList()[0], + clients: null + ) + ); + appConfigProvider.setSelectedScreen(2); + Navigator.pop(context); + } + else if (widget.type == 'topClients') { + logsProvider.setSearchText(null); + logsProvider.setSelectedClients([screenData[index].keys.toList()[0]]); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: null, + clients: [screenData[index].keys.toList()[0]] + ) + ); + appConfigProvider.setSelectedScreen(2); + Navigator.pop(context); + } + }, + onLongPress: () => openOptionsModal( + screenData[index].keys.toList()[0], + widget.type + ), + title: screenData[index].keys.toList()[0], + trailing: Text( + screenData[index].values.toList()[0].toString(), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + subtitleWidget: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (name != null) ...[ + Text( + name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 5), + ], + Row( + children: [ + SizedBox( + width: 50, + child: Text( + "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor + ), + ), + ), + const SizedBox(width: 10), + Flexible( + child: LinearPercentIndicator( + animation: true, + lineHeight: 4, + animationDuration: 500, + curve: Curves.easeOut, + percent: screenData[index].values.toList()[0]/total, + barRadius: const Radius.circular(5), + progressColor: Theme.of(context).colorScheme.primary, + backgroundColor: Theme.of(context).colorScheme.surfaceVariant, + ), + ), + const SizedBox(width: 10), + ], + ), + ], + ) + ); + } + ), + ), + if (screenData.isEmpty) Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.noItemsSearch, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ) + ], + ), + ), + ); + } +} \ No newline at end of file From 578e606b83c57beb0a2277b4b7e7079672d115c4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 15:58:06 +0200 Subject: [PATCH 057/676] Optimized logs --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/screens/logs/clients_modal.dart | 100 +++-- lib/screens/logs/filter_status_modal.dart | 208 ++++++----- lib/screens/logs/log_tile.dart | 427 ++++++++++++++++------ lib/screens/logs/logs.dart | 389 ++++++++++++-------- lib/screens/logs/logs_config_modal.dart | 320 +++++++++------- lib/screens/logs/logs_filters_modal.dart | 219 +++++++---- 8 files changed, 1043 insertions(+), 626 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 45b4526..8017577 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -606,5 +606,6 @@ "remainingTime": "Remaining time", "safeSearchSettings": "Safe search settings", "loadingSafeSearchSettings": "Loading safe search settings...", - "safeSearchSettingsNotLoaded": "Error when loading safe search settings." + "safeSearchSettingsNotLoaded": "Error when loading safe search settings.", + "loadingLogsSettings": "Loading logs settings..." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 97967c8..61aa7de 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -606,5 +606,6 @@ "remainingTime": "Tiempo restante", "safeSearchSettings": "Configuración de búsqueda segura", "loadingSafeSearchSettings": "Cargando configuración de búsqueda segura...", - "safeSearchSettingsNotLoaded": "Error al cargar la configuración de búsqueda segura." + "safeSearchSettingsNotLoaded": "Error al cargar la configuración de búsqueda segura.", + "loadingLogsSettings": "Cargando configuración de registros..." } \ No newline at end of file diff --git a/lib/screens/logs/clients_modal.dart b/lib/screens/logs/clients_modal.dart index f9b9099..bd39541 100644 --- a/lib/screens/logs/clients_modal.dart +++ b/lib/screens/logs/clients_modal.dart @@ -8,10 +8,12 @@ import 'package:adguard_home_manager/providers/logs_provider.dart'; class ClientsModal extends StatefulWidget { final List? value; + final bool dialog; const ClientsModal({ Key? key, - required this.value + required this.value, + required this.dialog }) : super(key: key); @override @@ -94,44 +96,36 @@ class _ClientsModalState extends State { }); } - return Container( - height: height >= (logsProvider.clients!.length*64) == true - ? logsProvider.clients!.length*64 - : height-50, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor - ), - child: Column( + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - top: 24, - bottom: 16, - ), - child: Icon( - Icons.smartphone_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), + Column( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 24, + bottom: 16, + ), + child: Icon( + Icons.smartphone_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + Text( + AppLocalizations.of(context)!.clients, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], ), - Text( - AppLocalizations.of(context)!.clients, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - Expanded( + Flexible( child: ListView.builder( - physics: height >= (logsProvider.clients!.length*64) == true - ? const NeverScrollableScrollPhysics() - : null, itemCount: logsProvider.clients!.length, itemBuilder: (context, index) => listItem( label: logsProvider.clients![index].ip, @@ -150,7 +144,7 @@ class _ClientsModalState extends State { } } ) - ), + ) ), Padding( padding: const EdgeInsets.all(24), @@ -176,7 +170,35 @@ class _ClientsModalState extends State { ), if (Platform.isIOS) const SizedBox(height: 16) ], - ), - ); + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: content() + ), + ); + } + else { + return ConstrainedBox( + constraints: BoxConstraints( + maxHeight: height-50 + ), + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: content() + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/logs/filter_status_modal.dart b/lib/screens/logs/filter_status_modal.dart index 16d9c5c..aec5aac 100644 --- a/lib/screens/logs/filter_status_modal.dart +++ b/lib/screens/logs/filter_status_modal.dart @@ -8,10 +8,12 @@ import 'package:adguard_home_manager/providers/logs_provider.dart'; class FilterStatusModal extends StatefulWidget { final String value; + final bool dialog; const FilterStatusModal({ Key? key, - required this.value + required this.value, + required this.dialog }) : super(key: key); @override @@ -31,8 +33,6 @@ class _FilterStatusModalState extends State { Widget build(BuildContext context) { final logsProvider = Provider.of(context); - final height = MediaQuery.of(context).size.height; - void apply() async { logsProvider.setSelectedResultStatus(selectedResultStatus); @@ -83,95 +83,94 @@ class _FilterStatusModalState extends State { ); } - return Container( - height: height >= (Platform.isIOS ? 736 : 720) == true - ? (Platform.isIOS ? 736 : 720) - : height-25, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor - ), - child: Column( + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - top: 24, - bottom: 16, - ), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Text( - AppLocalizations.of(context)!.responseStatus, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - Expanded( - child: ListView( - physics: height >= 720 == true - ? const NeverScrollableScrollPhysics() - : null, - children: [ - filterStatusListItem( - id: "all", - icon: Icons.shield_rounded, - label: AppLocalizations.of(context)!.all, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "filtered", - icon: Icons.shield_rounded, - label: AppLocalizations.of(context)!.filtered, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "processed", - icon: Icons.verified_user_rounded, - label: AppLocalizations.of(context)!.processedRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "whitelisted", - icon: Icons.verified_user_rounded, - label: AppLocalizations.of(context)!.processedWhitelistRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "blocked", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blocked, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "blocked_safebrowsing", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedSafeBrowsingRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "blocked_parental", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedParentalRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "safe_search", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedSafeSearchRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - - ], + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 24, + bottom: 16, + ), + child: Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + Text( + AppLocalizations.of(context)!.responseStatus, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ) + ], + ), + Container(height: 16), + filterStatusListItem( + id: "all", + icon: Icons.shield_rounded, + label: AppLocalizations.of(context)!.all, + onChanged: (value) => setState(() => selectedResultStatus = value!) + ), + filterStatusListItem( + id: "filtered", + icon: Icons.shield_rounded, + label: AppLocalizations.of(context)!.filtered, + onChanged: (value) => setState(() => selectedResultStatus = value!) + ), + filterStatusListItem( + id: "processed", + icon: Icons.verified_user_rounded, + label: AppLocalizations.of(context)!.processedRow, + onChanged: (value) => setState(() => selectedResultStatus = value!) + ), + filterStatusListItem( + id: "whitelisted", + icon: Icons.verified_user_rounded, + label: AppLocalizations.of(context)!.processedWhitelistRow, + onChanged: (value) => setState(() => selectedResultStatus = value!) + ), + filterStatusListItem( + id: "blocked", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blocked, + onChanged: (value) => setState(() => selectedResultStatus = value!) + ), + filterStatusListItem( + id: "blocked_safebrowsing", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedSafeBrowsingRow, + onChanged: (value) => setState(() => selectedResultStatus = value!) + ), + filterStatusListItem( + id: "blocked_parental", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedParentalRow, + onChanged: (value) => setState(() => selectedResultStatus = value!) + ), + filterStatusListItem( + id: "safe_search", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedSafeSearchRow, + onChanged: (value) => setState(() => selectedResultStatus = value!) + ), + + ], + ), ), ), Padding( @@ -188,7 +187,30 @@ class _FilterStatusModalState extends State { ), if (Platform.isIOS) const SizedBox(height: 16) ], - ), - ); + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: content() + ), + ); + } + else { + return Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: content() + ); + } } } \ No newline at end of file diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index ff7b058..5e10280 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -1,10 +1,10 @@ // ignore_for_file: use_build_context_synchronously + 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/home/top_items_options_modal.dart'; -import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/functions/block_unblock_domain.dart'; @@ -18,12 +18,16 @@ class LogTile extends StatelessWidget { final Log log; final int length; final int index; + final bool? isLogSelected; + final void Function(Log) onLogTap; const LogTile({ Key? key, required this.log, required this.length, - required this.index + required this.index, + this.isLogSelected, + required this.onLogTap }) : super(key: key); @override @@ -95,133 +99,250 @@ class LogTile extends StatelessWidget { ) ); } - - return Material( - color: Colors.transparent, - child: InkWell( - onTap: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen(log: log) - )), - onLongPress: () => openOptionsModal(log), - child: Container( - width: double.maxFinite, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SizedBox( - width: width-130, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - log.question.name, - style: TextStyle( - fontSize: 16, - height: 1.5, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 5), - if (log.client.length <= 15 && appConfigProvider.showNameTimeLogs == false) Row( + + if (width > 1100) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + borderRadius: BorderRadius.circular(28), + onTap: () => onLogTap(log), + child: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: isLogSelected == true + ? Theme.of(context).colorScheme.primaryContainer + : null + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + mainAxisSize: MainAxisSize.min, children: [ - ...[ - Icon( - Icons.smartphone_rounded, - size: 16, - color: Theme.of(context).listTileTheme.textColor, - ), - const SizedBox(width: 5), - Flexible( - child: Text( - log.client, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor, - fontSize: 14, - height: 1.4, - fontWeight: FontWeight.w400, + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + log.question.name, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), ), - ), - ) - ], - const SizedBox(width: 15), - ...[ - Icon( - Icons.schedule_rounded, - size: 16, - color: Theme.of(context).listTileTheme.textColor, - ), - const SizedBox(width: 5), - Flexible( - child: Text( - convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor, - fontSize: 13 + const SizedBox(height: 5), + if (log.client.length <= 15 && appConfigProvider.showNameTimeLogs == false) Row( + children: [ + ...[ + Icon( + Icons.smartphone_rounded, + size: 16, + color: Theme.of(context).listTileTheme.textColor, + ), + const SizedBox(width: 5), + Flexible( + child: Text( + log.client, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 14, + height: 1.4, + fontWeight: FontWeight.w400, + ), + ), + ) + ], + const SizedBox(width: 15), + ...[ + Icon( + Icons.schedule_rounded, + size: 16, + color: Theme.of(context).listTileTheme.textColor, + ), + const SizedBox(width: 5), + Flexible( + child: Text( + convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ), + ], + ], ), - ), + if (log.client.length > 15 || appConfigProvider.showNameTimeLogs == true) Column( + children: [ + Row( + children: [ + Icon( + Icons.smartphone_rounded, + size: 16, + color: Theme.of(context).listTileTheme.textColor, + ), + const SizedBox(width: 15), + Flexible( + child: Text( + log.client, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ) + ], + ), + if (appConfigProvider.showNameTimeLogs == true && log.clientInfo!.name != '') ...[ + const SizedBox(height: 10), + Row( + children: [ + Icon( + Icons.badge_rounded, + size: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 15), + Flexible( + child: Text( + log.clientInfo!.name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ) + ], + ), + ], + const SizedBox(height: 10), + Row( + children: [ + Icon( + Icons.schedule_rounded, + size: 16, + color: Theme.of(context).listTileTheme.textColor, + ), + const SizedBox(width: 15), + SizedBox( + child: Text( + convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ) + ], + ), + if (appConfigProvider.showNameTimeLogs == true && log.elapsedMs != '') ...[ + const SizedBox(height: 10), + Row( + children: [ + Icon( + Icons.timer, + size: 16, + color: Theme.of(context).listTileTheme.textColor, + ), + const SizedBox(width: 15), + SizedBox( + child: Text( + "${double.parse(log.elapsedMs).toStringAsFixed(2)} ms", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ) + ], + ), + ], + ], + ), + ], ), - ], + ) ], ), - if (log.client.length > 15 || appConfigProvider.showNameTimeLogs == true) Column( - children: [ - Row( - children: [ + ), + generateLogStatus() + ], + ) + ), + ), + ), + ); + } + else { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () => onLogTap(log), + onLongPress: () => openOptionsModal(log), + child: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + log.question.name, + style: TextStyle( + fontSize: 16, + height: 1.5, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 5), + if (log.client.length <= 15 && appConfigProvider.showNameTimeLogs == false) Row( + children: [ + ...[ Icon( Icons.smartphone_rounded, size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 15), + const SizedBox(width: 5), Flexible( child: Text( log.client, overflow: TextOverflow.ellipsis, style: TextStyle( color: Theme.of(context).listTileTheme.textColor, - fontSize: 13 + fontSize: 14, + height: 1.4, + fontWeight: FontWeight.w400, ), ), ) ], - ), - if (appConfigProvider.showNameTimeLogs == true && log.clientInfo!.name != '') ...[ - const SizedBox(height: 10), - Row( - children: [ - Icon( - Icons.badge_rounded, - size: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(width: 15), - Flexible( - child: Text( - log.clientInfo!.name, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor, - fontSize: 13 - ), - ), - ) - ], - ), - ], - const SizedBox(height: 10), - Row( - children: [ + const SizedBox(width: 15), + ...[ Icon( Icons.schedule_rounded, size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 15), - SizedBox( + const SizedBox(width: 5), + Flexible( child: Text( convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), overflow: TextOverflow.ellipsis, @@ -230,22 +351,23 @@ class LogTile extends StatelessWidget { fontSize: 13 ), ), - ) + ), ], - ), - if (appConfigProvider.showNameTimeLogs == true && log.elapsedMs != '') ...[ - const SizedBox(height: 10), + ], + ), + if (log.client.length > 15 || appConfigProvider.showNameTimeLogs == true) Column( + children: [ Row( children: [ Icon( - Icons.timer, + Icons.smartphone_rounded, size: 16, color: Theme.of(context).listTileTheme.textColor, ), const SizedBox(width: 15), - SizedBox( + Flexible( child: Text( - "${double.parse(log.elapsedMs).toStringAsFixed(2)} ms", + log.client, overflow: TextOverflow.ellipsis, style: TextStyle( color: Theme.of(context).listTileTheme.textColor, @@ -255,18 +377,85 @@ class LogTile extends StatelessWidget { ) ], ), + if (appConfigProvider.showNameTimeLogs == true && log.clientInfo!.name != '') ...[ + const SizedBox(height: 10), + Row( + children: [ + Icon( + Icons.badge_rounded, + size: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 15), + Flexible( + child: Text( + log.clientInfo!.name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ) + ], + ), + ], + const SizedBox(height: 10), + Row( + children: [ + Icon( + Icons.schedule_rounded, + size: 16, + color: Theme.of(context).listTileTheme.textColor, + ), + const SizedBox(width: 15), + SizedBox( + child: Text( + convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ) + ], + ), + if (appConfigProvider.showNameTimeLogs == true && log.elapsedMs != '') ...[ + const SizedBox(height: 10), + Row( + children: [ + Icon( + Icons.timer, + size: 16, + color: Theme.of(context).listTileTheme.textColor, + ), + const SizedBox(width: 15), + SizedBox( + child: Text( + "${double.parse(log.elapsedMs).toStringAsFixed(2)} ms", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ) + ], + ), + ], ], - ], - ), - ], + ), + ], + ), ), - ), - const SizedBox(width: 10), - generateLogStatus() - ], + const SizedBox(width: 10), + generateLogStatus() + ], + ), ), ), - ), - ); + ); + } } } \ No newline at end of file diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 5393c04..a900964 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -7,6 +9,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart'; import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; +import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -64,6 +67,8 @@ class _LogsWidgetState extends State { bool showDivider = true; + Log? selectedLog; + Future fetchLogs({ int? inOffset, bool? loadingMore, @@ -188,6 +193,8 @@ class _LogsWidgetState extends State { final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void updateConfig(Map data) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingSettings); @@ -252,12 +259,25 @@ class _LogsWidgetState extends State { void openFilersModal() { - showModalBottomSheet( - context: context, - builder: (context) => const LogsFiltersModal(), - backgroundColor: Colors.transparent, - isScrollControlled: true - ); + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => const LogsFiltersModal( + dialog: true, + ), + barrierDismissible: false + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => const LogsFiltersModal( + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ); + } } final Map translatedString = { @@ -319,6 +339,15 @@ class _LogsWidgetState extends State { log: logsProvider.logsData!.data[index], index: index, length: logsProvider.logsData!.data.length, + isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index], + onLogTap: (log) { + if (width <= 700) { + Navigator.push(context, MaterialPageRoute( + builder: (context) => LogDetailsScreen(log: log) + )); + } + setState(() => selectedLog = log); + } ); } } @@ -383,161 +412,207 @@ class _LogsWidgetState extends State { } } - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.logs), - centerTitle: false, - actions: [ - logsProvider.loadStatus == 1 - ? IconButton( - onPressed: openFilersModal, - icon: const Icon(Icons.filter_list_rounded) - ) - : const SizedBox(), - IconButton( - onPressed: () => { - showModalBottomSheet( - context: context, - builder: (context) => LogsConfigModal( - onConfirm: updateConfig, - onClear: clearQueries, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ) - }, - icon: const Icon(Icons.settings) - ), - const SizedBox(width: 5), - ], - bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null - ? PreferredSize( - preferredSize: const Size(double.maxFinite, 50), - child: Container( - height: 50, - width: double.maxFinite, - padding: const EdgeInsets.only(bottom: 10), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: showDivider == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.1) - : Colors.transparent, - ) + Widget logsScreen() { + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.logs), + centerTitle: false, + actions: [ + if (!(Platform.isAndroid || Platform.isIOS)) IconButton( + onPressed: () => fetchLogs(inOffset: 0), + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ), + logsProvider.loadStatus == 1 + ? IconButton( + onPressed: openFilersModal, + icon: const Icon(Icons.filter_list_rounded), + tooltip: AppLocalizations.of(context)!.filters, + ) + : const SizedBox(), + IconButton( + tooltip: AppLocalizations.of(context)!.settings, + onPressed: () => { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => LogsConfigModal( + onConfirm: updateConfig, + onClear: clearQueries, + dialog: true, + ), + barrierDismissible: false ) - ), - child: ListView( - scrollDirection: Axis.horizontal, - children: [ - if (logsProvider.appliedFilters.searchText != null) ...[ + } + else { + showModalBottomSheet( + context: context, + builder: (context) => LogsConfigModal( + onConfirm: updateConfig, + onClear: clearQueries, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ) + } + }, + icon: const Icon(Icons.settings) + ), + const SizedBox(width: 5), + ], + bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + ? PreferredSize( + preferredSize: const Size(double.maxFinite, 50), + child: Container( + height: 50, + width: double.maxFinite, + padding: const EdgeInsets.only(bottom: 10), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: showDivider == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.1) + : Colors.transparent, + ) + ) + ), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + if (logsProvider.appliedFilters.searchText != null) ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.link_rounded, + ), + label: Row( + children: [ + Text( + logsProvider.appliedFilters.searchText!, + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: null, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.setSearchText(null); + fetchLogs( + inOffset: 0, + searchText: '' + ); + }, + ), + ], + if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.shield_rounded, + ), + label: Row( + children: [ + Text( + translatedString[logsProvider.appliedFilters.selectedResultStatus]!, + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: logsProvider.appliedFilters.searchText, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.setSelectedResultStatus('all'); + fetchLogs( + inOffset: 0, + responseStatus: 'all' + ); + }, + ), + ], + if (logsProvider.appliedFilters.clients != null) ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.smartphone_rounded, + ), + label: Row( + children: [ + Text( + logsProvider.appliedFilters.clients!.length == 1 + ? logsProvider.appliedFilters.clients![0] + : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: logsProvider.appliedFilters.searchText, + clients: null + ) + ); + logsProvider.setSelectedClients(null); + fetchLogs( + inOffset: 0, + responseStatus: logsProvider.appliedFilters.selectedResultStatus + ); + }, + ), + ], const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.link_rounded, - ), - label: Row( - children: [ - Text( - logsProvider.appliedFilters.searchText!, - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: null, - clients: logsProvider.appliedFilters.clients - ) - ); - logsProvider.setSearchText(null); - fetchLogs( - inOffset: 0, - searchText: '' - ); - }, - ), ], - if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.shield_rounded, - ), - label: Row( - children: [ - Text( - translatedString[logsProvider.appliedFilters.selectedResultStatus]!, - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: logsProvider.appliedFilters.searchText, - clients: logsProvider.appliedFilters.clients - ) - ); - logsProvider.setSelectedResultStatus('all'); - fetchLogs( - inOffset: 0, - responseStatus: 'all' - ); - }, - ), - ], - if (logsProvider.appliedFilters.clients != null) ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.smartphone_rounded, - ), - label: Row( - children: [ - Text( - logsProvider.appliedFilters.clients!.length == 1 - ? logsProvider.appliedFilters.clients![0] - : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: logsProvider.appliedFilters.searchText, - clients: null - ) - ); - logsProvider.setSelectedClients(null); - fetchLogs( - inOffset: 0, - responseStatus: logsProvider.appliedFilters.selectedResultStatus - ); - }, - ), - ], - const SizedBox(width: 15), - ], - ), + ), + ) ) + : null, + ), + body: generateBody() + ); + } + + if (width > 1100) { + return Material( + color: Colors.transparent, + child: Row( + children: [ + Expanded( + flex: 1, + child: logsScreen() + ), + Expanded( + flex: 2, + child: selectedLog != null + ? LogDetailsScreen(log: selectedLog!) + : const SizedBox() ) - : null, - ), - body: generateBody() - ); + ], + ), + ); + } + else { + return logsScreen(); + } } } \ No newline at end of file diff --git a/lib/screens/logs/logs_config_modal.dart b/lib/screens/logs/logs_config_modal.dart index 9af7335..a540559 100644 --- a/lib/screens/logs/logs_config_modal.dart +++ b/lib/screens/logs/logs_config_modal.dart @@ -12,11 +12,13 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; class LogsConfigModal extends StatelessWidget { final void Function(Map) onConfirm; final void Function() onClear; + final bool dialog; const LogsConfigModal({ Key? key, required this.onConfirm, required this.onClear, + required this.dialog }) : super(key: key); @override @@ -30,6 +32,7 @@ class LogsConfigModal extends StatelessWidget { context: context, onConfirm: onConfirm, onClear: onClear, + dialog: dialog, ); } } @@ -40,6 +43,7 @@ class LogsConfigModalWidget extends StatefulWidget { final BuildContext context; final void Function(Map) onConfirm; final void Function() onClear; + final bool dialog; const LogsConfigModalWidget({ Key? key, @@ -48,6 +52,7 @@ class LogsConfigModalWidget extends StatefulWidget { required this.context, required this.onConfirm, required this.onClear, + required this.dialog }) : super(key: key); @override @@ -146,125 +151,154 @@ class _LogsConfigModalWidgetState extends State { Widget generateBody() { switch (loadStatus) { case 0: - return const Center( - child: CircularProgressIndicator(), + return Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.loadingLogsSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), ); case 1: return Column( + mainAxisSize: MainAxisSize.min, children: [ - Expanded( - child: ListView( - physics: (Platform.isIOS ? 436 : 420) < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.settings, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.logsSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - 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: () => setState(() => generalSwitch = !generalSwitch), - borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.enableLog, - style: const TextStyle( - fontSize: 18, - ), + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.settings, + size: 24, + color: Theme.of(context).listTileTheme.iconColor ), - Switch( - value: generalSwitch, - onChanged: (value) => setState(() => generalSwitch = value), - ) - ], + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.logsSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], + ), + 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: () => setState(() => generalSwitch = !generalSwitch), + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.enableLog, + style: const TextStyle( + fontSize: 18, + ), + ), + Switch( + value: generalSwitch, + onChanged: (value) => setState(() => generalSwitch = value), + ) + ], + ), ), ), ), ), - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 14), - child: Column( - children: [ - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => setState(() => anonymizeClientIp = !anonymizeClientIp), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 30), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.anonymizeClientIp, - style: const TextStyle( - fontSize: 16 + Container(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 14), + child: Column( + children: [ + Material( + color: Colors.transparent, + child: InkWell( + onTap: () => setState(() => anonymizeClientIp = !anonymizeClientIp), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.anonymizeClientIp, + style: const TextStyle( + fontSize: 16 + ), ), - ), - Switch( - value: anonymizeClientIp, - onChanged: (value) => setState(() => anonymizeClientIp = value), + Switch( + value: anonymizeClientIp, + onChanged: (value) => setState(() => anonymizeClientIp = value), + ) + ], + ), + ), + ), + ), + Container(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: DropdownButtonFormField( + items: retentionItems.map>((Map item) { + return DropdownMenuItem( + value: item['value'].toString(), + child: Text(item['label']), + ); + }).toList(), + value: retentionTime, + onChanged: (value) => setState(() => retentionTime = value), + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) ) - ], + ), + label: Text(AppLocalizations.of(context)!.retentionTime) ), + borderRadius: BorderRadius.circular(20), ), ), - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: DropdownButtonFormField( - items: retentionItems.map>((Map item) { - return DropdownMenuItem( - value: item['value'].toString(), - child: Text(item['label']), - ); - }).toList(), - value: retentionTime, - onChanged: (value) => setState(() => retentionTime = value), - decoration: InputDecoration( - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - label: Text(AppLocalizations.of(context)!.retentionTime) - ), - borderRadius: BorderRadius.circular(20), - ), - ), - ], - ), - ) - ], + ], + ), + ) + ], + ), ), ), Padding( @@ -316,31 +350,29 @@ class _LogsConfigModalWidgetState extends State { ); case 2: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.logSettingsNotLoaded, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 22, - color: Colors.grey, - ), + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.logSettingsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant ), - ) - ], - ), + ), + ) + ], ); default: @@ -348,16 +380,28 @@ class _LogsConfigModalWidgetState extends State { } } - return Container( - height: Platform.isIOS ? 436 : 420, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: generateBody() ), - color: Theme.of(context).dialogBackgroundColor - ), - child: generateBody() - ); + ); + } + else { + return Container( + height: Platform.isIOS ? 436 : 420, + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: generateBody() + ); + } } } \ No newline at end of file diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/logs_filters_modal.dart index e9a6052..19ba0c0 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/logs_filters_modal.dart @@ -18,24 +18,32 @@ import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; class LogsFiltersModal extends StatelessWidget { - const LogsFiltersModal({Key? key}) : super(key: key); + final bool dialog; + + const LogsFiltersModal({ + Key? key, + required this.dialog + }) : super(key: key); @override Widget build(BuildContext context) { final logsProvider = Provider.of(context); return LogsFiltersModalWidget( - logsProvider: logsProvider + logsProvider: logsProvider, + dialog: dialog, ); } } class LogsFiltersModalWidget extends StatefulWidget { final LogsProvider logsProvider; + final bool dialog; const LogsFiltersModalWidget({ Key? key, - required this.logsProvider + required this.logsProvider, + required this.dialog }) : super(key: key); @override @@ -57,6 +65,8 @@ class _LogsFiltersModalWidgetState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + final Map translatedString = { "all": AppLocalizations.of(context)!.all, "filtered": AppLocalizations.of(context)!.filtered, @@ -101,25 +111,51 @@ class _LogsFiltersModalWidgetState extends State { } void openSelectFilterStatus() { - showModalBottomSheet( - context: context, - builder: (context) => FilterStatusModal( - value: logsProvider.selectedResultStatus, - ), - isScrollControlled: true, - backgroundColor: Colors.transparent - ); + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + barrierDismissible: false, + context: context, + builder: (context) => FilterStatusModal( + value: logsProvider.selectedResultStatus, + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => FilterStatusModal( + value: logsProvider.selectedResultStatus, + dialog: false, + ), + isScrollControlled: true, + backgroundColor: Colors.transparent + ); + } } void openSelectClients() { - showModalBottomSheet( - context: context, - builder: (context) => ClientsModal( - value: logsProvider.selectedClients, - ), - isScrollControlled: true, - backgroundColor: Colors.transparent - ); + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => ClientsModal( + value: logsProvider.selectedClients, + dialog: true, + ), + barrierDismissible: false + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => ClientsModal( + value: logsProvider.selectedClients, + dialog: false, + ), + isScrollControlled: true, + backgroundColor: Colors.transparent + ); + } } void filterLogs() async { @@ -161,47 +197,45 @@ class _LogsFiltersModalWidgetState extends State { } } - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - height: Platform.isIOS ? 446 : 430, - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ) - ), - child: Column( - children: [ - Expanded( - child: ListView( - physics: (Platform.isIOS ? 416 : 400) < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( children: [ - Padding( - padding: const EdgeInsets.only( - top: 24, - bottom: 16, - ), - child: Icon( - Icons.filter_list_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 24, + bottom: 16, + ), + child: Icon( + Icons.filter_list_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + Text( + AppLocalizations.of(context)!.filters, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w400, + height: 1.3, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], ), - Text( - AppLocalizations.of(context)!.filters, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - height: 1.3, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Row( @@ -233,7 +267,7 @@ class _LogsFiltersModalWidgetState extends State { ], ), ), - const SizedBox(height: 16), + Container(height: 16), CustomListTile( title: AppLocalizations.of(context)!.client, subtitle: logsProvider.selectedClients != null @@ -270,26 +304,55 @@ class _LogsFiltersModalWidgetState extends State { ], ), ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: resetFilters, - child: Text(AppLocalizations.of(context)!.resetFilters) - ), - TextButton( - onPressed: () => filterLogs(), - child: Text(AppLocalizations.of(context)!.apply) - ), - ], - ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: resetFilters, + child: Text(AppLocalizations.of(context)!.resetFilters) + ), + TextButton( + onPressed: () => filterLogs(), + child: Text(AppLocalizations.of(context)!.apply) + ), + ], ), - if (Platform.isIOS) const SizedBox(height: 16) - ], + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); + } + + if (widget.dialog == true) { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: content() + ) ), - ), - ); + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).dialogBackgroundColor, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ) + ), + child: content() + ), + ); + } } } \ No newline at end of file From 5660aefdc589c52ee184e943876181d91e4de952 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 19:00:06 +0200 Subject: [PATCH 058/676] Adapted app updater --- lib/base.dart | 22 ++++++++++++++++------ lib/screens/settings/settings.dart | 2 +- lib/widgets/update_modal.dart | 26 ++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/lib/base.dart b/lib/base.dart index c4c3c68..1c5ad7d 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -55,15 +55,25 @@ class _BaseState extends State with WidgetsBindingObserver { } Future checkInstallationSource() async { - if (Platform.isAndroid) { - Source installationSource = await StoreChecker.getSource; - if (installationSource != Source.IS_INSTALLED_FROM_PLAY_STORE) { - final result = await checkAppUpdatesGitHub(); - if (result['result'] == 'success') { - if (updateExists(widget.appConfigProvider.getAppInfo!.version, result['body'].tagName)) { + final result = await checkAppUpdatesGitHub(); + if (result['result'] == 'success') { + final update = updateExists(widget.appConfigProvider.getAppInfo!.version, result['body'].tagName); + if (update == true) { + if (Platform.isAndroid) { + Source installationSource = await StoreChecker.getSource; + if (installationSource == Source.IS_INSTALLED_FROM_PLAY_STORE) { + return null; + } + else { return result['body']; } } + else if (Platform.isIOS) { + return null; + } + else { + return result['body']; + } } } return null; diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 9d983d2..74f8a40 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -231,7 +231,7 @@ class SettingsWidget extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - IconButton( + if (Platform.isAndroid) IconButton( onPressed: () => openUrl(Urls.playStore), icon: SvgPicture.asset( 'assets/resources/google-play.svg', diff --git a/lib/widgets/update_modal.dart b/lib/widgets/update_modal.dart index b3acc8d..a6f456a 100644 --- a/lib/widgets/update_modal.dart +++ b/lib/widgets/update_modal.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -22,14 +24,30 @@ class UpdateModal extends StatefulWidget { class _UpdateModalState extends State { bool doNotRemember = false; - String getDownloadLink() { - return widget.gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('apk')).browserDownloadUrl; + String? getDownloadLink() { + if (Platform.isAndroid) { + return widget.gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('apk')).browserDownloadUrl; + } + else if (Platform.isMacOS) { + return widget.gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('macOS')).browserDownloadUrl; // macOS package is a zip + } + else if (Platform.isWindows) { + return widget.gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('exe')).browserDownloadUrl; + } + else if (Platform.isLinux) { + return widget.gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('deb')).browserDownloadUrl; + } + else { + return null; + } } @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); + final downloadLink = getDownloadLink(); + return AlertDialog( scrollable: true, title: Column( @@ -104,10 +122,10 @@ class _UpdateModalState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TextButton( + if (downloadLink != null) TextButton( onPressed: () { Navigator.pop(context); - widget.onDownload(getDownloadLink(), widget.gitHubRelease.tagName); + widget.onDownload(downloadLink, widget.gitHubRelease.tagName); }, child: Text(AppLocalizations.of(context)!.download) ), From 3c924570409eb27115d735d3ee61f30449b6f327 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 21:34:00 +0200 Subject: [PATCH 059/676] Adapted clients screen --- lib/screens/clients/active_client_tile.dart | 100 +++++++ lib/screens/clients/added_client_tile.dart | 250 ++++++++++++++++++ lib/screens/clients/added_list.dart | 156 ++++------- lib/screens/clients/client_screen.dart | 179 +++++++++---- lib/screens/clients/clients.dart | 226 ++++++++++------ lib/screens/clients/clients_desktop_view.dart | 161 +++++++++++ lib/screens/clients/clients_list.dart | 56 ++-- lib/screens/clients/fab.dart | 32 ++- lib/screens/clients/logs_list_client.dart | 223 ++++++++++++++++ lib/screens/clients/safe_search_modal.dart | 187 ++++++------- lib/screens/clients/search_clients.dart | 38 ++- lib/screens/logs/log_tile.dart | 2 +- lib/widgets/custom_list_tile.dart | 5 +- lib/widgets/tab_content_list.dart | 7 +- 14 files changed, 1249 insertions(+), 373 deletions(-) create mode 100644 lib/screens/clients/active_client_tile.dart create mode 100644 lib/screens/clients/added_client_tile.dart create mode 100644 lib/screens/clients/clients_desktop_view.dart create mode 100644 lib/screens/clients/logs_list_client.dart diff --git a/lib/screens/clients/active_client_tile.dart b/lib/screens/clients/active_client_tile.dart new file mode 100644 index 0000000..cabbb6c --- /dev/null +++ b/lib/screens/clients/active_client_tile.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + +import 'package:adguard_home_manager/models/clients.dart'; + +class ActiveClientTile extends StatelessWidget { + final AutoClient client; + final void Function(AutoClient) onTap; + final bool splitView; + final AutoClient? selectedClient; + + const ActiveClientTile({ + Key? key, + required this.client, + required this.onTap, + required this.splitView, + this.selectedClient + }) : super(key: key); + + @override + Widget build(BuildContext context) { + if (splitView == true) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + borderRadius: BorderRadius.circular(28), + onTap: () => onTap(client), + child: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: client == selectedClient + ? Theme.of(context).colorScheme.primaryContainer + : null + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + client.name != '' + ? client.name! + : client.ip, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + if (client.name != '') Text(client.ip) + ], + ), + ) + ], + ), + ), + Text( + client.source, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ) + ), + ), + ), + ); + } + else { + return CustomListTile( + title: client.name != '' + ? client.name! + : client.ip, + subtitle: client.name != '' + ? client.ip + : null, + trailing: Text( + client.source, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + onTap: () => onTap(client), + ); + } + } +} \ No newline at end of file diff --git a/lib/screens/clients/added_client_tile.dart b/lib/screens/clients/added_client_tile.dart new file mode 100644 index 0000000..d8a4b8f --- /dev/null +++ b/lib/screens/clients/added_client_tile.dart @@ -0,0 +1,250 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.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/clients.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; + +class AddedClientTile extends StatefulWidget { + final Client client; + final void Function(Client) onTap; + final void Function(Client) onLongPress; + final void Function(Client) onEdit; + final Client? selectedClient; + final bool? splitView; + + const AddedClientTile({ + Key? key, + required this.client, + required this.onTap, + required this.onLongPress, + required this.onEdit, + this.selectedClient, + required this.splitView + }) : super(key: key); + + @override + State createState() => _AddedClientTileState(); +} + +class _AddedClientTileState extends State { + bool hover = false; + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + if (widget.splitView == true) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + borderRadius: BorderRadius.circular(28), + onTap: () => widget.onTap(widget.client), + onHover: (v) => setState(() => hover = v), + child: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: widget.client == widget.selectedClient + ? Theme.of(context).colorScheme.primaryContainer + : null + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + const SizedBox(height: 8), + Row( + children: [ + Icon( + Icons.filter_list_rounded, + size: 19, + color: widget.client.filteringEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.vpn_lock_rounded, + size: 18, + color: widget.client.safebrowsingEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.block, + size: 18, + color: widget.client.parentalEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.search_rounded, + size: 19, + color: serverVersionIsAhead( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? widget.client.safeSearch != null && widget.client.safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + : widget.client.safesearchEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ) + ], + ) + ], + ), + ) + ], + ), + ), + if (hover == true) IconButton( + onPressed: () => widget.onEdit(widget.client), + icon: const Icon(Icons.edit_rounded) + ) + ], + ) + ), + ), + ), + ); + } + else { + return CustomListTile( + onLongPress: () => widget.onLongPress(widget.client), + onTap: () => widget.onTap(widget.client), + onHover: (v) => setState(() => hover = v), + title: widget.client.name, + subtitleWidget: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor + ), + ), + const SizedBox(height: 8), + Row( + children: [ + Icon( + Icons.filter_list_rounded, + size: 19, + color: widget.client.filteringEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.vpn_lock_rounded, + size: 18, + color: widget.client.safebrowsingEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.block, + size: 18, + color: widget.client.parentalEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.search_rounded, + size: 19, + color: serverVersionIsAhead( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? widget.client.safeSearch != null && widget.client.safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + : widget.client.safesearchEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ) + ], + ) + ], + ), + trailing: hover == true + ? IconButton( + onPressed: () => widget.onEdit(widget.client), + icon: const Icon(Icons.edit_rounded) + ) + : null, + ); + } + } +} \ No newline at end of file diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 922d2de..9bb3ab5 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -1,12 +1,16 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:flutter/rendering.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/client_screen.dart'; +import 'package:adguard_home_manager/screens/clients/added_client_tile.dart'; import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/fab.dart'; import 'package:adguard_home_manager/screens/clients/options_modal.dart'; @@ -27,13 +31,19 @@ class AddedList extends StatefulWidget { final LoadStatus loadStatus; final List data; final Future Function() fetchClients; + final void Function(Client) onClientSelected; + final Client? selectedClient; + final bool splitView; const AddedList({ Key? key, required this.scrollController, required this.loadStatus, required this.data, - required this.fetchClients + required this.fetchClients, + required this.onClientSelected, + this.selectedClient, + required this.splitView }) : super(key: key); @override @@ -69,6 +79,8 @@ class _AddedListState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void confirmEditClient(Client client) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingClient); @@ -130,6 +142,10 @@ class _AddedListState extends State { clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); serversProvider.setClientsData(clientsData); + if (widget.splitView == true) { + SplitView.of(context).popUntil(0); + } + showSnacbkar( context: context, appConfigProvider: appConfigProvider, @@ -150,15 +166,31 @@ class _AddedListState extends State { } void openClientModal(Client client) { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => ClientScreen( - onConfirm: confirmEditClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, - onDelete: deleteClient, - client: client, - ) - )); + if (width > 900 || !(Platform.isAndroid | Platform.isIOS)) { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => ClientScreen( + onConfirm: confirmEditClient, + serverVersion: serversProvider.serverStatus.data!.serverVersion, + onDelete: deleteClient, + client: client, + dialog: true, + ) + ); + } + else { + Navigator.push(context, MaterialPageRoute( + fullscreenDialog: true, + builder: (BuildContext context) => ClientScreen( + onConfirm: confirmEditClient, + serverVersion: serversProvider.serverStatus.data!.serverVersion, + onDelete: deleteClient, + client: client, + dialog: false, + ) + )); + } } void openDeleteModal(Client client) { @@ -181,6 +213,10 @@ class _AddedListState extends State { } return CustomTabContentList( + noSliver: !(Platform.isAndroid || Platform.isIOS), + listPadding: widget.splitView == true + ? const EdgeInsets.only(top: 8) + : null, loadingGenerator: () => SizedBox( width: double.maxFinite, height: MediaQuery.of(context).size.height-171, @@ -202,98 +238,14 @@ class _AddedListState extends State { ), ), itemsCount: widget.data.length, - contentWidget: (index) => ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - isThreeLine: true, - onLongPress: () => openOptionsModal(widget.data[index]), - onTap: () => openClientModal(widget.data[index]), - title: Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Text( - widget.data[index].name, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.data[index].ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor - ), - ), - const SizedBox(height: 7), - Row( - children: [ - Icon( - Icons.filter_list_rounded, - size: 19, - color: widget.data[index].filteringEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.vpn_lock_rounded, - size: 18, - color: widget.data[index].safebrowsingEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.block, - size: 18, - color: widget.data[index].parentalEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.search_rounded, - size: 19, - color: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? widget.data[index].safeSearch != null && widget.data[index].safeSearch!.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - : widget.data[index].safesearchEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ) - ], - ) - ], - ), - ), + contentWidget: (index) => AddedClientTile( + selectedClient: widget.selectedClient, + client: widget.data[index], + onTap: widget.onClientSelected, + onLongPress: openOptionsModal, + onEdit: openClientModal, + splitView: widget.splitView, + ), noData: SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart index 461ba42..2e282f5 100644 --- a/lib/screens/clients/client_screen.dart +++ b/lib/screens/clients/client_screen.dart @@ -19,6 +19,7 @@ class ClientScreen extends StatefulWidget { final String serverVersion; final void Function(Client) onConfirm; final void Function(Client)? onDelete; + final bool dialog; const ClientScreen({ Key? key, @@ -26,6 +27,7 @@ class ClientScreen extends StatefulWidget { required this.serverVersion, required this.onConfirm, this.onDelete, + required this.dialog }) : super(key: key); @override @@ -300,51 +302,13 @@ class _ClientScreenState extends State { ), ); } - - return Scaffold( - appBar: AppBar( - leading: IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.close) - ), - title: Text( - widget.client != null - ? AppLocalizations.of(context)!.client - : AppLocalizations.of(context)!.addClient - ), - actions: [ - if (widget.client == null || (widget.client != null && editMode == true)) IconButton( - onPressed: validValues == true - ? () { - createClient(); - Navigator.pop(context); - } - : null, - icon: Icon( - widget.client != null && editMode == true - ? Icons.save_rounded - : Icons.check_rounded - ), - tooltip: widget.client != null && editMode == true - ? AppLocalizations.of(context)!.save - : AppLocalizations.of(context)!.confirm, - ), - if (widget.client != null && editMode == false) IconButton( - onPressed: () => setState(() => editMode = true), - icon: const Icon(Icons.edit_rounded), - tooltip: AppLocalizations.of(context)!.edit, - ), - if (widget.client != null) IconButton( - onPressed: openDeleteClientScreen, - icon: const Icon(Icons.delete_rounded), - tooltip: AppLocalizations.of(context)!.delete, - ), - const SizedBox(width: 10), - ], - ), - body: ListView( + + Widget content(bool withPaddingTop) { + return ListView( + padding: const EdgeInsets.only(top: 0), children: [ - const SizedBox(height: 24), + if (withPaddingTop == true) const SizedBox(height: 24), + if (withPaddingTop == false) const SizedBox(height: 6), Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: TextFormField( @@ -693,10 +657,7 @@ class _ClientScreenState extends State { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - SizedBox( - width: editMode == true - ? MediaQuery.of(context).size.width - 108 - : MediaQuery.of(context).size.width - 40, + Expanded( child: TextFormField( enabled: editMode, controller: controller['controller'], @@ -751,7 +712,125 @@ class _ClientScreenState extends State { ), const SizedBox(height: 20) ], - ), - ); + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded) + ), + const SizedBox(width: 8), + Text( + widget.client != null + ? AppLocalizations.of(context)!.client + : AppLocalizations.of(context)!.addClient, + style: const TextStyle( + fontSize: 22 + ), + ), + ], + ), + Row( + children: [ + if (widget.client == null || (widget.client != null && editMode == true)) IconButton( + onPressed: validValues == true + ? () { + createClient(); + Navigator.pop(context); + } + : null, + icon: Icon( + widget.client != null && editMode == true + ? Icons.save_rounded + : Icons.check_rounded + ), + tooltip: widget.client != null && editMode == true + ? AppLocalizations.of(context)!.save + : AppLocalizations.of(context)!.confirm, + ), + if (widget.client != null && editMode == false) IconButton( + onPressed: () => setState(() => editMode = true), + icon: const Icon(Icons.edit_rounded), + tooltip: AppLocalizations.of(context)!.edit, + ), + if (widget.client != null) IconButton( + onPressed: openDeleteClientScreen, + icon: const Icon(Icons.delete_rounded), + tooltip: AppLocalizations.of(context)!.delete, + ), + const SizedBox(width: 10), + ], + ) + ], + ), + ), + Flexible( + child: content(false) + ) + ], + ), + ), + ); + } + else { + return Scaffold( + appBar: AppBar( + leading: IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.close) + ), + title: Text( + widget.client != null + ? AppLocalizations.of(context)!.client + : AppLocalizations.of(context)!.addClient + ), + actions: [ + if (widget.client == null || (widget.client != null && editMode == true)) IconButton( + onPressed: validValues == true + ? () { + createClient(); + Navigator.pop(context); + } + : null, + icon: Icon( + widget.client != null && editMode == true + ? Icons.save_rounded + : Icons.check_rounded + ), + tooltip: widget.client != null && editMode == true + ? AppLocalizations.of(context)!.save + : AppLocalizations.of(context)!.confirm, + ), + if (widget.client != null && editMode == false) IconButton( + onPressed: () => setState(() => editMode = true), + icon: const Icon(Icons.edit_rounded), + tooltip: AppLocalizations.of(context)!.edit, + ), + if (widget.client != null) IconButton( + onPressed: openDeleteClientScreen, + icon: const Icon(Icons.delete_rounded), + tooltip: AppLocalizations.of(context)!.delete, + ), + const SizedBox(width: 10), + ], + ), + body: content(true) + ); + } } } \ No newline at end of file diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 549b242..3b52760 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -1,9 +1,14 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/clients_list.dart'; import 'package:adguard_home_manager/screens/clients/search_clients.dart'; +import 'package:adguard_home_manager/screens/clients/logs_list_client.dart'; +import 'package:adguard_home_manager/screens/clients/clients_desktop_view.dart'; import 'package:adguard_home_manager/screens/clients/added_list.dart'; import 'package:adguard_home_manager/models/app_log.dart'; @@ -90,83 +95,154 @@ class _ClientsWidgetState extends State with TickerProviderStateM @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; - return DefaultTabController( - length: 2, - child: NestedScrollView( - controller: scrollController, - headerSliverBuilder: ((context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - title: Text(AppLocalizations.of(context)!.clients), - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded) ...[ - IconButton( - onPressed: () => { - Navigator.push(context, MaterialPageRoute( - builder: (context) => const SearchClients() - )) - }, - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.searchClients, - ), - const SizedBox(width: 10), - ] - ], - bottom: TabBar( - controller: tabController, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - icon: const Icon(Icons.devices), - text: AppLocalizations.of(context)!.activeClients, - ), - Tab( - icon: const Icon(Icons.add_rounded), - text: AppLocalizations.of(context)!.added, - ), - ] - ) - ), - ) - ]; - }), - body: Container( - decoration: BoxDecoration( - color: Theme.of(context).scaffoldBackgroundColor, - border: Border( - top: BorderSide( - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.1) - ) - ) + PreferredSizeWidget tabBar() { + return TabBar( + controller: tabController, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.devices), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.activeClients) + ], + ), ), - child: TabBarView( - controller: tabController, - children: [ - ClientsList( - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.autoClientsData : [], - fetchClients: fetchClients, - ), - AddedList( - scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clients : [], - fetchClients: fetchClients, - ), - ] + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.add_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.added) + ], + ), + ), + ] + ); + } + + Widget tabBarView() { + return TabBarView( + controller: tabController, + children: [ + ClientsList( + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == LoadStatus.loaded + ? serversProvider.clients.data!.autoClientsData : [], + fetchClients: fetchClients, + onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( + builder: (context) => LogsListClient( + ip: client.ip, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider + ) + )), + splitView: false, + ), + AddedList( + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == LoadStatus.loaded + ? serversProvider.clients.data!.clients : [], + fetchClients: fetchClients, + onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( + builder: (context) => LogsListClient( + ip: client.ids[0], + serversProvider: serversProvider, + appConfigProvider: appConfigProvider + ) + )), + splitView: false, + ), + ] + ); + } + + if (!(Platform.isAndroid || Platform.isIOS)) { + if (width > 900) { + return SplitView.material( + breakpoint: 900, + hideDivider: true, + child: ClientsDesktopView( + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + fetchClients: fetchClients, ) - ), - ) - ); + ); + } + else { + return DefaultTabController( + length: 2, + child: Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.clients), + centerTitle: false, + actions: [ + if (serversProvider.clients.loadStatus == LoadStatus.loaded) ...[ + IconButton( + onPressed: () => { + Navigator.push(context, MaterialPageRoute( + builder: (context) => const SearchClients() + )) + }, + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.searchClients, + ), + const SizedBox(width: 10), + ] + ], + bottom: tabBar() + ), + body: tabBarView(), + ), + ); + } + } + else { + return DefaultTabController( + length: 2, + child: NestedScrollView( + controller: scrollController, + headerSliverBuilder: ((context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + title: Text(AppLocalizations.of(context)!.clients), + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + actions: [ + if (serversProvider.clients.loadStatus == LoadStatus.loaded) ...[ + IconButton( + onPressed: () => { + Navigator.push(context, MaterialPageRoute( + builder: (context) => const SearchClients() + )) + }, + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.searchClients, + ), + const SizedBox(width: 10), + ] + ], + bottom: tabBar() + ), + ) + ]; + }), + body: tabBarView() + ) + ); + } } } \ No newline at end of file diff --git a/lib/screens/clients/clients_desktop_view.dart b/lib/screens/clients/clients_desktop_view.dart new file mode 100644 index 0000000..8f0f772 --- /dev/null +++ b/lib/screens/clients/clients_desktop_view.dart @@ -0,0 +1,161 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/clients/logs_list_client.dart'; +import 'package:adguard_home_manager/screens/clients/added_list.dart'; +import 'package:adguard_home_manager/screens/clients/clients_list.dart'; + +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/screens/clients/search_clients.dart'; + + +class ClientsDesktopView extends StatefulWidget { + final ServersProvider serversProvider; + final AppConfigProvider appConfigProvider; + final Future Function() fetchClients; + + const ClientsDesktopView({ + Key? key, + required this.serversProvider, + required this.appConfigProvider, + required this.fetchClients + }) : super(key: key); + + @override + State createState() => _ClientsDesktopViewState(); +} + +class _ClientsDesktopViewState extends State with TickerProviderStateMixin { + late TabController tabController; + final ScrollController scrollController = ScrollController(); + + AutoClient? selectedActiveClient; + Client? selectedAddedClient; + + @override + void initState() { + super.initState(); + tabController = TabController( + initialIndex: 0, + length: 2, + vsync: this, + ); + tabController.addListener(() => widget.appConfigProvider.setSelectedClientsTab(tabController.index)); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + PreferredSizeWidget tabBar() { + return TabBar( + controller: tabController, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.devices), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.activeClients) + ], + ), + ), + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.add_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.added) + ], + ), + ), + ] + ); + } + + Widget tabBarView() { + return TabBarView( + controller: tabController, + children: [ + ClientsList( + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == LoadStatus.loaded + ? serversProvider.clients.data!.autoClientsData : [], + fetchClients: widget.fetchClients, + onClientSelected: (client) => setState(() { + selectedAddedClient = null; + selectedActiveClient = client; + SplitView.of(context).setSecondary( + LogsListClient( + ip: client.ip, + name: client.name, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + ) + ); + }), + selectedClient: selectedActiveClient, + splitView: true + ), + AddedList( + scrollController: scrollController, + loadStatus: serversProvider.clients.loadStatus, + data: serversProvider.clients.loadStatus == LoadStatus.loaded + ? serversProvider.clients.data!.clients : [], + fetchClients: widget.fetchClients, + onClientSelected: (client) => setState(() { + selectedActiveClient = null; + selectedAddedClient = client; + SplitView.of(context).setSecondary( + LogsListClient( + ip: client.ids[0], + name: client.name, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + ) + ); + }), + selectedClient: selectedAddedClient, + splitView: true, + ), + ] + ); + } + + return DefaultTabController( + length: 2, + child: Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.clients), + centerTitle: false, + actions: [ + if (serversProvider.clients.loadStatus == LoadStatus.loaded) ...[ + IconButton( + onPressed: () => { + Navigator.push(context, MaterialPageRoute( + builder: (context) => const SearchClients() + )) + }, + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.searchClients, + ), + const SizedBox(width: 10), + ] + ], + bottom: tabBar() + ), + body: tabBarView(), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index af1ee86..3ca250b 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -1,36 +1,42 @@ +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/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/screens/clients/active_client_tile.dart'; + import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/logs_provider.dart'; class ClientsList extends StatelessWidget { final ScrollController scrollController; final LoadStatus loadStatus; final List data; final Future Function() fetchClients; + final void Function(AutoClient) onClientSelected; + final AutoClient? selectedClient; + final bool splitView; const ClientsList({ Key? key, required this.scrollController, required this.loadStatus, required this.data, - required this.fetchClients + required this.fetchClients, + required this.onClientSelected, + this.selectedClient, + required this.splitView }) : super(key: key); @override Widget build(BuildContext context) { - final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); - return CustomTabContentList( + listPadding: splitView == true + ? const EdgeInsets.only(top: 8) + : null, + noSliver: !(Platform.isAndroid || Platform.isIOS), loadingGenerator: () => SizedBox( width: double.maxFinite, height: MediaQuery.of(context).size.height-171, @@ -52,32 +58,12 @@ class ClientsList extends StatelessWidget { ), ), itemsCount: data.length, - contentWidget: (index) => CustomListTile( - title: data[index].name != '' - ? data[index].name! - : data[index].ip, - subtitle: data[index].name != '' - ? data[index].ip - : null, - trailing: Text( - data[index].source, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ), - onTap: () { - logsProvider.setSearchText(null); - logsProvider.setSelectedClients([data[index].ip]); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: null, - clients: [data[index].ip] - ) - ); - appConfigProvider.setSelectedScreen(2); - }, - ), + contentWidget: (index) => ActiveClientTile( + client: data[index], + onTap: onClientSelected, + splitView: splitView, + selectedClient: selectedClient, + ), noData: SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 4eff04e..83cf864 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -23,6 +25,8 @@ class ClientsFab extends StatelessWidget { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void confirmAddClient(Client client) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingClient); @@ -65,13 +69,27 @@ class ClientsFab extends StatelessWidget { } void openAddClient() { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => ClientScreen( - onConfirm: confirmAddClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, - ) - )); + if (width > 900 || !(Platform.isAndroid | Platform.isIOS)) { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => ClientScreen( + onConfirm: confirmAddClient, + serverVersion: serversProvider.serverStatus.data!.serverVersion, + dialog: true, + ) + ); + } + else { + Navigator.push(context, MaterialPageRoute( + fullscreenDialog: true, + builder: (BuildContext context) => ClientScreen( + onConfirm: confirmAddClient, + serverVersion: serversProvider.serverStatus.data!.serverVersion, + dialog: false, + ) + )); + } } return FloatingActionButton( diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/logs_list_client.dart new file mode 100644 index 0000000..ef910fd --- /dev/null +++ b/lib/screens/clients/logs_list_client.dart @@ -0,0 +1,223 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/logs/log_tile.dart'; + +import 'package:adguard_home_manager/models/logs.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; + +class LogsListClient extends StatefulWidget { + final String ip; + final String? name; + final ServersProvider serversProvider; + final AppConfigProvider appConfigProvider; + + const LogsListClient({ + Key? key, + required this.ip, + this.name, + required this.serversProvider, + required this.appConfigProvider + }) : super(key: key); + + @override + State createState() => _LogsListClientState(); +} + +class _LogsListClientState extends State { + late ScrollController scrollController; + + bool isLoadingMore = false; + + int logsQuantity = 100; + int offset = 0; + + int loadStatus = 0; + LogsData? logsData; + + String previousIp = ""; + + bool showDivider = true; + + Future fetchLogs({ + int? inOffset, + bool? loadingMore, + String? responseStatus, + String? searchText, + }) async { + int offst = inOffset ?? offset; + + if (loadingMore != null && loadingMore == true) { + setState(() => isLoadingMore = true); + } + + final result = await getLogs( + server: widget.serversProvider.selectedServer!, + count: logsQuantity, + offset: offst, + search: '"${widget.ip}"' + ); + + if (loadingMore != null && loadingMore == true) { + setState(() => isLoadingMore = false); + } + + if (mounted) { + if (result['result'] == 'success') { + setState(() => offset = inOffset != null ? inOffset+logsQuantity : offset+logsQuantity); + if (loadingMore != null && loadingMore == true && logsData != null) { + LogsData newLogsData = result['data']; + newLogsData.data = [...logsData!.data, ...result['data'].data]; + setState(() => logsData = newLogsData); + } + else { + LogsData newLogsData = result['data']; + setState(() => logsData = newLogsData); + } + setState(() => loadStatus = 1); + } + else { + setState(() => loadStatus = 2); + widget.appConfigProvider.addLog(result['log']); + } + } + } + + + void scrollListener() { + if (scrollController.position.extentAfter < 500 && isLoadingMore == false) { + fetchLogs(loadingMore: true); + } + if (scrollController.position.pixels > 0) { + setState(() => showDivider = false); + } + else { + setState(() => showDivider = true); + } + } + + @override + void initState() { + scrollController = ScrollController()..addListener(scrollListener); + fetchLogs(inOffset: 0); + setState(() => previousIp = widget.ip); + super.initState(); + } + + @override + Widget build(BuildContext context) { + if (widget.ip != previousIp) { + setState(() => loadStatus = 0); + if (scrollController.hasClients) scrollController.animateTo(0, duration: const Duration(milliseconds: 1), curve: Curves.ease); + fetchLogs(inOffset: 0); + setState(() => previousIp = widget.ip); + } + + Widget status() { + switch (loadStatus) { + case 0: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingLogs, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case 1: + return RefreshIndicator( + onRefresh: fetchLogs, + child: ListView.builder( + controller: scrollController, + padding: const EdgeInsets.only(top: 0), + itemCount: isLoadingMore == true + ? logsData!.data.length+1 + : logsData!.data.length, + itemBuilder: (context, index) { + if (isLoadingMore == true && index == logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else { + return LogTile( + log: logsData!.data[index], + index: index, + length: logsData!.data.length, + onLogTap: (log) { + + } + ); + } + } + ), + ); + + case 2: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.logsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + } + + return Scaffold( + appBar: AppBar( + title: Text(widget.name != null && widget.name != '' ? widget.name! : widget.ip), + centerTitle: true, + actions: [ + if (!(Platform.isAndroid || Platform.isIOS)) ...[ + IconButton( + onPressed: fetchLogs, + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ), + const SizedBox(width: 8) + ] + ], + ), + body: status(), + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/safe_search_modal.dart b/lib/screens/clients/safe_search_modal.dart index 9d51f01..1be694c 100644 --- a/lib/screens/clients/safe_search_modal.dart +++ b/lib/screens/clients/safe_search_modal.dart @@ -64,109 +64,114 @@ class _SafeSearchModalState extends State { ) ], ), - content: Wrap( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Material( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: widget.disabled == true - ? null - : () => setState(() => generalEnabled = !generalEnabled), + content: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: Wrap( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Material( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 5 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.enable, - style: TextStyle( - fontSize: 16, - color: widget.disabled == true - ? Colors.grey - : Theme.of(context).colorScheme.onSurface + child: InkWell( + onTap: widget.disabled == true + ? null + : () => setState(() => generalEnabled = !generalEnabled), + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 5 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.enable, + style: TextStyle( + fontSize: 16, + color: widget.disabled == true + ? Colors.grey + : Theme.of(context).colorScheme.onSurface + ), ), - ), - Switch( - value: generalEnabled, - onChanged: widget.disabled == true - ? null - : (value) => setState(() => generalEnabled = value), - ) - ], + Switch( + value: generalEnabled, + onChanged: widget.disabled == true + ? null + : (value) => setState(() => generalEnabled = value), + ) + ], + ), ), ), ), ), - ), - const SizedBox(height: 4, width: double.maxFinite), - CustomCheckboxListTile( - value: bingEnabled, - onChanged: (value) => setState(() => bingEnabled = value), - title: "Bing", - disabled: widget.disabled || !generalEnabled, - padding: const EdgeInsets.symmetric( - horizontal: 36, - vertical: 4 + const SizedBox(height: 4, width: double.maxFinite), + CustomCheckboxListTile( + value: bingEnabled, + onChanged: (value) => setState(() => bingEnabled = value), + title: "Bing", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), ), - ), - CustomCheckboxListTile( - value: duckduckgoEnabled, - onChanged: (value) => setState(() => duckduckgoEnabled = value), - title: "DuckDuckGo", - disabled: widget.disabled || !generalEnabled, - padding: const EdgeInsets.symmetric( - horizontal: 36, - vertical: 4 + CustomCheckboxListTile( + value: duckduckgoEnabled, + onChanged: (value) => setState(() => duckduckgoEnabled = value), + title: "DuckDuckGo", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), ), - ), - CustomCheckboxListTile( - value: googleEnabled, - onChanged: (value) => setState(() => googleEnabled = value), - title: "Google", - disabled: widget.disabled || !generalEnabled, - padding: const EdgeInsets.symmetric( - horizontal: 36, - vertical: 4 + CustomCheckboxListTile( + value: googleEnabled, + onChanged: (value) => setState(() => googleEnabled = value), + title: "Google", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), ), - ), - CustomCheckboxListTile( - value: pixabayEnabled, - onChanged: (value) => setState(() => pixabayEnabled = value), - title: "Pixabay", - disabled: widget.disabled || !generalEnabled, - padding: const EdgeInsets.symmetric( - horizontal: 36, - vertical: 4 + CustomCheckboxListTile( + value: pixabayEnabled, + onChanged: (value) => setState(() => pixabayEnabled = value), + title: "Pixabay", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), ), - ), - CustomCheckboxListTile( - value: yandexEnabled, - onChanged: (value) => setState(() => yandexEnabled = value), - title: "Yandex", - disabled: widget.disabled || !generalEnabled, - padding: const EdgeInsets.symmetric( - horizontal: 36, - vertical: 4 + CustomCheckboxListTile( + value: yandexEnabled, + onChanged: (value) => setState(() => yandexEnabled = value), + title: "Yandex", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), ), - ), - CustomCheckboxListTile( - value: youtubeEnabled, - onChanged: (value) => setState(() => youtubeEnabled = value), - title: "YouTube", - disabled: widget.disabled || !generalEnabled, - padding: const EdgeInsets.symmetric( - horizontal: 36, - vertical: 4 + CustomCheckboxListTile( + value: youtubeEnabled, + onChanged: (value) => setState(() => youtubeEnabled = value), + title: "YouTube", + disabled: widget.disabled || !generalEnabled, + padding: const EdgeInsets.symmetric( + horizontal: 36, + vertical: 4 + ), ), - ), - ], + ], + ), ), actions: [ TextButton( diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index ce5d2bf..e22e238 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; @@ -99,6 +101,8 @@ class _SearchClientsWidgetState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void deleteClient(Client client) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); @@ -183,15 +187,31 @@ class _SearchClientsWidgetState extends State { } void openClientModal(Client client) { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => ClientScreen( - onConfirm: confirmEditClient, - onDelete: deleteClient, - client: client, - serverVersion: serversProvider.serverStatus.data!.serverVersion, - ) - )); + if (width > 900 || !(Platform.isAndroid | Platform.isIOS)) { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => ClientScreen( + onConfirm: confirmEditClient, + serverVersion: serversProvider.serverStatus.data!.serverVersion, + onDelete: deleteClient, + client: client, + dialog: true, + ) + ); + } + else { + Navigator.push(context, MaterialPageRoute( + fullscreenDialog: true, + builder: (BuildContext context) => ClientScreen( + onConfirm: confirmEditClient, + serverVersion: serversProvider.serverStatus.data!.serverVersion, + onDelete: deleteClient, + client: client, + dialog: false, + ) + )); + } } void openDeleteModal(Client client) { diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 5e10280..776bd0c 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -42,7 +42,7 @@ class LogTile extends StatelessWidget { required String text }) { return SizedBox( - width: 70, + width: 80, child: Column( children: [ Icon( diff --git a/lib/widgets/custom_list_tile.dart b/lib/widgets/custom_list_tile.dart index 34a7c80..bfd379d 100644 --- a/lib/widgets/custom_list_tile.dart +++ b/lib/widgets/custom_list_tile.dart @@ -10,6 +10,7 @@ class CustomListTile extends StatelessWidget { final EdgeInsets? padding; final void Function()? onLongPress; final bool? disabled; + final void Function(bool)? onHover; const CustomListTile({ Key? key, @@ -21,7 +22,8 @@ class CustomListTile extends StatelessWidget { this.trailing, this.padding, this.onLongPress, - this.disabled + this.disabled, + this.onHover }) : super(key: key); @override @@ -30,6 +32,7 @@ class CustomListTile extends StatelessWidget { color: Colors.transparent, child: InkWell( onTap: onTap, + onHover: onHover, onLongPress: onLongPress, child: Padding( padding: padding ?? const EdgeInsets.symmetric(horizontal: 16, vertical: 12), diff --git a/lib/widgets/tab_content_list.dart b/lib/widgets/tab_content_list.dart index 9603c95..d1f2ad0 100644 --- a/lib/widgets/tab_content_list.dart +++ b/lib/widgets/tab_content_list.dart @@ -16,6 +16,7 @@ class CustomTabContentList extends StatelessWidget { final Widget? fab; final bool? fabVisible; final bool? noSliver; + final EdgeInsets? listPadding; const CustomTabContentList({ Key? key, @@ -29,7 +30,8 @@ class CustomTabContentList extends StatelessWidget { this.refreshIndicatorOffset, this.fab, this.fabVisible, - this.noSliver + this.noSliver, + this.listPadding }) : super(key: key); @override @@ -73,6 +75,7 @@ class CustomTabContentList extends StatelessWidget { return Stack( children: [ ListView.builder( + padding: listPadding, itemCount: itemsCount, itemBuilder: (context, index) => contentWidget(index), ), @@ -117,7 +120,7 @@ class CustomTabContentList extends StatelessWidget { builder: (BuildContext context) { return RefreshIndicator( onRefresh: onRefresh, - edgeOffset: refreshIndicatorOffset ?? 95, + edgeOffset: refreshIndicatorOffset ?? 70, child: CustomScrollView( slivers: [ SliverOverlapInjector( From 5cd789bf3a1decaf4fb3300703766fa96898631f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 22:31:36 +0200 Subject: [PATCH 060/676] Changed clients search --- lib/providers/servers_provider.dart | 52 ++++++++++++++++ lib/screens/clients/clients.dart | 60 +++++++++++++++--- lib/screens/clients/clients_desktop_view.dart | 61 ++++++++++++++++--- 3 files changed, 154 insertions(+), 19 deletions(-) diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index fd0bd58..e59d8ae 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -34,6 +34,9 @@ class ServersProvider with ChangeNotifier { loadStatus: LoadStatus.loading, data: null ); + String? _searchTermClients; + List _filteredActiveClients = []; + List _filteredAddedClients = []; final Filtering _filtering = Filtering( loadStatus: LoadStatus.loading, @@ -87,6 +90,18 @@ class ServersProvider with ChangeNotifier { return _clients; } + String? get searchTermClients { + return _searchTermClients; + } + + List get filteredActiveClients { + return _filteredActiveClients; + } + + List get filteredAddedClients { + return _filteredAddedClients; + } + FilteringStatus? get filteringStatus { return _filteringStatus; } @@ -148,6 +163,43 @@ class ServersProvider with ChangeNotifier { void setClientsData(ClientsData data) { _clients.data = data; + if (_searchTermClients != null && _searchTermClients != '') { + _filteredActiveClients = _clients.data!.autoClientsData.where( + (client) => client.ip.contains(_searchTermClients!.toLowerCase()) || (client.name != null ? client.name!.contains(_searchTermClients!.toLowerCase()) : false) + ).toList(); + _filteredAddedClients = _clients.data!.clients.where( + (client) { + isContained(String value) => value.contains(value.toLowerCase()); + return client.ids.any(isContained); + } + ).toList(); + } + else { + _filteredActiveClients = data.autoClientsData; + _filteredAddedClients = data.clients; + } + notifyListeners(); + } + + void setSearchTermClients(String? value) { + _searchTermClients = value; + if (value != null && value != '') { + if (_clients.data != null) { + _filteredActiveClients = _clients.data!.autoClientsData.where( + (client) => client.ip.contains(value.toLowerCase()) || (client.name != null ? client.name!.contains(value.toLowerCase()) : false) + ).toList(); + _filteredAddedClients = _clients.data!.clients.where( + (client) { + isContained(String value) => value.contains(value.toLowerCase()); + return client.ids.any(isContained); + } + ).toList(); + } + } + else { + if (_clients.data != null) _filteredActiveClients = _clients.data!.autoClientsData; + if (_clients.data != null) _filteredAddedClients = _clients.data!.clients; + } notifyListeners(); } diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 3b52760..91d7dd1 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -61,6 +61,9 @@ class _ClientsWidgetState extends State with TickerProviderStateM late TabController tabController; final ScrollController scrollController = ScrollController(); + bool searchMode = false; + final TextEditingController searchController = TextEditingController(); + Future fetchClients() async { widget.setLoadingStatus(LoadStatus.loading, false); final result = await getClients(widget.server); @@ -136,7 +139,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM scrollController: scrollController, loadStatus: serversProvider.clients.loadStatus, data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.autoClientsData : [], + ? serversProvider.filteredActiveClients : [], fetchClients: fetchClients, onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( builder: (context) => LogsListClient( @@ -151,7 +154,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM scrollController: scrollController, loadStatus: serversProvider.clients.loadStatus, data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clients : [], + ? serversProvider.filteredAddedClients : [], fetchClients: fetchClients, onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( builder: (context) => LogsListClient( @@ -216,19 +219,58 @@ class _ClientsWidgetState extends State with TickerProviderStateM SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), sliver: SliverAppBar( - title: Text(AppLocalizations.of(context)!.clients), + title: searchMode == true + ? Row( + children: [ + IconButton( + onPressed: () { + setState(() { + searchMode = false; + searchController.text = ""; + serversProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.arrow_back_rounded) + ), + const SizedBox(width: 16), + Expanded( + child: TextField( + controller: searchController, + onChanged: (value) => serversProvider.setSearchTermClients(value), + decoration: InputDecoration( + suffixIcon: IconButton( + onPressed: () { + setState(() { + searchController.text = ""; + serversProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.clear_rounded) + ), + hintText: AppLocalizations.of(context)!.search, + hintStyle: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + border: InputBorder.none, + ), + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + ), + ) + ], + ) + : Text(AppLocalizations.of(context)!.clients), pinned: true, floating: true, centerTitle: false, forceElevated: innerBoxIsScrolled, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded) ...[ + if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ IconButton( - onPressed: () => { - Navigator.push(context, MaterialPageRoute( - builder: (context) => const SearchClients() - )) - }, + onPressed: () => setState(() => searchMode = true), icon: const Icon(Icons.search), tooltip: AppLocalizations.of(context)!.searchClients, ), diff --git a/lib/screens/clients/clients_desktop_view.dart b/lib/screens/clients/clients_desktop_view.dart index 8f0f772..19e6254 100644 --- a/lib/screens/clients/clients_desktop_view.dart +++ b/lib/screens/clients/clients_desktop_view.dart @@ -11,7 +11,6 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/screens/clients/search_clients.dart'; class ClientsDesktopView extends StatefulWidget { @@ -36,6 +35,9 @@ class _ClientsDesktopViewState extends State with TickerPro AutoClient? selectedActiveClient; Client? selectedAddedClient; + + bool searchMode = false; + final TextEditingController searchController = TextEditingController(); @override void initState() { @@ -90,7 +92,7 @@ class _ClientsDesktopViewState extends State with TickerPro scrollController: scrollController, loadStatus: serversProvider.clients.loadStatus, data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.autoClientsData : [], + ? serversProvider.filteredActiveClients : [], fetchClients: widget.fetchClients, onClientSelected: (client) => setState(() { selectedAddedClient = null; @@ -111,7 +113,7 @@ class _ClientsDesktopViewState extends State with TickerPro scrollController: scrollController, loadStatus: serversProvider.clients.loadStatus, data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clients : [], + ? serversProvider.filteredAddedClients : [], fetchClients: widget.fetchClients, onClientSelected: (client) => setState(() { selectedActiveClient = null; @@ -136,16 +138,55 @@ class _ClientsDesktopViewState extends State with TickerPro length: 2, child: Scaffold( appBar: AppBar( - title: Text(AppLocalizations.of(context)!.clients), + title: searchMode == true + ? Row( + children: [ + IconButton( + onPressed: () { + setState(() { + searchMode = false; + searchController.text = ""; + serversProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.arrow_back_rounded) + ), + const SizedBox(width: 16), + Expanded( + child: TextField( + controller: searchController, + onChanged: (value) => serversProvider.setSearchTermClients(value), + decoration: InputDecoration( + suffixIcon: IconButton( + onPressed: () { + setState(() { + searchController.text = ""; + serversProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.clear_rounded) + ), + hintText: AppLocalizations.of(context)!.search, + hintStyle: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + border: InputBorder.none, + ), + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + ), + ) + ], + ) + : Text(AppLocalizations.of(context)!.clients), centerTitle: false, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded) ...[ + if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ IconButton( - onPressed: () => { - Navigator.push(context, MaterialPageRoute( - builder: (context) => const SearchClients() - )) - }, + onPressed: () => setState(() => searchMode = true), icon: const Icon(Icons.search), tooltip: AppLocalizations.of(context)!.searchClients, ), From 954a8ad49634679bedf54a4ee7e960c285095beb Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 1 May 2023 22:41:18 +0200 Subject: [PATCH 061/676] Changed macos icon and name --- assets/icon/icon-macos.png | Bin 422255 -> 434970 bytes macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ .../xcshareddata/xcschemes/Runner.xcscheme | 8 ++++---- .../AppIcon.appiconset/app_icon_1024.png | Bin 414551 -> 431799 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 4705 -> 5762 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 515 -> 532 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 14960 -> 18240 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 938 -> 1005 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 76128 -> 84277 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 1956 -> 2246 bytes macos/Runner/Info.plist | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/assets/icon/icon-macos.png b/assets/icon/icon-macos.png index 54f7bda4a1028f0f34720f74cf0e2abceb0f4a25..5bd77ccaad26e33093b6af60bfb9e958763327c8 100755 GIT binary patch delta 352532 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�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�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

$ToPse6XEJHCHWdss;xLZQH>dif5J$5bU7 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�g27$#nv#ECP51tgVu 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ΞKms#|G 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ª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 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index a91bd3f..0edb998 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -57,7 +57,7 @@ 2B20822A5E5ADA2133261EFB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* My Server Status.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "My Server Status.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* AdGuard Home Manager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AdGuard Home Manager.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -112,7 +112,7 @@ 33CC10EE2044A3C60003C045 /* Products */ = { isa = PBXGroup; children = ( - 33CC10ED2044A3C60003C045 /* My Server Status.app */, + 33CC10ED2044A3C60003C045 /* AdGuard Home Manager.app */, ); name = Products; sourceTree = ""; @@ -192,7 +192,7 @@ ); name = Runner; productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* My Server Status.app */; + productReference = 33CC10ED2044A3C60003C045 /* AdGuard Home Manager.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -431,7 +431,7 @@ ); MARKETING_VERSION = 1.14.1; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; - PRODUCT_NAME = "My Server Status"; + PRODUCT_NAME = "AdGuard Home Manager"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; @@ -563,7 +563,7 @@ ); MARKETING_VERSION = 1.14.1; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; - PRODUCT_NAME = "My Server Status"; + PRODUCT_NAME = "AdGuard Home Manager"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -589,7 +589,7 @@ ); MARKETING_VERSION = 1.14.1; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; - PRODUCT_NAME = "My Server Status"; + PRODUCT_NAME = "AdGuard Home Manager"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 85b0db9..0a0b302 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -15,7 +15,7 @@ @@ -31,7 +31,7 @@ @@ -54,7 +54,7 @@ @@ -71,7 +71,7 @@ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png index 23f69c7f2b91ba82eb71646e0a40c145c1767b4e..8820378c5af7bec1e255271b96221343371a51be 100644 GIT binary patch delta 345215 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 n^lSc}SaRnkJ| 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 z zlt0ebo%&nUET6lJ1CAC@c&YeS+zKMUvv>@GcFi^(TdyZrC3sXE+f%T9|Gu0ULOYbM za#~rAtpelpy6_jp$d1aECoIRdMiv!9=V1xdPI~5;{6TXdJ{JhWl)t3l3$9I*L*T%_ zKm1iv#()m@Su|(6O&6KKs3qydxbbrM;KGG0%yjBAa|qZ{mo<*P)#?PMPDn+^R?0S7 z+4YC|d!VA1Un*$p__?a=~!#v*6_O5#M2qa}WG9#Z$u}rwtuoky8P&U9!B!-Z4ga zVE*-O;(FN?!ywgJKX>Iv?@M1->?8%f16q;;i=81BiOV-s;~!y?giV~WXm1vku`|Dh zHt<5L-G4kA^Keb}EXS$)2(_pLN>MmB*3?qP-t=@4Yjq`h7|QAl6?as!#lG(ez);Jj z8y82NY{q$H5>8SB(Umz~yr{35kIf8adll14QmtA48;tUL5U!#io|fmnJXM94NjzbS zxlqr!WB0FyaiIESFw`P^FQx;zn%F5ny*CTwf!cdZW3TTAms=y0!P!x{Xbp(?x{lBq6$@k&?_#P49pR1x48iA8fnp_(f#(+oxn} zwiS6RxAWR%)q7p7+RlO_3VpgJ2c<-MG(}eDA9w~10lJ619Vxi#s>Y+{6Zfkt)kpwlxPG>U26i1Gzow&`~ z*wOFTH938W4YTVC_+6R~^lfJGVdOuhV_|B&PWCW+x_9SAAEb)yzwdl~Kh{v+6R+oE zryliYxjXJ*cN;!#QX!T&q+3V zBbX+)g*VSY-SRJ+MRJ1eT1)r=zSPS(0f)Q41q6aPk3p@OWYVllz#X~|bJ^U#L2T6!LaTDi<*1w8M6^pI!F4C8$hahO~2^S0MRCKR! zsHU)MnOP?DsvL|5$Pfo>Cb}(GH*J8=MxWY2jjO-)c$l;yVZ#L;Mp;umwo(>? zQ_EK6!bk17g(oqpUDMe*&lLnxCO@Xu@RE&^az1+45pI^}oAc<~d$cwTZK`S!^8uSe zj}6VMS~Q2PJS-?`Uxv=~!=m0AMLE7{jHSE$-vCv<}&-uWl zM;Bicmzhc@w_FgIY0|hMB*xAq9x+^q6?`}V8( z-@4Vmw{D-SDsK7Z`$84^mWOrH3p2colD|)Y)#pwqD5<1EYFU*jjh{{;e0PSv2tGy{ zGMm#iPF0Wv5sw{Ru8s;b1YPIW_KgA`X7Ag==z1SC@3Za&#|>TYW7qOkZ{P@aMPeBr zi?t*+ZWWN-9&lPL6A>@Hu=^T%lbgJ+Omtx(u*&>(AKs?_iM1m*`Gds@28WJrvx@-RFv)nNtQG>D zer0-y{ZXm+B|l--5G@aN$AI4h4J7YNW!NKj>QPl1+MShi!E)jntIEGu#|AK$9Xy3!8)|Ur{q=R9ks3 zgneohT}*lLEZXoQc>5sSCfLL$kRZLLU*Qn{Ope%9l;CoX*Vt?rhUNCzY)F%@)!`sJ z{Ym~R)$vTEM0f@TaHRJ!w?M-=wRVek(hR9XN?X^7u&kq(+n|i`NTUbe2CpAKiF)CG ze4GQf>1Hy|Vlp2GL=Qv%T|v6vlKfno1jB!-d}^o4o*V>R@oU#1ekgG1*4YV+a3Gx$ zf+p}_1V8LD>Q0|ui5VK@<0%VsL&aKcoGzqsvRFG`z4QUN(d#|0QlCgaByJwq`rfmV zF8&W-jya@G?@h!gREuMJjznh5F;j4j55qL3@o@ipN zoXD5DR>jif02+-n_-aLv?URyvB)+Y%1TI=6s5SAH$TDO4+(d~k$wx=m9WyIESr5L= z+D2-W!5oj_;q50CD*Xu(;1q8GSZ9*dcS07I0cOeLD{7Y}w5J_emck;Y+E+y%jjA7C zD*4idXv%2FbOt*7N(8sm&=Hz*A4z%!NpB}iSc@S zNM|BYMJ|UOIVN7bcanrMzxvzi ze1oFTwUjXZF0lUavAp>)?y$*!u^8z9>{2=Wli)24K;Pu12+OF`?7W&fd?m&VMXPT4 zWybWQe(IJk;@{AnFBhMUx9*wO;a$9?iry`SwKaJ4>eqyJ6c` z?{e!1eh!%X{LPXYycoZB=6qMHH@%5}SImxfiM}iDkx|LgVcP5-lpoPPA4r$@0$+Q_ z9+)cQYcoexTzA1E~mQL(HM9D=ZsOpZEna6EBQY{jc4N-{^gu&6jRh${<>Gg|rZ#}A7wuAK>K{o-|@vNq@BgC{iYq@(D&u;8WlJ{+{t|(tkN*<)$q8``O{FG+O+_l*I?7annfx1 zzz)R&@0Kb@?yaC$SCzSI?4^LNy|z192bLnx2L-&`)x$IAR5$^pw2(BC0{vRXHp@4q z%9sbV1JVlt0+9yekaL~evX*;agmIx6iNbLv6jJNnw(ceNz#l(uTbQj3ZYaiHD<^qn zCI@(rmwSkoz(hu*TRbNRa3viLesS|!HF-Gx^b)LvA(e;yR&eqFH=V;M0+J-`TUna= zu7^sZ7;U3K7f202Rl%@h`jOL!;Qd99D`esod})-Qw>6pbh#p9ohPh(jKPrb!TNc&c zdagtoLiF-K!4Pg08h1=UgjnUjWm!%ALcduTV)}EJwAA*+_HDbGGPIvRF=64+^S2Gw z|97Zn#@q74JYy;c#X{KI)Rtt)#vy;R_C)ZLJtD6HV9dBglc74`W?j4Mhf03m+96+B zZY&x8epW^>OAW}Pvz0GITk1O2%>^mkO!9xF&lvI41IXrG`yf|ko2Jz@6~L=6Y^avW zF`~h`4zxAklARRsY-rw!7}2$KMB{2!a$S`5v97X9?kF zJI@d5pGIxk*B-F91`ga-zQ9A}cVv{MSxo{n9oNUeQS1;yWz@Ra`qLb2@^S+M`5X9y zklV{8i}%#fpk2pq#kGy_$L{sX;+u23n`Qt2GMxnob8T7W3kbD6xQ3=`w+PC(9R{X@Ekt{*mUn! zNK8qprF``zcg*0mQSjf4qMjlSU_`*B!0zBjMgDS-|3pwu`jVesi!7+r&ueD!z!DFz zTE`e|QkrPxokmwI3O(|&xc7e*m_e3Rv6eS-B9eFv?|=jS$mYPsZw3n`?o!0M!Wcpd z&6`3Gg*HMJDh+Qh3JD?vSLuz0{jksm%SaD3rY?+v)Xn4zeuAOVZj9uSA1W|%R)8^F zi_46%)GnY~94z{g_kMAtQ=BtRxXK6gXHt5Uxp&zli&E3l| zYf+XR^(c;y4!P_ooPd=jO%$M5Xih)11Oj+a_q9A`mqW$_pmdGm)Us>goLs&B|FgP` z{5~7uZVoYFaEP9a)`a3%luWb_yDY!2A971Lr~z+Sci3kCd(vbP>%Ef!D1zX*RcRu2 zb|RQON13_-^Z>HMTC2Pnggb$KDL&#vN7!D`{me< z^9WTNk~SLa)nNsYgmezt{rRG;;RMUfZJ~1MQ+1xo@}Tm(!?Ysg#Q`0Ln!No}bnq79 zWnqzx*7IHEk5>IYzbn`;!1{UWu#=X@RfMatDjS`NRIb20O20=aB|QB~L_iv0Tu;i1re(wY4}L9rX+i0-q{xW1v1Nm&WSWx)02gU=*jzwh>l)=n zMwFpae{nL=dyAoiU^ryd12%n2jIH`qSKoJWyrsQg@;TlCkd0l;J6^n{}1xg^s_4lqY!kd8>#QnQ+dUJU;% zY_~B|*&W1$p=KQ5mTh(U5w`DMK#;7(x1Bj?7(<|UeK<9&>Poks;{S8PUZwGj&J2&Y zu{q-tB-`LoKRRUgaCku~9}hazf+Aj;AdxLvR@3I=vajrZd=kY?mq+KaU#puwGAom$ zevaXlXm5a%XK%&=hgZnVf^9Az!8O>gk-ulWsx&Y{VKQeB%d!%uAojayG9bdZX3Clqg-;AUuRYqJWZoMG?p`Qi6jO;Z=IbLYZWY%;t!SJHmzyqm4N!^xUX6Rd~hYIG`rX_Lm@JDR^ zs9c8Wcot|_;bNK11|u%Fu8+R|X7pH7rIJ$n=kn*`x#%6*y9K2KZr4_tb~(5($#oTGOB&>mgu)VG7}XY_$`)5*<2#kwbJ^vQJdJIVV;Df4yFA-627lIziOJ$~j-#l?o ziyy9;vM*BHWLnbVba70+u#N=5Qo4C}9>(zRjtTGVt4qEN4Kfv3p{iS(&9>@n(db^Q zUXKDdCy$+aPiEw0tAry@^-ppIm?1~C+lbG8tjo-K>qz^N86qmNM(zBjM*LeC@6Gz*+swc3AGZ~43?%~IOA)D$ZDrxVKk_F zKn{+x@}A$+J?#q-=44O&%rcEmZu(*iuG4#crqtNU{i355r7o$W|1TYBk#W(=xI0wn zfd}kr2E&CObx1i$*K%>>2lRX@&L3}|Oh6WDsQhZ`!l0eQoBx~#kLZ1mZqQ`Z(q~K$ zMRtuRnoUUUZk9L2WU-O zj`P<%5w2Y~a#dY&iVMVXJAPH8R~Uv2`WWZ$T&+XnqQ+)W37)m!m)^jjifMj$=|ZRU zh+e-PeXByHs*=JV%+Fz}6dVBnS*ts9xQXIGSJcfm=K!|fHz*M_9Xv{l%?p-KdreVU zurh>9eT5!Ks^uo-ke2|c2gU^=QCh@HDyl(MHZ)?|O-j7X%69C&?cX(=8I`o)4GtYF zhEXe2rxZGtp3gdp;W!(hEcZ8U;Cp}LY(_$lXT}Ek4Hf!9URu?~qazj|VDd|Hbr+v4 zqO3u5%n3z_7e>XK_iA!vI`8Ra#2l1c2X zN!E)vuepEdtqm|{e_sST1u|~$J{~UzKCTD#qR&*&wz+2jd>>JBP9*#@P3A!?ceW@j zdq)X0QdyB=CJ&0dJobcdpCKAVyyWsJqUyMe_}`6uY3Ew>CZC%Eb-XnHdTk3%#uRNn zB}q|Dev%wZR@E@^>sGG>(tD!1zPdhvN^JibmOE+d&0^{%Ue*9Kld`*l*H}Y`kB@QY|Y|Ecxi{hW~QIVP~q#aatd;k^j9A zgrb`wrjpmo=DuN|%l|^UH{j?}#)-CAzp;~q|6_2Egeu30HdVFkoE&_fhD95~fo8K1 zb(o%r5jwMD*0BzdLA1ChY5C`(u@sit7fGf~K$D!)XWTGr*ePTj>HZLc)!cq5FN<}q z`_Hy=*w{F^3=#es?h?KPR{rU^J)4_y#;8E?kL;|RS(+-<>AEnFg`7TRoIAUQo0-G9 ze}DvK^OlgvOzk~hoUB*IvE)eT8(r-RKT*LCi8n(_GdaKw+B;<^vfAe*(DtzHmxwsX z)2RjI-0sauLyrt=NL*MqYOOPJNs7IDJ$|LD&Z8Yx9|+wC9~bG!1M6ow5RG`->ZLMx zYg=4~e+jCoe*UAe7`qtKt62dpNr8)=CL#0p6M~T^d1^;pA_SWVYz(}Hp!wAXo>9OQ zMGAYsqXtA(=l)Hs=1M^{DxH{i*vwM?CTsp=UF$j&%uHc7RvR^p?|nHuyAz{r8_x1n zohrmUC_J-LS@o2r82PgKHu2b2<#k?6;^nv;oMl{OP0@R&i1L19#s|I@zEfbGd=264 z*Zu_~1Ldfno>R=RibjZ~CC1m~BR}^c;gO%k=N1_JP<)HbjkSAACqY5`B{{W9PYydN zQ$YB(d{a*?8vAt+(pkun(pC~NE1!)%V3&PgM-4}DYPL`r7aY7-V322$O|yn0yTgHK zm;Z+5qZR#0;*#{^W%#h;@y7`0)2x=NaH<8<8P5JoRjz}i1S($*>)GI>vgjpe@*jFj zop?aQbM)FH0DK7nrytj}ulepb6?UJr_?{d|4E#i}{<2m-IE#&C#xcM*f=_NvpO{A$ z!@vvPLauNT+7dkFq#d`tBRxvb8`*f3b}i^w4bZ3 zZooX*E%yoCBx7yrF+*oR|3br0H~62qurm-%u#JJ>Hyky#lP!UYH7(mg`&*n_-V9-&06Fu*9xy6s@i4q9%Kv^|z;aFLgBX=V)yit}tOVh)~^tF7H77UegI z2{BO`Z(w%0)JATf#$cVThce%inet^!&{vW++GKY7S);qx@8@qk{67G(Ku*7K0Q_5# zTGZ3@bKG%SX3p=dqnV$@f;m7Vv=0-EP-^K(sgZe#y6A`2{} zUmY8bY5?qY&R9Ot290TQnE>Wwaljz&S64h|@3o(da4^p4EA38GweEmMjSA1Q2LM^FB70df-bZuA-_p}NZ1`r4Jbu&y&8Z~tL-uwQ!$(1 z0m%#{gEIAZF@YRqNySw3Ff)HQ%S&R%cWMfXUJf$!Q9o89p%@Su-KKmMuDk5BmCuZv&1|2Ko+opXhFb0WQV9z2mX9S}mju^=y$Ldu}*`Cqso4P4pE zwZrMwzaR1J_m98#@-KgV)W-jNu3wMO{{C-{```8UpaHesXuzqlQeQ%!Bc!i3S)B5< z=hi2NPmF8Be#x?26(j~1CqWGC6a0_Rd_-8uMc&GI|GlCn%aPsrW!E!)`I^!xRc zD=X}qthYIKq>E3(sidtWbW)9*7U~aNYy2MIJJIqGQ1K+5(ocWSK-b^0s1vZwS>~29 zG9VjL9@Sz4_?$S%mQHFPIB3g!z>bFU<)IvNu3s>(0AtVe5fe-{FM1Md+P$rcrT&{?S zsP`r&5g+vj{813Z5iTk!hzJPsz?KSjJUEN*vR(EwT?r$!qT;+e#f+3|@(A)NfWddN^0=uW$ z;3lwIT)2sW4RXgse27uQb7bI(yR}+wl?E)74>BlZd{yaJ&a6}xyhRum@x+C#z8S3| z=F60Fa@q^Ag=i55W!XIrmA8tj?y8YiW_cmuZn&0s8>F#6i|$k4x%1U#^_70x%gaqB z0G2{u_-lX0?>rm7UPV{0>TzNG&j!ATt-8-jds^||(*UOV?yXuRE6euKvS3dxc-527 zbtEqVR^GKR5MHazQM?%dj$yp$!G-35P^j5T<9}h7<|S-p_?jCWC0~2P8_P#7`iy~$ zfv{nsWlYeC&{qCfc3Jg2aq-wYS(bL_E%2`V!T_-vIT){lIW z7Dq*7yIzxyz2yyWGLNw(Y=5X&g(q)+c$PF zeYltfI5;>LeaK)FeMMzO@{@Eqioj$c7EXWW@>kX9DK^PJkwG2_ke}inG%c0mO~X;T z4WU>XlE?(h=Fy0WVuN*r%Y^GIh9N|G1V7i=uU8(;V_ zW4uxt!@={aWuHvR#RX!Weu1=3pAF3@u?_uE%Wm@}%ikW}j z>)somnZ5407d-_Q{I-o@nE=?b0O8_$im0_{vQ@`V<$ig_hVk=}J4Z%Ocz@Pg98Q|!eI zCELtyb(edRSG*EQgc_fH)>)Muglm5x;i^J0e+I7zPsTV8kYhXGk61Nly0*!ndAomw zTmQ-qTx)c#j1JWrJMpWx#guN31KVO%QNeHSe>#gVL_g9?b*~TQL(8r@&;g{SrfEjM z5U;Hv+vPlY0mf`_-CM#|g?rrUc=^b?-{jwgo?30)`W(W%Vg%4s)JU>Tr7C};U{E0u zgDjReDg)S!GOh?wuPJbTe*ZJ)er#@(yW|3`Vk8_txc-tUL^ z6BozfRyzjZ8Q=RD`R^}zx?HyR^0s|qB6}~k0V!CYC;VE~t9lESwV!J5W7b(=lWy2{ zZb}DU6@DO~VBFHPJ0EkLy!3zj9yd=^T-or7_r67b|F8el^-TfTEOw^k+#s`orIj!- zQ_S@rtFBG7)HYEdMU5`VQKTNc z3VB!6vtm9&V~W3Xf6rrYf2Dc5gs)OC51rP=6@9T3bN9!FxfWjpXH|dT9-c3}<`5^c zR8iUq`y?}qW!n0$=~$l>v&AF~eiRLQG5L=dD=mmTUoc_NV!8K#ebTvz%U5TP%jK0D z!7Qt>;A3cl?Ne0E4Am0TnGp&DmqsfObsL*_-d+SR1EyIRH)&cM^M&eJx^y9@U>IvY zhO3>P3Z4X2hshDow_AUFA{9u*ckFqi28tXPY4u zTje!?RErslQaN9cz!gyn3a#d$eEb+1Y)lAltfoLft~16L#NdAhj7TCrvso-J+Yd%L z#z}!{$uU)IEA(g#E58OXj{4dxxK^jl*VHx(KRvX){taBTQ@H*6I;QwbAs$o*ywm-< zSe?C3_?|(Fx1#n2I7R*EGTf8ECw7?OnB_));nV$F1!o{M8xw0i)f{b7+u>N#o?|?p zcL;P^c?nwQi3dt>8P618U2)RFz`|5);513xnc1vdzb{)txe{zSA#I0k~j+Z z8Rc0%9ml;`t9nU)m#|G?nE=?z;D?F8hGPK)8x6RHS0{Y6pWg9mm;v9Gm&+M|a~JLg zP&5qykhzzUP%@>&LMKU(DAJ&?TtP9A=T&l-yQr8d9F61d!bvHb0`mI$Bt;@uygXa^ zA(?*N-f1 z9mdBcY<;-zao^Z3YPFUBf=NGV9wqiECjNh{q)s|9aAYvT{muF!d(#MwBjnGra9wE< zPxBEH4Uo5%3(f?bmH41vKTzhQ<;(+uuD{{NHU`{Kne%1x&Er^n{H6mNr;Xiwz7N(Y^{IFyMay#|#Z=IgY!iycH#{?4{}QV*Y~#0@eMt83&6q zrJ7vfE^ZjlctZ8G+laCZlhUe8z-cxCIZEwNHzUq2f6g0XqWVNi@Z3ZjI7ty|il?&( zfv~KjygXNO_(^gE_`5T@C16`$pp%rB)!ad9TGh8nfGQ%f7Lk^K$2xR8U`>CeX9>qH z;c5@d1i+RBtiG^7YQKb3MQjGtKK*8ctC|9E;9O}`>P7Vd3Blr@O&P$MBs5)+dw#*K z-lS?Zg<;=HRUt!q%gHN5J0=&n+(Lp*gGvL-i0mJCl+3d?AA-+uYq zveAVMv&%K`Fn~xTHP3^#de?u+@wzfFALsi)W)tjXMZ88^V`hKUwg4lQ_VC-xyjYrc z?JH#6Cy8pKu}v$eTQWXHu9c{ICcwCkK|Jf1$dDgyUtf$V=o1-fX+*uC#_ zub#<#VB7R|ZNO=wNNRu9j~PLgwu{)8CX&%%Qk44ybOX5xuz_H`lZ^qq=k9CrtNJ#Q zBCcDkzv0?>Jf8tD-KxBs_T!CWy?Fta)cGjA-y6cxD>@+%`X0I+LJ%Gdn%u_#)lCJjEhv9fj14aw!qK`5qOtm2z>FjWYAVMUhlUmdU~^peI$QuH6lkZfYARm-&%jeqdDfcecd-*c_uI6s~50cWe(_r z?H7F-UAdi0q2toN6hLQJXxiumhw(vY1??7!{Yhr3D6AmNXhxx8qJqgXN{krr8np!m zz!1k`9taZ!Oa+X^W~AfXD9s1?1r*8D)ex)W2YKJvxHi7%c&1As+G45x%V;MgrE)?D z5R!jzBgueKo}=`+E`6z)PkvW(RYE=^-5K*>8QD*g4C=jvtq98mz}5v48)1nY1|SJ% z2qj2n$XDLq1F>dE90FVX(2ro9y0LA0*pUri5Rkz>f8T~6mVXmu)$^k|nKJ?v!si2+ z5Hajj6^~XD;E^vPWMmLKY3G+Et>Vwky%&GiBE8tMrilhcR#5PYXcHtv4=Fwtth`-6 zPC!iem>sCj3rmApd{+Np)~cTkfI~kw|0kBago;1+( z)4^oA^k4P6V>*AJ#vtlc1DJ?(|{;p8e)?^^V)D9p>PMC&?Y2Ent6f z)Ls&ZU^s)oLJ9-PUzvPLd0J}7Aa=zR0yXQ{7j0_`T()Q9ZmsgI%BL^>oSb&{ugj|+ z_G@y(Ll57TS63!Xr|qA0($C2K|M*wrqZfTf=CL(>L%z7|!MP!Jw#Pi?s_}%yy1`nw z{?9*J#|oWN=d%v}){0^ooO zc95`nt>C}*AnnIhC$|Lsdwz^Qj}!Qjfly!cKI&4@W#iD~(tK*Tk9oD=;{kvDI;1lAVAP&eL$`>+kvwsQ)3SjH4_li8@yzGYms#5MX@ zftaUlRmxd+rN)){O`&g=K24{A85(jrqPxYb8#?3?uI{i*0Bl>Z)&6vF&`?N)QD)cO z45osM%I~VfnXo^J;$%hPAUS_Z9yi*n_)2v(PXW}6MVNhWmg{Dk1@~E|QTfIvN^9uc zjR5=9jSOaFi<4}tGTp3mE|XMkc?l}5Pt7uqT^ zyASGjrELY?W*b^L2C}6YG=5)+PVg8NP%5Yy0E->zfQcH3z6~6?pWzU&fl&m-7Xk3K7O4X+|$V@gD~0*J+LtC_TtX&0fT_lZ+omz3CTEM@h+ zh`!s-K4mz6*1TR4#$|sfQ^#YpG)qaC6vYLIZVW7og8F(!VVikT=(Cg>j%#WiFM=F zN21em#Z2K?R^@y15UM?WspJyw`uBb4&}q_{3A%Cl#Okn?hnKtXGb6oGoJ_gvm$9_0 zxqATSE%R?jT_?-hJeOAfO{e2lAi>0$ix5i z`}~PUwiXLOWvX`-2`e)O&ha`*q;Q3LB6a07Oi2=`%q}Xga)d#B{M+Ja5U!h5#vTN~ zXnXyIGxk6Zoq&3DhkIR{k8I(?|zj0;LDyh9i^#bzvv-&^j$xb1tYiz?;J!~x7w_|PB%O3 zNO|cgkKb>`{}g`y75_`#^|22)e?b<3(|IBjd!-A#gdwHIf3bHZcm+WA7RsCRk05to zWk{qg^a~EwO-R=n^7Z}^=BuWQHM}l_)US886OVsAUaq~`vyq2O*v??vS5k-bb9PCG z7wxImul4<$(TcW9iJ12%tL5r_mk~v!qOt|%s6lmaQ_GYf9gxRkV<^s&r-1YZ_dr5N zjFv@{6WN8TSV{=G2-FEPMkCwKSgMopj-XFWFWz(m+PaAo&8w5Jb#p!}OK3NQCaI}_ zfo^{!I)?~p#LrN6f6a%X23g6Cm$poWgq&uO{}Q$%EE51*79b#e;k?>jZ4(}*NhFOv z@q_#{ZOa6T#s_CNNg$L@GS+?D!BDkWuvy&7WJORN-dkR7_8asL5@^gP&y|t5OYdF* zZOAV?PR2v9UbwQ%Gd?+%<1mFeUzX|vIGKN# zqEu^VQ!=f0A%CH^?j%qAFAtVq{)@BQISEtPD|8Y*>Rf12a3qr&U-;m^ zseY63f8K+iAh$m9ru&WNm%Zz+<@taA8aH;-NC~U;^E1#|+&D5LNz>>%Ocv^)0m<<3 zG}d+l<0hyBDjMem^gx(;)qGD|LyCVN64@TQ-UwUOXz?HMk>>-h;;%|9;i?GQX{H98 zC#a?dUFoqn#ru?KhviQK3i>AEx$HB2NFVC~Oo?B-kZy=`SPhItGiFUbK)!kL132di z9eQol)CpzdvL(7x$l z80XFGo>%EC1_8y1|@AP=7V;Yff>}2(BV0DfFCpoA9S-B z9k`AkbFi(@vW6{wsa^&ZAXqi2_a_C>^NqR&Kw09?aN=hZla{cJ;Q_a~i|l!2k-cX9 zBeZ@uxjW-~5qRu#cj%!#Vi@7izNcpN!vl^H*oJ48te-+0OQQS)lXHKqK2LwcIdZEb zj+WEzbe}H8{tQ2Uw+G6Ulq=)>?6CDNdMR;YEK{P7N{cdQjlz7?X zXumBkg54zCv)eQJ)mne3hhl4%xKh>YNjFbpWEx9LIKTq+kBl6`Z&>~J$*(ZMMY@(x z;CBSXsAeFS=)iwz$)bv71Ctj6Ks$dKIFOVE35Cu@ouXwF!&_-WUKmO#ubS(DGJ}b^Ux-IeO}vEd2+IV()`m^%*K9iWfGxB z#jW6IJ_le}`6X;=xbfjPlyAA^?c{I&{a<`FnT;gjNgoLSVg3%i@D!UR@iZYXiJjIS zNbIMh5P)Ormz(?vJk96>RS}A3N&Ay8|6RHH4Udw09e00+U5L5z;pyN05c$xBpOnA+ z$Ug<~fm7(42nfi~#gCm}uj6~?-%*ENPhNi7&+k{`fBI6w51;jPx%iSV(E(^ij@vtv zalb02quiTXdxxgQX8>`)pGCBU`o0Jm>J){EBYrSQMyg)Nvh7|u>#*wINq1#&cp&sb zpMUGl7@B{^(h?59V1^c?S+eQT&sHjTicW}@98uhBAUuvfnIcI(7LM*Kz~MmTY(TE) zx{&z9xY%F}TK=?ut5exLwnS*GhAMdBBe^{)mzT&5lN9@9`Wt_MKd1oW8ROtF4Vzxj zbIY$pSrF>!^|7xhumB11i6>P|*0H>FJy!dCl0tv7bS(eFFL;#lMz)6Sa{HAuvC*?; z3ELBv34pB)(VXfHw;U%w!F^gg9snB?$orsU^lX$a>;>PLN1wK%k$%GgH@oJQ7%DyTq)AQ zVi|wcz|gN?pPssnLmzPfnVptRpjjOP+O`)`OiMT*!-H=3&GP1d|L4{Rs$kBi1@6P< zRvj&}(Dcc$D%!_QMvOoQrDM65UuSt$^K%AWI)Vy+-ih^3O+;^(u|FQW75NaA1w~!sKHX0=OXKo3WWqR%8#0ia0Kl z!{=wAdkSH@0%?+nHJVD4?Ir8J0pNel?ZEwzm71|Kb+nLO9i&~tHil&aV9NtRhu!0h zz^?{CQ;g}&Ch?a`*8mI+uCGYi9H9wKKiwWwUQs&tNeA;w852zU;<=3Sumc0LvK{H7 zTr|CR!90eWLk|NIx@j>lDx;iGV+F;U(rq?=I89BwqvzGXUtA@n#kb!9iYI?1)jk0) z=2>9CCiN@;rzIRP;k$N>mtT0@3t}H}eCA++Evu=2tULl%Mp~crRV*H-am-R)99GFF zGa#i&YfNH*Jrq>K;F!nm8s+ZLxK^;qpA95>KKG@I<&@|Ds=V&Ue?yMG-VwXf`sj@&Dqtze&#ghu2Fm z_${B&bp`cTnNRHBwdmTfLH59&<&h>>#5@z>(6L2UaO@v4rarh9bvP ze%Zw5K*-w|>^&$zeIza#)8m5*ldv~7Qp7NEqA{5tN`IBm44PxAO8}mvO!GNRxlSET zA{~$&wN3DPNODcMktlyr!jM-Oyf5La7M2Ns10f`VGr*Qfh{n*3zr62%m%KO8!E$Fb zzH3Uu`39M_fmWl_fYcRLMAj5BO& z4w;8RnT+aCHt@e17!JxB$}E@3bfkseh;;hSS?CWiWS-H9$6lvke`;_)S|CDkNLP@Jt?i;g_%V zqFpjz2KFp^dcI3Mbm@;=_$hht^PeKG__1G;>t6dhSDwim!m&r*R9Y{JLCL z*G{jkuBB74*FJyFu7AjNsIuQvEigUSEgX8gY4g553lq?$zd%>!KgmF7|E?le>o zkpxbVB1tB(p&RyXjcCnuX8Ex%nS#^lvs_K_JHuT7lS?PRQ6;NJ)`h###(d?t`98-{ zg~9s=tLze}E~bbI)jdaK#Vc{ITp%R#dDP~`UwD6iDyHyk3&4zHs;`_@{v>6}lX;OQ z4VG|Vgvo{ZU7!4r-B-TSju!fxt*AR#as1d^BWvM)%^)lRPdqW>ipIQ=QN6sXWgr6Z z_PmO`rakfucmhfdbQ|&1_ox4F`{?=dqvt$Jp8tdYL-wpjCv5GXaF1JlgZ%&B`EYsE zEB=3=8Py#aC0?j8dj0DhCNJGF{_pZNU%y{z`NE}Nl82oA4Ef^DZ#<}vPwQW)jiimI zlR#yU2{livtDcw$r~tw%Pw(CY(hMDBV+Mn6H3}|SNK)L08!n}Z_Z{lT#?mULBr1d* zc#b~47ukhO?dL(ayW3aB>?LeZ2wnhaZ5MxdIQ&m<#3wO}3&s`Y!THsu;|u4RUC{O3 zaZLm~m91Z7LGswKA3vlEGiv!PpX!64MtW_8m^||9AWFOOhI9$fjPRG$!6VzYAc^rX z$!zh!_Pn<}U>*{js6Vil-Allg?o~u`IDl-#p)&HSJ8wVW`i*!-g2>KP3Ow=a*1mtl zeAZ{2x8+&<75AsKx7C|?SJb+Mt1&DS0NWNixl?S+$hw|C!{cSvSP8TxCW=JUjp~0<2g(q2;_|sIEiNf*QScCyV)4ry?92e(bLaWm z!I42p*F^gu-z98yIO+I%$gjWgMRUKIG042SFKz_czSrEi+MjHtv=}A|UNZ>6rQ17_ z+vpigQ8~#4vaDzoN8+!6DOx^{U9(-;_JAp@v>xPY|BCngo&54EPnV~B_m6*kC2YOI z;rmZGQO^I5kIA$D_FNJ+B87y?T4m;;dk&E^Px{&YZv0Q-=l%KJb4?}6`j2&+y4 zG<>QJw$hHVQXyHy0ko80{JZqZ+`;7#y{0ca|glz~aeZ(fE@HFq0PdcyIzIIK|dfpD$ zt0Av&?hh&7_SnzMFz+M=g+aHAi0x6=v66un(^kXaqU%nPM?6%WXg>s)#z@B)#&isX zBG&WC3IjpZ5=3ty{z>FT<*{yhMrp0Qa23Iof3lWkMI}5{BG14}?gxKdH=abGbT#un z<09N!K3Lr+uLwTx0Ci_C0&54(M_gWmr)ly$(!mFTj{xBkwjnGN0NWPAcyy39hk;yl zms*ivd{TCtu5xCT48bI`!)Hdqo=E>}Ugt7yM2dmkCS!_p#xF&+lu14gx`xV4>IQK*y8go*!O$FV!dgu#z-1NZtlD+Rhc<^I86ohQd0b&Ndx9^bVeIo^jS z-1jv3*9$%-uXx`-SiNPwGM5H9^jg=J7oPf9x#z8Jzu(J0^R2I!bN=x!;_AMrEMP#r z(tZDEqoODLYdnARgo5E;gyL%+^ZOM6a%8U{9%WmfYHeSQAaU8RW$_US(HN2>SG_FD z5Bk#pvVUWO^W!ZUQ-8V3&AxsfJ4-k)1KPi2qkV{J@P}Nn?Y#=A`LfALp&{c2TmmZu z!%%+fex%bYbzGjmM&_T6cU{G=jE{_# zj-kHg%%$5P#bp3KH+rwo`GsuQ{x4Hcjpjg5I7fw6j#5R8cpvE*l4LP^zd@!U0%;12F`fmVC zrSA)!oGBr%&Q*WDUc0=Qf_{76jC9D;$$cCX0#nCa^I*Y>GqOp53bfDZ#5z6X!Q;<+ zj@B+h@i~TjBSELlH-7rg|VuBx>Jr-BeS* zLVuzD1sR4_wBS8OI;X@mOj3oABe`iSXKS&@$RB4%oOZ_(_g51v;pzz17jeCsdu!L< zG}?Ulse>@-T*e_o0!Y%xg)?GhkMc_Ye1m@gjfPx$9XmEf3}7ZR!PBYyts`0tq>1Mp zKx}cIm}j8ohqOi#)5Lrek^z#i3)clF@#i{~_{*3LaYuV~X~igz$Slp^c!c3{evm_^ z7b&mM&V=2#9U+rDy~&?vCVE1@ai042w#1)6GuL$q+Y*)ufNcu|B7D5`139=W+Ted| zH@pw2$)&6me5N^nP9y+g0!WOTf?O{(qzUmvTtFt-Fjhj$2MANDBu6I!*W?VJA`gPK zu1QyQAYC>+W14H?BL^;k9~b8}>x4lb5WAjLRw6pjAB;NX8br#)Wo z_uOBQPkjCYfuJ^Hkq)$f}M7n<59yy+jtM-UX`MVpV zM<|po*Bkws>o;7LV!TEfWKXUTKr4+WdK{ysyct(nwhU6*Z>UzzH*8&& z_$i`^AIgK}k-bZ)L%lf9q|?#_NURI<&eKI2G0_QZM{TKj^sLY22=RY=3EL8u34m=2 zL6+C_j1`AOMPY)}6ZoKHU{mr)r9n+O*}f;%9qB+qc7+Nq_(B4ZL_?mz4gwC-@`1+cr%)Tz*i_E?>1yrIl*U;B zg$bc094O(&huuK#d)x`~x_^78evWSy`ptZ~!r=h5c?Imz1FnLh#$b-+4dlcC9A!f; zi5&lCJY_p&x1Q)yR}}4t^Vr1s1yfj4=asgVp^>0Q=}!8Fn~Q(R-BulUy`SQJ@$yUM zwC6op-td@b$}Nt#$(3RCuHl&LA1P-)_;K>U=l!yL@v=+g+N(YC{8N5L9&p>cUM1!I z)XRQf&j0lPX`kwwf{7y-=EX#Z;B$W1^KZWzL0`|4Dkg7O_vpU=ks7E}xG6N!Sy^dS z&%%Y3P{w+_7Kwl0TI14rC$`ETWS4rugfB&i%FMbmR=#N-GfOyFLUr7Ljyyk3n1eAx zP{({DT{jG~soABQun*%vTTJLyc{yJm7ed$~2v7-zXjeYbN(N(JA*PWqMi$OBUsKs5 zdV+D9#(SVM*I|H7gJ4h`74jkabDd*@CVmX?Z~%TOG3ld*KkI~Ez+)v;$Yt8= z>Eu?YS!$g8&;4q8hCS6gV0g}Z{&cqHpY_rb4w!K29Z!_k{o6YPuJ>&PSg+@e_#{i{ zkU)F|Mc;Tovq`lC3PY&$o8*E%tNeKh$XDy5dOd%w{_idAx2ET7>X);@TGi+)bG?e_ zmKOB}z=`mM_lfUZed?kM<&@_>NnZ2lr^^ivJ^U+W^FG5JkGZw{(MgYyhrIYV<+LYn|kXAVj z*0O)W1A2q5M7;ED-j|F{toc+r@sAO8GHOn}<9)6mmzS{p0evw)8!0oEX|fM|l>3g* zJ>x$K8N@A`TnK(Jjs~=LxRS>k9*uAm=gHtIVW_T-VUYLq4h+>mhhnxG(rhT#XfH8p z&Yz9-p+{(Lv^sd6_!#)caX=fF%dd7TC)0m}X!*Up*a!W1w;O*(G;PXj3EL2s34m=2 zWh8{6(DV5K7S0?`1s@snY=rrWiAelrDFi06fPexJV?iRlP!gxTvS2HP^a2}lC0C6y zZ}bE`gh-Y7v`MIdX66q8J_Cb;c*bA_pF$^^)?8nYXMq(T*Jpl2!aV7<&NH5?$FqO$ zsQ=8$B7Va81_jk01Q83cl`vPB=7~@_ear*>&$H(KN6(0NRdRl{*Y9i23sLIkre4C< zhX>yFZgTjwuOnZ${L;3vKeg|?=wE!&XTGn)J~@RZsxa1QEKd(+dvDM|GTwn42(GUp zyfTboHcvjmSi`vma~aK@zi31=^e}&O^a%1=KPEZLt`{^e62mjCyRr^$R&N zZ>QTqfHLbeJO5@5tB|J)5mqXY^Lih|VAi4hYyhTBk5Klk8;VYDg;h@IP%(cU+uZ(D z*j4p5*?D&OA=lX%D_6~=%o47S0NliVGvk6}pq2D4;{xQHZAue|2qk^R z_<{4y_o-aQB5@^YkS5VE4B(~6Mlet}l)o{6J{!av=m-OSKtpchoNg2sbnb)33=BhC zjQE-94Vi7O&yfC6+FVY~1NVO|KOo8_Y+qO=0JbcYN6b#uNl}y}&=9J`I`H#Mc*qaWNf>4MkzIjv=E^VL=j*ks1DXbc zlvr-a9?!!5HjYGOS4x-bZe=$q*OlKM*xbQ?yRDgaA1Z*uXTu=e206<8E^md)|e~m3!+~Gm}3$sVh^1l zo6W9C+%AMY4ZZ$eF5q@HATkP0Olk*p*BbL{#|fJ zh|>SY^WPyq^S^&ze)oUW$9(0?z5?N@GX5{RQQY)wb*V8ZycRqv3`Pgbc-A78Y6{-M_G=gxHUZ+?c+`9>*$^K$&+t? zuX(I2;a~|Y!*DO+pSO_oyPE;F%k$6=GXTN$rhdKwLk$gS#yEdj2HBG+%D{`wAovx-%O##Gn7_gm|v&Zgd1vNBC^iW{m&*Jy0@alYJs~ z*Z!E1*{E&N>Z3SI*oLr70Bl*P^w$JQmLX<*>HxO!#XwjTyA~VAwpttj6PJfaWN@lK zrpfkT+zo__0cC#%K1sluKB97ikxbXTpVEL`u4@+fUXM_OS=dYy(aIoS^<_0idM@^r z1XD-@(f2Jh z@L;C?#^aD>UFd_p&BgY1vm9cX$}+BC%M)m$XP_NN9<0}1AKg=a)<3*Xj=j-M<>&5q z+LdSeS2;ZDCBH2n_{_&57PVD=@rQW}K=uYeH0TRV2$;pcQgN#NhR-nJ2_qvyTrcJ4 z;X3KW&h39$;(MeqSq%tXV>H%xm0sYvZVh2X3hNQz*v_L zuto`OHsEh)pN!9FTnCR?V7kmZ=1r149gVENMsQx8tFi_r~vb~2MQ zY+lDElS37fj9$W4gk=I?8w2el^Z_p2!OMfvbU+(?_B~?DLk4*#VYKPc6*It* zXA!ox8&=K=sU&%o%M2BXb<1_?;$~r8B^uIr)k$9k`t0VC-noK{0)2_>YADK$#9*@)Cb`ZR^@SsvXc7m9c~aC4A$} zj*~kcbF94UlOJl(gAbap=7mA0iEvhcbpswZ+-Iu}xgv2q=KhSaF#;nf1S|SYZkkt? zWvlPiXg8O1Y+aeX0*YsYGOdW>dF|vedyRijyqNQAXCgf1HD}4OM;#;Icc=SYG3IVT zc+Q(&Dd)ZC%>r|!@lW0O=VocYB_H@V{}4~~qJ#+nTvtyc;%&*N?MsO*Upx?0a2=_%_IoAVIv+;jd z`>_*nS!c{CRxA9>uM79*5eBocVZ4-0w9)g?nM!4pH(|J8Ni&D=(W{%C3XzwXa&PBe%WDK;q}1IoqS+I4yKtv?=jG zQl7}Tt49Z3m#_t4nE=?fV6vV;DuI7oL!tviEgxpbnFc$Gg|H0ruJIQ_mCMR2x)2a1 z6H6NJEJ^Sv(G~KoyWlbBP5hJ>2dw48FGhvv%6J|5^H)Sh<^`U&4VL9(sT0Z=0M-V6 z+GmoGPm4FprZgGQ&I2HNYI|4KE2#mv7WwfPJzH*m#Es?dw?6*MWAfDy-tp0Yl_$L7 zdGw@2R_jW?**sYJpEL!|MF@X}e)0Ba4}v0M86$uGhPuIc>K8Vl#BDti*1J4MxkIC3 zASZdXzs8t8L9234Jpdkh=lkc3mvB&ok)=g_YN&&!K4JS?JeTBc)I`My+hn7w#@8Kb z`;w1k@H+SR63B1Kb{kU(-;Bg|C@x{g4htom67nCUsdca@o%j{b%^H7|gGWq%qHE5F z^J{U8o&3De^E_!_I#Q$%KfPJ1#p@tks3*%$^o!PC+@mU2gB}=95~gJuLKk1K+_r{g z0$?jc9#|yE7@%fBRHc6&;_Iknp_mQgZcu0AED2dlhrDyVB>b7ijxM3{ORDEUz)PIF z9Rj$aYq|{TIpF6;<9C09GN|d-$`Of%u}GNc=D8g)(VcN zg!H*dT$a%|;osup(qz%9)w}TPc6Q+(|cm;?P|F%lyg1 zigN&HVna((GOJv6`Q`Ehr$0qr`{-xL|8w-suN>pA!tmKIUNrCfzjS@M%&i2`mj1Wr zFcMll%SzkPya7t{ia->OZ>#*4+PjF!oGj}AW^3T}M)}5Wv$etNV#I7pqitT>b;VaM zSdZfi0OmCpudjc1$YJx?Si->+cG2TDNQC;Fb!MSXE-)Zlw_TBuSk(9z*=&GvsX8`= z;wCj7PfUt40|6 zOQvxnrn9(R6M>AaxDS62T^!GzC%&^>&GodxgxZMm zkwJZ#f2h_bzAj-a!ZHD{Z6W%hdoX-c(?gD%2iv{|T?Wd@NbL&G*A%yIioZ*mKqtQ% zl|RaBmwbXjI>;j^5!QxTie{R3<4r2NOO_O>j1GUv3Wx!7l}$9d^4zTsOxwQNboYA2 z@XBu^nV<}II9^$!KC+vop6ItJ$xkX8o*+b*C+03^el zc*hX_>=!>Tr#$ypK}jo;@_4JU+~F>8H1SB24N8~|0kng z=pNCl_=LbzhG3s+`m|rc3TOhW@F-vq9t@rYuv1s^{Q06LQN=PTy_?Hjdp~6{XV;B} zs@JF9;a>CDSi->+Sm;pa%9vo91cPnXt>)A1oJG4RdA~abUfB0diK__j^^Pz>HM!oq zuGW9ChY89MpT|`7KF#H(b5qP99AF_~`8&VPJTL$pIZOJ3cN_3z0`hg%YGqg^XGYuD zO|m2NfYS&4Qu?&S|3-H8asnBAUwS%N9?^`39i%&wVYz)Qi!|vHzSa=y!1g}#uhm84 z+F4*J&&3O1E5kAYu+=ljX?-u60e(>>B$>6_8UfV1xl3g&;p z9#d(?7CdYMND`M};Y5GB7I7>)B%Om_VE@y_v)yLb=Gtu6X4|gKHg9%Yn{C^+H)FGH z+fU!$^Ecf2+}F%G?>Y0Ci~b(?RQf>WT^RU~-8_X?#TIG73{Ly0`uIF%y);Q{$n)oy zykBSGAUI#+{GVoY@25Wb(ZK9a6RykQEYihwX0mJK&lmaq#Lv5=7IfoA$BoI~_@dFy z_gT{qR0jvh&-FJxpR8Pr;J|)g=*OR*)HAZ&ZDmprbB2Y|J1*`L?*T7@+MuGpUc$wp z23S4{!=+3LHwcA1NwNYCh`Mf@&-?bt@l%9q!|ri-=d}4CF!U|zI=7q}n8z^LPsDa6 zUM<->N*L0UF}CZp;@@Gkf+(=Q3EY?R_|djdg})E;iRbwa0_ z%*ar8Q#ZIS$TqAwd`#U)&B%<3;9Z)XRvFzx!87w0W3jH0D5uK9ys+^EZ1a$@ai>G> zEV6N!Stf9erA#xFOq~BGxOo-~?d;#R$bEfh-7)2}A=`TzVJR&Fm-- z=yO@ICdo*!YCjjKSkaZT&$bB{1zoMgT@%m@XkvmdPxXEJbszQ1Q;hi> zMrnk&W%(inEMk(Jb}x0qWiKn`HV<4(C_*mckMHZx+WoO>9ke-MstpRH>baVME%*Db zkumWeVNYO;j7CJdR+!5{-f;!KpTnE~+f_qR@?Y&orJYg9#y+g!MbM2zb>c_ z>#S(%{vlzleK=@-fXN!qX`L3ZkJw;s~`ND+c+3Jkn@@~z0sGfYDM3_He*5NlayG4Y4q^;U{{i!O*D@^6Nf#O$y%Q}#dkm`qa-{S0LC5>*+1$%&-t!DR3P|fuAYFp- zCBl|qtG2SEr%UxLlkalfE{U@1#`$?3n(vI(?9CSr%XjSR*m>B8s63l`d3A=L;CaXMtaRoe&co_dTl{Bk*X-9E&v zjbatXDd((jUn<6ldr6d=cldIPVi)IlSgOz1pZ_BQbp{{Kpg%49kRFD2frTJqP^*#@ z$q@qt1T1yxoP;vt4eD{SMZaM8k0i<7CG@N7Iu&OBXVSk#;x`U%*F|oD76h|zJX09aB^=Ajj%)Z53 zYC1^_b7zm`v}tCbUAFq^P|TSfp)OS=Y9IcK)Kx{pl^r+mWo zURvuFrC{zJJk)rnc_!W5ct`+^>IU;>W z8zgm`Q6=m5Hkq#XV|e2T+hd83um!-~p@o?X8X(hu(!K%sUvW&ko8oakM**n*dc$m_ zw>c+5*#xuQZ095&jT)3`1fz2IS60&akBFU82#*vO(^<{AcP(B(O9;rMG^6vdUq?Bm zT6zcypI%wsanQT`7l;N-K6*{G z$tsW{t}0l$tE8Z0QX^vio742o@gaZIBx)E_{a#N@X_d9&0B#9%Y?MYNC8`eL3rcYw z7WRvUtyCBBVtQ${mgCINAx{!t19I~nN9dJ4wKeIT{@CpFr@%JzSJ($JWqmobw$=&x zQSZziIE*h-M?l8*ET(1EZFE=9sf~wo8S5b}y|Xpw6eP`SxUA%f3+gTd(_E$~`ey|3Tsl@6DXmOyp z_pO`lMAC2av+f?EqsKEz!cm14Yp~d%jKj=fw$dQm+1%n#0fa$EGu!r#vdZHW zAjuZ^#$C&D#Yl{^@)vo?nDv^fkz*y)<)4|_Ps?9_Si?a))P%8I?R451?-o?CX0+?MTacx0$blbHug;l|c z26vg3OCvIWhJX>8m!i4$mcG5=~Kii_c?*(^itW2d>VQ6Y>sS#iu&U*q?? zw)O&P-g-FRu{=)F_2{tlJZl@~U+;fUbmmnx+fts$BdbAZMdG5($(@LYr+z#&Nm9YcxV3atPzbpk7NZ!r*zZ`uG{$qzdKL_OM;pTf5$!w;v?H zoAYzMIG^r?`|a+7h_uf2l^cVlqaKC3=G7v^;wTJNFT=HT^MDF zS-d2rPYnTam6AuG$~*~_Evgs@Yan1+`s2eRASXf}x>d|0L5Nk6Ai9!RB1rf_jq7H* z|B$IBD3HNf1GX$XTS%o+q9*5aN+654EmgWt1Xerx$f1#jrgkZpnsdXM_Gs|7BtxB0 z1hvdmgH?`9kH5bGq@QNEa+@EM0`Cc3-^CPNm%!T8cN-^hPyy~Xxj)uL0Ry1MGg{4f z@aq;Co}$~7arJB?M&j~4(3X&RBf6uf!|d%XMVLjtOs--3Pc&KR0k0BCGH5ai?_fyNR7jQlk68 zkMBN{uP_qpgd!scYKudK8c5QYWgRdGV1t>I#f^I!aiK;-$TQ^r$J8LeYFnn48zki9 zNOa>C+{3IhkRju!T>n;%D{}mq;MY~g_UObP?W0Hvt(zj(037LFFigFqJDJ*US-|(0 z9LW(um52(VbP04W{3Vmm4wb&8n*HFi2Nl1YPOi%^(DVb7IA}1$2G*yGnQB62_#f@) z_M2t2n#jEka%5Y2S&E->UE`a3bad{)FYlrtGLjiZpZ+7_l(S#Id-ThH6s^65;pvyU zw&ZQIV0{+zo{ewDc3PboV~LcRnvBTn^C}cJ%)T_j_K`MS63H}%}Cmu-d*{qBQWl0V*fT!3Ssw- zZI;K+AicTBY^Ikv^j78#+q0p_m0+g#IvSddDd42uiZBh>*!eb9rjqPp&VZwvuc6Kr z=!sFr(%7Gp;WO6}RPFg+kH>XXQVPdjw~ncUAFp863-MTO2wK=J|3w&I+s=lPtLKH* z=Y+b(mBFGEb%(t5Ekf1Z?UXqaPcZ*uMwivRAt6JzA0LtGmU1kWgcTh9Rmv0B6;7T@ zuNf)I2m1WeR-8e9i>yAv$z_(e9tUb|03hFmpR#AC8nSqIs&FMp!)EBF z?JwSp2!z1%GyH+1pSr-yvE#c4@~c$(7F@6-;oB0|R9wvGA!L9J{I5G&fH)xn_oJ|c zvWGCbd6*AM=DXe6BSY;v^!cS)=v{ZTxqQ8lycpR}BC}=d!B_;`vH{#p$%*x{@LGbl zDxhhxj$r>w2^ zjr?HA-C>A$uhea;L9^|__E1p#HU&iuzVqkbDA=TLCen~iB?5NBU}5BRbwLMI!0eTw z?B#JRF8X;BYgQxXEQO84%Hs3Z%4iSK9H9io#6oNH+^r(a*Mt?)wa4NvXpA|M2^e7= zpJw`BR{1}OTXl^G3SV3E=U+XpcG5`?XMy$kXbn&_GiNpwn!rMvalUwpj|5)26LIYl z09Dz&@gG|>V3JFYbsNvRrQ&{eBB;<@NA=wH5qn*9A&FcB!rg3?h?RN7O8cOrrNOV< zpqye4+^`@oTGr%Zh;Pq06!7+X00;%>owC33=%eqB$X7p~MZxg$=_^{*xN@7w+KT}< z<=HR2hj{raPPQb-ll>Co^9gc|pL{<#d7J0~8rCF9LMXL{wFwdRx4S8>3+{aB1@sP_ zR?wJnUp$99^n3TuTjU$q)kNojU-S(xF*lHx)b))thnbtuo5%c4oBDmd08z!IO6EWO zl%LB<1m))0-pJh8Hp+pI`^8rP2^?=rn1l*Xt!ewZV_Xety~(`#ZW zkkg*4LVAe3l#J%b#w$D~b}{&Mkk@41H;XC>XMkzX>mEKm|EYI_=GH1$Tg;_`(7_Ogl8Sxb?q#LW6RIQC z_7i!-U7p`%(Weupr6c6s9kO9WtJ6y{b#eKKC~lS_t}1xhV_g8^x`?_Nr&tilx)6dM zuJ8x(OHE!nK&O=#aOwicTZR(nXh?ZiDeXW^#{DG6s9tFo$1Ho6 z(!eYdbOq=4*nEg(kl6mm1ld>zF8XLJ*X8CoM+Vlre7Ckyh)16c55PjTU)OT2h)GQKESH zM~A~WLXfq)IUFRq&a9ZJn7=zHkfSDTZ__A{3o;RvKn&=4A_^06{%4Mm|EX9Yhh^1J z)4Dkvk;gs7Lv5JkH~m`pyNK;4yIoZA(ogQ*@gP~2JINb@5XT|0rk2=X?>w^2n4_QU zv6Q!sw-W_2Nd&oDs44%Ts$#Q6+eHe^G=ChMmD-Tb-JVJjzm0fXUAA8CVW%2?fQl$U zYPIS_MvDRh(~Tf4mGEB~3r)d)4p5kD%8&%uORQHKpg>V?W?C|NL!&WfNvA!)f9gXm zpn{Mq`Q7I&90l+hc}8jwkdKy>P_eAHPHy`U>?yvsD71BCb0#nP56FloxCif|Qs>IL zOZy}2L^GRoCF@N?Woiudd~Yi6#!s>ecNyYtlr09{VzIL1S+86{+M;y(r?_e!H2Q?F z{s*xp@T^HsdQ9mzxn{i#5%wtDKq=%C4Lvv9Sb7bdwgfI2Cq?2VkutLPKOIwmiV5*F z{F;8@$j!s$v9INI3A)kd)SUnTvC8xa~)!d=>o9_hs`Ph!fRDZx% z^D80?%SX+3ufoh=(O>PaQ05HdT#;OEVQWy;6&RF22lySMfWWi&en4J>&nL!TY!GCV zN*g<6ex4GHJXF?4`?VYNEaF(=VT}$CBH?G>39--@$dcTeTQ@tN5;sq`QP{_{*Eckz zgPstyHjWs)t_lh=xW9~dYPg^)*;)cF8i3OGdn4Hyo?k2~w>wU7KjNt+O^P!@yAV~9 zPM;vCn7g(Fuf`mS4DhwfMmc{$uya7g6Y@oe*i2V_r!86NiN6ZN$D51G!YVT+9X1YQ z0%sx^MbchZe>N7lbKROHmf;xtyD*eWoeI4X`gR#~k;JZr=k(oBX zBOY>9Ke#Hi4^ocqG7U_NtAR@lyC8D>SVQwCA^F)(TK)caCP((oAR?I+HbR*XMgu3M?Ld&LgHL6*63OHcYm zAWaPaL)B$Mp0|GS)gCh@bxi!rHp^cCY!r|-oY-|U5|GCf@LmA&q0^qnA7Ys{c7lUY z*JXpZyf*Fh$*K1-pvV%ES=#WTR+$4!97iIZZ*0fU%kz$54o^9?WDIm|3R_ur?h19kY#lpQhh z^C_0QI#gG7Q!)DMlVsSGS^iS!k0NNR-WAz;{KzGge|IIy^yEveAjL7fhnhER;%gdR z_Y2M4%o9wZW*ry7H&}<=B0I33A6C%s6OZLr{4LL9T!nx|LUjZE@{_vlIEHp>hKN}3 z9(DFRO5#SK3R$4lGzQ$B`>B`u)17SG`@j9;FrMm`Qn&*2$^*VIkXIg&;FhTgP?5es6ps2V7 zwu}*}88j~wiQG5h_Zwq8ioD-tZ9hz#{6aZ0Kjl1zPN$gcf`3tcGwbsXmkc|?L3wze zvja&^v#aG+=2@xk%pD2~a7N&ae$HS7*5~SRUt>%eV)^j1t7y}S*A|Q1toZKa_0M%K zmn~XKV;Hu#kbj7q2mcdh{jSL&Y`bjPLF?4JfSc^_uUM9kCkrOlKQv*T6Y|37hha|A zBzIw-u&rKBc0)D?$x%w}nFl2A;e<{?54EKH&d3kB$S2ouVsDtUr?5#ICPx!WK(oJ} zkhGjh#=5Rp;Z_KF+@X9-H6QwXsWD8W+)-O2-!nCdB8)5B`l_zv(Vo(>^;biS0i*4o3nT9Dgzwg_DG=zAS8OetFaZdMB|)hV??)-R!cJcl(J( zrVbw~8T=YOXm7|ern5^ig%T1l%MqxJI88#TKdzhAysSBlIO_4{-1f{(!4q)?idzzc zCM6Zz^xWd#Q3$Tm4lNy|o^)ZdmLt?inf46+*c%+B+~XYSJfO@#I@I|0BgBak z{EQsG!jK<+E68h%>(W=57gBF}pCW(sF_JP04e8zvMVJ|vd5wLy*u@jLXB>ADf_~GXpc+&UDR{cR% z-6)p+@R8ke_TC)=!E((MC4KRyYVi%9V5Dkichf{MLEiS4r+wh$K5`7(!XdpsUMx~g zEb7=i?l4?>`Yo-j{00}BpOn;YfYw@xOBF`j@2i-r;_HGLsAM`RzKf`5u8g%&bY*6j<|uFT>a@bLsdKl9JlB!nI^DFX z#-~+q;x~{sOIfsBa4i}=Gbg`jS}MIIo>CmIB(^l0A+_JbR)H)3cB`E*mU->r+Si_A z`6}{{YU*tV$}GCiS3ZC|`4aoJvB`LEWg(WEC~7#T5Ad{m2!U<>2Yo1ig8EcTH5j4} zQUY?2>5wwa8s$MB(ex(BTA3&Zt#k#E!^DVl@5RvWJWWs={ud{gV?KL{O&_ zg8wQtW-1Hhkne`tG1H2`G5A^F{1q6%kx!QQ`EY7$&YsC?m`XV&e77*lIlomO+SivZ zB5ns+1FGH_`?=b{Brw32Hi(BZ<0yWyOAI8$C1%SK=Xmi6OgpR8%R zaQmn^ZJ4;AckODNdv1aWrGIm%GeisT*<~^90o5S=O(!W$EGja@o^q`I@Sb2pyGp&A zVAnZyJ$2u`134ioYe-{6bH&nT^^Z`DEE$x9Hikx8(hEus*3DPHqjnlwTiUUVH(Jn` zTD?{6Xh%gXFx_LNM<)^QdQVl1F)#Xm)3n&(3R3!8M;fxo)l9Z!_BZ1dn2qy`bT;MbsceAI}fA z%w20E4UFsK@gSwse&hC;>*BC<7*XecLgB>3EyTKTFKGR#K+We^MJbV85iVPyyasqd zuflr-4-u;Ff?G}1G7-!h)YeI_9*JJCJO-Ah;tt=ZKf^-aer%Uk^GR>K^#XaoIfj-G z+ez(;enRWP1fza6eo2)|({vK(XI3t|*i2E4zy1IvY)-e9Za-Y2iA5Py$aNTnoyw%D zyP3VFCcbo{eM;i>hN%|I2i~RCzWa*|E&MXKfVR5F(t4Ni#j146FNo9pM%h@y4J#zZ zt)IhR%|e#_n2!)=-!?VPQN zEjLjyUh%S_6`x(tzZE`Uwe5c>>lJ8r^g)eY`bKkt;qNbgbbbWo@o*XCM}LDaPVk)V z{a+MCmKZD+A}Pu`HZ%$P1dhpj9~AhZjC|8Sh_%zGyN~ z+WJ<#6kHpN*s1pD3?g+&cAelmA}n399@Akra%J6|XbphS#|`!tI(nWgv;p0%Gq&&e zVnu#IiSW66JZ@fi!~@0qY3CJW289L=Hvt;eHi`Bx9r!2gfGlT28D=^!=c6t_-|V?B zyC071dBp$xad_#~&U=c;5H7|ecg?|GsY8PS*+LtKEb2@O;voZ3`7`;2<-z%?P59Lu zuRbf^r(YGZ(AF}2FD82EPrjmD1T>g0lHvQMX)lJrn26>y8tWF)(mAco>9C1f^}q>A>Z*|?KY-t;tTeE=n-pJ>hzVo zbf~~i87n-OylWF%DKyp;3SKg0mCgBI<6{YU_YSD-BNn%ktoEYkmzie{IwBH6BxT~& z{)jA#9}BUP9Etrh@*W1$Upr+_JZtrc9B`C$$PI6RVK<2B1jlLV+`6hm88OFZV!q<$ z3<_%^k}eI<@A@5De}L{QZ~jnx!orl?o1n13d?=;fwO$oeFaWc6W4QW zY$xN)d4BdTO!f8>(yyI5XfMu_n$t1)wRf+*QsCamN6C7>3pCmlUCrD=v`>u=|5?H> zn1aZ{T4gGq@rd1_q=wqyN)4*bTpL4smrBi~WtYJaml=+9xB>$#x$`Wqt!wfw6zx>rEB4sbv+lfe)fiBjHul^5Y<8RVXjW10Dfx&$VJoWEwx zLbdoMm)$VNheWrqf?-m+9In&qW%5;0oTDkjK3^T+(2p-p#mZww^^vUM8`T{19=F!- zbNvsQ9uqzsvAg-*0|`~NrO335qAtl7;?K!js@US76K0B)Pbwxfjf8>;n8Y#@Bb9*( zmk066Ji%AKEYTptyH%mW-o@!`igxJf-pB2rZGJ;RGtV^Gd-?7~a`C+h2aohqQ1#dz?#F?c&R>B0$zoQaYJE^oKwyb?w8xl_yTw0RY zF+p5|qN+@99%h3X;>Cn3V0ZIH*YRalk2bsI$?1ZE`~3o2YbkWYllB)>S?j9OZ~|0- zkBh(yS8E3>W98El6Nt^_03sio-vo%_cUD*U{%Z zOYGoeYCHl%U&R0zxUB9fnk5)54R=7nka4b+EX0^;MdT4h_J}o+H(S*U(0YjFZi-Za zjrB18TRT(!7c|4m`J+M%dCxFu6*s1{Jt(9`E)Ar6ISB3qf!}<8?e}j_lCXHG4%2Gb z^c)AU@dwHn#INjQ1UB|*Fu0p>?=rdiZLWB)6Q*Cz;Tr9Lh+3IMUg`;zDN|KGXS#xl3Zz~nqfUeocpnw7$Uh2iOukU_A*gcGZ8e=;D? zFsMF6-1d8f3|JX<$3J)$#Nkjtj9f;KHWI6y?ei*<5kq$&Uzm%e=#irJ#%%V~TD^tG z{nL~*0IbjrKt+&snqn!XYZJ4wGj$=J7(x>yiV!)C8Bw`J&WLul3L zB4WGUqS?_c{;m2RCPtb0f?ixc|E+LFXQApRs)JO$D|fQ}RcL>e4}nLY4-s9=$DDxm zMQFLOac)X48_~Cx0G*O2sjRAsV{Cn)=?4Cy$gh)$u6nS_pq#a1)PGYW1kg<4+^pk7 zEPp~RN+gOHVp#J}bc23yoj&(;Hy&~!h9-_mL3TS)x7}=pc+c03b%+`esy{hzWyt=q zDDDxN@@(rk`3ihO?>cDdIW6vZk?|M{-B=vLzy8TudHxAK+8FW$mJu z46@~^U5Y5j>9<`zPWgDiE;jh_@6>A!bmp! zjmkP8WU)x6wOTkPt8GN}!s`bbr4Pm)d;_RGIs|e=DDLbu#o#4?V)oFRj>HmX@tC%tXA?r5A z@E^SV6#ogY?unEEehR`ZQJE))v*(q{qmq>G-;+7({vcQPDU*k&k`2b|zHs5d6QfU) zx9}obqTbfxgjkNwKF-b1_U2N2GrtMOzA9aS=!S^hsb%ErRzbfleB7gBGNanj+|jrLtUaXLjd?qaDO8x@t33xgN~ zEpkMlRN$7DlJU<7-d49jTMnjO>I^?T_jxuYbk}u?_E;&8k2~yQPmd?s1_-T}5jVzA zwHGc%ZQ!vV!?$KpuEc4uE7Zg-f}|@YdSP9CeNn+6)Sgqg17xZAd%tQeo?IQ zV!45N8J@%UW|>^j4lh_APMCdRcis;Y|Mk%lRN>^l^&V-XD8sCv>kv>oFaP*Omg z$70HXO$|`GOhf0S3u0=d-=VpWqVr#E`JEeZ$3KyVa zn>?nGo%~kzRZj`axPbP7Cl#V!uA*T<2}P9V zF!_h8;wd5Q0hX}&>j&5pdEd&&+G`B815@yP!)dv3y#-QR6u_&0>eL!7B%N9Xq$hk` zt?nD|_)!x<$clemUzdA=&P>6|R=Etpek*&qTqqM}24}z9W>V0IX4gLiM}C;wWpq+ z?8FL0Lv8;aI>28ssH$0x4%^iHjSfSJB}j*4Rcg@5#_0r1F~psxS3kX$y;4EX{;&-A;7!=STQo|YIb)q5?5B@jBI;noK1+kgj(Vp; zP{ccA1C_70m;Tm7E-i7ja%$RENbC!1`??i+h~jZftZrRb2t^)o2txFA5mw_G(-i0E z&g{2G*-iP3(lntJaLB96g9r!b{j1e>`YX?Hsh_Xw0dH?__mYI+^^l_(+GY}vFo|Ks za$mg_cpYv2sL*b)F~z;H7hN9#NvSH(e%uMKqW}Y|DtX_f zKr`B7Pk#1$uY4vbsb3XOfnSLF+n8>~5Nb?lgB{ev9H>5*nL&nmY}PeTd+}eBc#JGh z#eTlc4&E$F|4_VrLegW?=ZN;&H%iK99t}Y_kqI00hw;Gh1c9^*~JF3Q{Px*>COPv6EHdyYh%PE zX$@D&#y7=ov=44f_-Rxw1PU=e1_MUs$>0vik-3~`w_8;OYZcuMs4B2*7!hIg@4>U} zZ%W>flUT#S{6c=g1S3?I@cD3$s4B(px~Aq5gDek=SOFw6dnplYVS z6r@lii>S4}g$yVyyXQcXJc9krMDm z8`R7c;_2~~$%HU$qH|b(*VS&-!C=1O%t+cUDKi`@g9S~4YzVaLspF#vEk#q|h+GY0 z1tP531 zo*oriw9hDJ7;t4}wsFLG=Q9yBm>f-6dtNQ84Ig7X5bg7K-(k)@`TIG6{qS0*4XZXk zc>4x@7#I$djj_-q*rI)QcQiExw5vAul~nJDebSw%OI39ZfA3}GswJ(__&2SN9MmLy zyoy=7K?|;sqhyp=n|)*SU{k2@}~0=*nGT)pw! z_cbO4t#aEqbsrMJFG340cNP$KtPxR^Ztb#cK^=$H^!qUX|L=rA0Rw`U`8`M?H6_;n z6)^grtz!r2T@nU8T$@&dK$6{zu*-Q~j-H=^FcJjHN zO^$RnhqGK?v(`eB6jZc(0Kfm5rc8GAF8Dl7NS#Q+Snn9fJZn}Tjm?O%bO>`&@8Xnquz*2hF*dA}>!33c3s+@o@c@RTae{2h!j>`ma6)@0@V~OGv;&FDVO$o zhE~fRFRz*e$%`)h{@=eB)^+Wpe?omn?uLSm}|_DUMcF$ z@&XaY(eLe^xxGv)(q&UvWxN%zlvv&@ve6DEw4cc^C8PJcYtO(baKefxmdgy zDMA$}XCA4E{j{F=z0o{*RWjq>EvebRa_1+~w*P!E*&JmNW1f;O|$(>ty7Ap!Me9fu8nm1GZ6!vdB4&?8LH*S(b7i3gs~Bg$`S;=xH@*b=1R zaa2fRB40CDg^$xaG~#^Mr~!z>B=itsd4|-RBd?W<(ldCgB6sSjD3+!8K0{;i^~q=5 zOe$Zpr9%7Am+Ey5((;= zvQh}B8#twJT9tW~a0HeX1P0}#O0?WG2xSVrT7m_SDhnKL)Y z1wGs18eGr}EZmPo|AmZd*0X_(oCt#gwehB#<-LWnDna2O%a26$1(QtV;Ysw?8k2K2 zX4Bo=TBs%B)lANZhiL;O?3B@Rd#0M1jU?Zdawgda#ruGBr>j`jKECotdXORnYmCvy zw~Gx2Wx#ov3v2^WW^4H_V$|TcRRD{pU*!07ksCBG@SRSN{=^c_{us@ zAWiznEtOJsf57kOz_ee_7NOEu9v;lJ&i=-~h9X=`-?OC9eMGfF8k95S`8M-nUyL`Y z?)9k=PLi4X;D(%U$oHjNUkXVUu&#DzR{Y=|%WJ4p#YXu$eQBBAENu%C0rzO&gOB#pn9jjej?h zE3Jp#)}qLV*SuklZkXt+ht~74SKR3t+{g(wuYMsPC4nDW>H~v(UhTV4j;RhqZct!EvRnhj%&FQokSO12tq=p~sGwo>8 zZ9mQ0y8o+(AE`n*>UZ%L>$=Aezo(GT^Xg%CDtk;2(nMRY8iu*q zJ++cF%KqU$(b`7lAO^oY`a`%ffzVPgEftGj=@#v9Fjn?mzxu;lxe0H#x+?e%ds4+F zg2B`ibj>WM|Fi|4kp&zIuR-0hkB2B;2;2_u!q7ardTjJ-f@pRl`1u+NAkumTM!!G? z_BjY+_QoH046A|sy{HJ{C-k1TmS^LOK=OosCmrk&B*XqRyf27f|Ho#{0n}!{wflSw zKpWq(i%mHfrJDB*4@C8H&B}Im5z^X{i!C53ZB5lo8BW3Q%#Plaq@CO5YY)>-dZltd z-s+UO^`@Hs1{<{8Ssph%)fiSx{oPg=In1b8W6&17K^Hm-~P zsWcmMG{cTDCG6R~&~=a21zfwubeuc%R>~jiE>H7$bwk!3CGoq{S@>Fyok7+#Nv|6; z%VP1gHSMS%9WC|rCOd_lvaBJc2nFkv%GMnPGL2RB&tp$_TVW6hUuf~jtgB|fh zdPeMWv#7kH)ZFqio&8d3HI2d$XoBR#YSCSlg;m`t3oSuNq4yvZfO^xBm{@T=I<;-B z6Yx@_`$q5@wf?KFzba-P3(!;(iC+)#?0uL%DqD%ux8^rh{maiu;xGla)ISiE!f7z( zJQkxZC+l>R;Vup)gK{8YdQrjjoq1seC9Uc$VhZ2NBW!mnyInV4uHkv6p5EeIK z?QgHq`1LoIrd7l1+9{w}AX!qk7}-Fk82-SN3#uuPLF8V1m|My&z#1B1<%FMU1;MX~ zY?hf_rf+r8thc7K0Kyk{y=YFY8hHk<3%BjBBJF#W%;-rq;JDJ&&$3C=b=14WJC~ZE zvxwJh;7KL={*Vs;+Q%^{jti&rl`q{ncIjrnR6!4MKPL(UVh zkncKK$2}RfMEN(_I;MupvguUwu=r%IuW68&NSYrjpu>|=oPj9HTy|}Cy2?Y;OE+*; z*0r7CXqS?J90$(9#+TJsHuB{Jk-enzi=7XOH6%iDCb!Y;~qkY?_El&M&ES z>SxAl!E}b;ESS0Z}ZCQ$tE@} z`q98_`~LGMEA!Di7-bMG_+4bBpBK@E$XUVkKSux{+UU+TTk-9x6?v)}*PY1WbN`H+ zzqDYp#?JMt&sSq4qgGev?_9qfMes^m-=)Rp^YDmj+v+5SpOF=ga~ zqYocxBl{$qt-D5uqg~Fi&ez%-VXU=_j4Po%H@B)(XiMSpkD`b6*%bG+z=;{P6JC6C ztw#~dx)NS!M!!#m99tIi53<#IcqzK4eHS47&>1>=hz)Uult#SGxp@fMVCm(f%rpd(>s2JqwEMM10_{-)yRwT#;zIq05s@>rmm z>y`H#Q8q3};U6-Yajj$X?n>*zt2^H{FwWqx?|(5Us^s;wb5~GJM`XUilMbU^uYj8V zY>CWCw$0W`eF-&GR$#P%tNd%Z$CbHN{^MN#wyPTd*Siv|*z5Gkjw{%y9qPX>dgJpP zg6g4q!M%MH-23{@;zF!O)gE%^y!BOJCpXHb#l}WcdWI!SjBsQZ&gv2AA>vZT?4?Bi zqwAU;__P~p{v_HYFbG;@IG_J}!xI=wdu3!NV%^Fp7*!I_pkS2fK9Ih$CYcTHBgZot zw6ArI*|LR%2qMe!&~I?QLd}bP`hPUNgIi|*_dT33*>;m{b8<~J*|zOYO`OTD$u&(i zS$DQ=d$PN;`}O{OpXWa~*R{`H8|$^#+5=ey=tD)o6H;^xq8?HbuXqDnzR@cm3T8kFtKG`Vp#=aUrx8#sKjM_Sp(0=HVun5L+}pP=c)p`3&< zYbv{;Q7Pm-VXSzjbF9@N6@VuGHM^Y>E19zY<7fh*}Y&dQ@IjIUno< zIS5WkdGnx+7(F|7j*C4}4P1>;l8tiRhRQT=)tjC}Eei@G_$a}fjZL!${%MsjhTb|) z?3r2D-koE2zr@iVJZ31$(NQefJIP5~{yQR;L7A29Jsx2rR7uQ|x!eT*Z2@pXu^@UP zTtCL{8h)N$A!vP4iT$-C*d^s?-g)NY#Erx?`}rDFKrE}d=yr5LlVoeVdSrH{MO)TV zb61suyX17yz_)du9{nm9Rn6Y5n#UmR*RqI)*j2FD=z`4{4t^v(qeMS(LxCWsqzR+3(;Au2?ls#20MdB)b64z{cmCeCQ zABu-oohdDX_O(0M41wO(_0~CYKTZf!gB?_o2`#@Z*4vEyYPKtWW?DwtyC$$QTE7&@ z*cntKz*@H%ZYes`2g(l|--?5X-hMU2kVj${J?57QTWCZdohRKu0*1g117h?f(h&B* zX?OXU2N3jG^x;KQ85rQf{iw$V0$uPfpdaeJSEPg=-r0ja_y0_0ceK@91JhMYnZGdL zs|D@_w~h>KsJPdtqU~?kPP;}KYb;1yqm9^cc|_A_u0Z$fMZb-*63CDy|6w$JZ*&DC zM})C>6|NfhQjL280kiU{ij|_|4E$8iqo0<}@%H^@>2|tRtRI~_utsaI+9y;5y)K4^ ztfDk;({OiGQvbioY;wGPBFzU)T~p=mA(o)}Sy6tY8(CAfBg4X@-MTQy*9!fq5$E>B zQMmCO&j|BcH?@J3Rrx+HuYsuetK>YbFG~fjQ10nFP^h9;#j97*%&4JGGV|bfqTUga z2zCM)g8b|N?K+=;q7SBTO=Zc+jgJz~?)R6ZsHcGS!x~4kZjIZ?hT(|AlpIo1q^u() zw$~S{cBPl#%@;ZF&(2F)T7oqY#GHOJb}2!(hLhsknbkGlOqFyu`zP)ZP{8JGo#(G& zg~JvAW3c+fkMbFvwsc&0B$Gst&x|3tGh$D3wXp*IS_`h}Us0)a#**Q?l&C*GuRL&0W?)6DtG;GZ9#3At{-+3hJm2~FKi!Msob`&zkou+TF60B%)oq>)JQA9jmDD=SfuxJ1^v^QX>`}X!?8+}ED z6T3L?^>p$*aHhfX?^}dXd7Rmi z3ZW?eJ9PTVn?Juqw%a#F-~QddpE)o>42^r%zDoZwUW>D!lzKJK!O+HETYYF3{xECP zBU>*D6Y?ps(Ytgtc15T_LW#pG5LBKXdPMrZ4`c1ZABh)BLD0qaS|1>qS=0fkM4x5oX z+`P$f^0`G%QQunU+q37>Gr{jK_b(0L8F;fxMJwH;xRXCSwUfbTnCyjhv@na#IjdPq z;84i5C}u3JdFYg5AJfcnlq2B5roMsASuFAZZLByfx%^AF^TeaPHjxI+zRvc<4A6eQ zvDoEefFDk=G_!SYRm}UMV}##2o`qQGAsNMX$#Pi&K{z;(f&QqH-Ra8v!}@91$QLFq z)Aba^{<)$1yDJ7P`x>U#df3|MHcHY@+Yt`Bd+~}RMn!fXM#o)jGF?E%IYTyTP^%&( z1Jr}#?)Yzzj zS*>3#LiLPDW{(ivV#<=dWu}AyA?RYK-?%aQs&df)q7G+fq&I-JQ{|@co_<9ds(Jyq z30O?vNcEiD>!_&I+Xi;YRgGj3!rFd88h_4a*j2Q9`Wg3d^APhsf6({->J$i7UZ~l~ ztqTf)a*}q;j*Z)FBTH4fwyIA_tQK-$dVYb#-R1Cm* zO{K1uc8p1`cz!my{Hd>H`GQRjX(^3)xmpyT^ubs5&lIkV@aRAY^?!>?gQH$f333iKQ z7umL}E7QJ-g*xC&_{m4pN-vVKI=1_fDSfa&62!smZ-eVC>kkoIWr;PZe_SzAiM2Fo zon(TUsZPRX+}C&yuk$o2@j5p11m!__K}RdrDdXM1!_)`D61A@)DKx185vXI^GjpZV zWTCA#+*L9v2AMTh&bo+Y4Cct>9I?zCK{VCP(cB+i`vB`$a$yV zOBx^p#TPQ;KCra9r8nOT{PV zX3q{5JAfD1T+-YdtIjNF?vrAOM)t>{m<9dsqHfI=UD^x<{umfJS<*>LqMz~MCNz9- zT?on7G^7QNR>@Wl+;HLOHP;J3pPg|?u`C4%Ats`#r$$^I*GM~-Y~wh4h?+Z-qt&Ua zS0H6SQ;oDA3bt;2Q-wFPK95}`fJw7?FpGsok_CQFPoV}nNU;bBHMxfh+RXIn|6s|b z&xjF&CmWXv z+S84FuL&J?&H&spB(|V3yfqo?_4^z66SyyA{LquSK~l>v*5*ZFeOeoo5*(FM*g^$C z4gm2#w+>xVUxzwRzGu(A^2*j^Bp)3LA`YI32G?brBuU1b^`%CrL-)h0sB6e=E-$=ojESr8(R2QM4bYh6lc z(B}i^$*zo+tN%o4`}TL2cH0sBcrp|)2eTMO&=S5d`cc{9l^-vMGaL6yncBgk6&S6& zX&cA?BrEq*@BF)0m-hut!dQUH6p%(CiQvdEWZ#eO7*!!#Lw*U5@%-9txoek#vqNEg zQ>YT10KX`*-L2gk)BKU^+r#^>%qEJ#I&(sbgid(i2sROuopiG#0Ssw|tcWst0}m71 z$2K=iJj*d|MUEm7=^LZstD&4QMWzJNSh-b)%(5+<35&?>1P-C`r8^c+U`GRma6vhI zI2_Btj@dlFd|LMB^$y$#D26-$$B}Wg5DHrZM0g&LB=7?sPuHlN`aZoF?Ut4jF3UP! z@7vV{B~DN`!QO+CA6Yj7;wv?;0Q^O1C%!l1mrccd1p8+0rMP#}dKZT;bdV@#i%_m4_-*Fy-ehH$qvh16E849ReaE2GTV zsCgw5Uu3mn(KF`Vrn;3h(3H)*H!ZCNxL zxY~KA90~=szqxVCd2>d}EKyYCivIdLfPnu=#z;N9q$3-iw@o5MH?a z7`cC8T(`nfEcvi(8PzereLuM&Kkh>&C$R|`x{b6SUdXOB6G~4~cZb88Eddd_;@5*I z9@dfd`-{Td@FOnBA}?PETei_?YmYDXINJdq~U^-Z?*aLO*q#Suj32a ztqT%X{s^@>eLF|ll#Kd=>^G^-befC6aFXXujjh`boHkIkdEu&EvC6wGrZPV1yzbIc zRNt(+Evj^~z)gREY;xen>?UQ$RiPmU**QloZg zS&C3-mCXT(+o{S$qN6kQ7= ziLwJgho)NU^?A%KdcD#>0yX;A*bXIfN6;K3E6*^C!`C=2e==XqB^GB|(zx!&oX>Sl z6&HeE1*B(grZF&zOcKA!Q^akLAXIp-gG|;=U!TGt_|$Ul@~}Ft`m2@(Rx&1TmWGj+ zR-0PqhzE{+#xpS*uHqhR`PxfjZMsooy7slbCryh93V1(XKhKyEgICB`h zPaAlZ&B2i@mnoO~L9z`f`FrC0s%Q^|PjxPTBUNY&uIc)g7u5N8F+!9gP*?${TC{k) zfR=_8em<9?MFNFfuIz;Akw1kT8jW(+ZTJ@kwG*Bd5!W`VgU<@>KkwICVqm{>UI{+} zQCoarV|xsFZaq)2J5Di*{Il)<4FFa@AimB-F0;g=t_>cTkkzHlN>CJrK%^jvRA~e; zNg(3;CHF!yGMR)73qIKj8Ax_LyiH4F+v$wZi{bH~Qh2Cv z0FGkl#BlW<&6g#MWH_<8NU@pI)y>Myj#6*z9yBUfZ_DUeJAyu7neX+lm+$?<%RM0H zKWzjkv4!py4EJk9t+q#fSf;crO#XvJuY&~Bna&kjeA%@ph22lxKPKMUGX}H~DMy;~ zY!&~QP&BE+AbBh>_-{FPo%rK2x`8NvL!+HMu6UjLNjLI$oIQ5(O(HqL6yQnwV63^Y z`AxAkSC$%~)5H1`pW>Nvt;n9zKQ0fV!bswO3J7JfFk0u(p9iQH!&Mh;_5Pf1&S>P% zgXtjXcdm2q6CI+nj})tfe*o_E$EwdGDJT;%Vboe|$&?Xnoq_U-pBbY5 z65aBBUG%oEUE~YtUA8Czxn+jd&720{`+v>4QoK+5uata_C(9Z76i>d5!EYOH!|7yo z*;`HYjg<&BNI%9Ru~NQ!2p1W^)Y6-#M1XaXA?Emfs1Ml$XJ*HQ{3*!BievIkmB&q` zgw#_xG}O5Zblm&Y4Y1YT7Dg)*7fwZz?Wf)k#rMH}kM6L#xODE{&;v!2jTx=g z7LiOeF+gu8hpsu@4MI7+as%Ma9VTO$K6Vc4g8MCANRqao3@qeF@UsBxiSY-E0@J~c z#>I<3OjagPxD~Q_#=p8GFq;v`gIHELL0>Du@K|T<%+b7T?xyk~kC5p!u(PIiaLw@a zN#vmZng##220b5?MH~c$i3tDsw{!`P{9iVF1DH5n2oT`3)K3cBR?tQ2K4ruV=0A&C z=)$&L4s>mlY)%((C16NO$S#5rWY3#!f?bvdlI?|nu|Wa652sVMAi?cPXfNmY4NdjENr`>&szfuX~Y!Vpu+(Z9kN z&LSs>c7{?zTs9+bEBT(Jm784;+SJ9Vj1Zl8y)QlB(eC?;ia>JAf=#(4aa=!do(%QR z%GV7LLr^PG_l02S&5?G9DU5^8ay3HAJ~({VBs5o&M$Kb8qQ~&(W31<}bRihf`5Y9~ zQ1urU@dbin<1hXk*)HyaW?*eCevY=OM0fPv7>Bf)B!#LRiTZ*jBc%<#qA)yc*0-$F zcZR}wLio*(by|+2+m>?RoYla!;j0f=^8E=gn(%Q}8aIe1XFR{e7vs6w2>c zmWLp8(1ulFVlJ3Ulut*ZUtlo8fE=x+{)Z&8mdch|F|S^1a8|29fc~nF8Qpl9F;}wgp~_jdh%5`&4A{&nVDWU>K6S&)Xs{v zgY3xnJIVO&l1OKN@zOFRU5;o1tVItoqe4h1@R z6XSxzs{N!mFEPprq=Ez%IDN-HP25>i>sd}%2^1)4o@gE6uPz-KX5Ty{MK;uP3P1jj zwc`lXCi4#?o7!cRk-J)u@cB8HxQm-l@qo-bA`MM}AFhOZT=#20Uk$&tFzu?{RVnvcS+U;tmJ?343m}jBg$bM*rgg{0`{;|tg$5AJhS`w1xwM7P(%u^}mNml%A zi+ssBaxBn8T%k)~*#GVk(7^tjkFctnecSa>tS|q^=d?Zb=i;!wJZ+MRCdI)i|LuIe zwsu^F+Fknv#{^;a^_m0J3=W{#rA5%7Q|EMy!LOXljb+*THLf@KgWn2ixNE-pmJCbh zqHr7YV&*|cl*xWoD-V4nH|O(NfWgUAMYNp*V#!7+C&b2SH~zz4yiQXhH7kMHNuF_+ z7+I=uK@RLG__2OfpV9pA;$KuT4_H}+QyKp}Y}^K%!xA9`XUb~&UoyxDK&Gsm~P)RPYgt-b&M@kahP^$8fI6xjvc&L zZ_d^0d}ju{^KuS-uN1wKK5B?CjSc))A;nTI@{n$P^1=`QJJ)y~m8>DkBD2vm?+LAd zR*WO{n0an=>ftDIh);8RbuDRFK}zSEQzm_h9@ISt#Lnd?a3Um;;qp*?ynP{sWx$>T?_o!bjFeCHWOQXxeqzzva&B4?fu#G3*|fiXipn4b$b&^V#Tut)81)3 zMOzPUO@&VQb0MYGRvPk{!`4EJFyd=4D3~vi{_ltW&%i1H1VNBQkn#sb8&qc6_}0#6 zlFUKik9Mpkt*vb&SYgh)T0Bl*TK2A{Y>;Bdc)wDxaP_H>syo!G7MjB9OV>VR-xaV$1mLSyXHme*#4^<4=<;w2}Gy_@0Wy6Uu>=@ z%p-tcBq4nG7DCP>eC$~92i{>SvMYB#M~QORdr$BCy>A0!g#!NLdIL-aa4NnaS6@LK z{(PZTwNo15#f(BhQ!Sd4CSGcJ)2jAT1 zLfWX-|2^ekcPWTFm)h0u{mBC{47q?Q1Y}T15(~|s@Q6gb>{yS$$B4%H{+cX(^GH>I z9CLkbH1~VJCMLviz$qRX3?OWXN=pmknbVvcy;N3jS7X2xH~tkqfey{4hJ&?>zalvF z4%q=?SU>&iYcFprF_c1_Et`}u@xK$N6>d7S6WX8`Lf^6!Pc^IsI6C%rP^EF+15o>= z3a$an`L|**c`TFto1guOMHp&Y#-x6g!eH)4izfL*GWi<$kVEz~2zGeCY#m{1gVEaO z3OZ1RbyTJv^hOyDx(-5Rd#S0`&eouq8EUR}i`GG~ncvyT(UvM$T4<5I16@e+ague| zN4%lrhTwULATZ8#{JN05j#F==2a=FnB=lm%(xq%_TKK3Cv!Jv#o@RzB%_1wmv6lbn zyZUtCS^u`lb|z35aagX{4*h1|gA;q{t8DS29AViP1spv)njI=y`L1K#P!Du+rbO*Q z6QujRunC%3hQorAO|C7uSA`gib)XP(?OH&Y0U86o@JmHb9Ad$_umRzEz%M`HtD&H! z-)ee0TaKG6#?sCTW%--Wv;1SWm-4Pf=WvJZyIIAJl){VWJ^}ZEY3dVvU=bnD!cM0Y zg3$vLyfM5L-;i$@(sF5q0)_m7|Ke{BNhU2bf0H`0z#{-T`Z zG_Bc(9|1=R$;2;6ZTScwzj`~AgC0$z8#8rfE}0+l=r~7zw-e9?$PxnWr+x?wAfKWnSp<8)B#)CCX+@w>!!Tx9I&d_qMw~$g z6_dPuq0;;ki@WfN;jHOjI?|frzn82++-a;Dw-roimSG2BYinGlVW>nx_?w?RtqQ3(0Ro+TGHs zcBbWJ%#9nnFuW4G8dUX{_>g@j;uS16OZVUBbC?XfRTyLgewsPB!|3G3QvR55J61rF-Ne{BWUOSTmjDMSzy1LFiA74%YxlIb{{?+%kVoZ<~(%-XYl29#Zf8qt~sv26t7z8xDG~sg`gE-qOk1~|~ zt{+)2t6f z(js&dX{eeWY|T`gsXaMvb73Ey=XPBW-sUcUnRaE$T|33Xvt32sx-EaIzlFaJtk>Ay z;NUbF_xnT$pYw0{prKANNo6&{HW(&rbP~uo_WL^p*KFwQB+W^{Z+|99WC9bnQ2S%j zfauUFsm|?Av+g=Q`b}Dp^v9JY-l)6<@c6cVyt-Z0{{xp_^QdCR2azRe27Ej<`Nk6N z`@M$7e`Do1=bCd}Lx2S0KGnA8s#pY~!m>HBB_jbFcBNW)^}EtJbd;~$deavgT0a01 z^Vn5PoK4|;L^mJ@#rt$pQ-BTC&60@wrlE4MSU4Z}>B^T?F%m)lIl$!y_Z1 zwqSoz!uTCJ|MG_Uux}&8c{q#2e>-S%>xF&|PzA`8@#m)i6z;mo(@gUIz;sS(cFu=R|9Ya0kS_jEVT$_H_O8 zk{}j2=g$YW?HBkldW&n@kOvZadsX-UxTXMKPt;(OJ&lX~wvK;Z7W$N?6Yi}4>;DsL zsKky>q*LO;nYy}+nNA2Y-AQ%b70#E=dXjjwjS=H;Xp5ytc5`^CKRaQg#W6nzf77oHw3Eg-ETuzjP@FaNlj zBU+#AZy&1($9cRsRy4XU@LgfV{_RmF)Juw?#oO*JN`_x6|GrbYR>8mRE&sN1OoHU_-jO$E%}V$w4#%IGMJ zAG;3x{u5ca;?dkN_7h0><1!7Q{7~O1ZiIO4@B{OIlniDeBdpWHlX666L|h?M5*Mun zpI$I`$2GwMj4PYrrEGI3u#ZfmbFDqkW0%w0YeUcFJGQgX+7AT2(&Y<2nwSSxf%Bsk zhLUH+q(MFM$dE^qoa@RT3GS6j2r-a@DeW#Xo6DVdK$`9>WlvA@laMzB}LlYZ6w5guc&CEM69!?~`2z ziG*5U>$X#AAa>;YUVn$0Uyh6c`e~kURYbsiO1AJVz&ZO2inNE`xuPT%9<9rEFm6jROFTA%6Xepk$?bC17Tp; zWT`{D#714RN2}p>@Ga`|YuG(siJYhs4)pFV5H0E2p;4P}wVJ?#9Jl*q3k-Ms741+^dct13o3$N!6KUya8r=q0xb+iA)+7ru0VY#v*yyL(H zOH>rgtwK*S5hTZfHLOP3ByZPRplL&Zb)i=WmjRrC zhm9um^0*~ELdr7Alg2l%w1=l<;3-yGzJ|0}ch2r)m0b%ZrQSEe#F%E9!H8usu0W{; z8Kb5iI__beCZeH?QFy*k38LMoRY0@yW9NG-XLM(hiz|9*CQAH1ix&8PmyKUb@`*1S z@)jv|_Mwvm6aQAtwF7z5`RkZu*a8*e=JziyRNs+DnM|94*QV|3GgR!k0Lb}a%+NY) zV_bo710qdVPipf0bbIoYGHJ?@_4Ca@;qD+EMh#GhkIKMU*-F4@Ff}K!d7lOxNE;nV z5yEK}=g{SuK zra@ zH9?ihOe#5{?C7QVD4xpV=n&4dLr&J(joZ)gbD`CGtL1jPJ5Z)0Naup>Eve@S{p}>a z&(P7=>Ra^0v=v|xbhG>fi!mF(j!`S|(u(gp46VB~;YMYwQi|xY z&QZx4!+>VpE z>URJK=d%a61ds&3?zq|Fd~9BBzY~oyAkCsYW>^Q}$zXc18%#XT9(%WI}Z6`0x6`+*Ort?Y?C z(xZE|UiIvb%zMi8;qo^!1Scmyn7}!2uXJDrA~jrxQ)PXM`BJ(Gi+BI#$B0artu(R2 zcrU+9XT}TG35|Pn;oJIRra%-|)6Y_zEtn{Ga+czTx09zA>cV+OZ^BJe+Qa5hljNyaBrV*QvHEjiLjPTmD2v~-lTqkEJlPiqwR!<@ zzGErq0|uR-AyAvkZC1Rfr0(D<)2#gS)1x{~c*THOOQ;OS{{S;*k)%dL@y#>yI7t$}%sgyG5l9Vo&0 z;>0}bAP-#4hXbjcOXUEK&8p#A%N+Q7(sA!+tBrx40|&EzAG26nA}+_iQM9nv&1U#% zza`YV$^KeqzqR7xUf3Co9a#9@O)$C%(%glX_>qcBfD(ny#aXq)MQ{*^lKXU@Z5*oP zT;q(7e{m#T051D$?8@FS{z#Qmc>SGP^)<3{HSl*^cPEuG=(*wk?iwMcC`pl#B7rnF?># z|Goa{h1s$GnnPU;0eF9jhlz)=gy2q*hp*|#G1|wy7}Zt8)G9$yQ|G?cX|y)q6x<&I zK}?jd>&2h>*y#j~OzSlpa6orp$0V20qYeEc9}Q@*FBVhc9}jfi!A~4^>G51Hbhu!7 z9=8i2OfDeu|9Sy2vN=I~`aAu-(w%%Sy(``Led0>bDEX@2325X18;pymc~(?BXC@XD z+FG}PLN)kBW_P&!%V4U&DWvhy|6#psquNI2xtR#9;R^~t9{4n!n<4#V`yuUc(2OFE})W zY$ZOY*wGKbw^4<3pv?yxFC9qfoJA+x9KvyZ4$J0C21$v}wJuc}6&q`HL@moWGlW;X z&<5UJbZ>qD(TxLg7VTT^(GR%+J=3K)DEaJ$q0BB~qPgdjk&`XA;m1&@Y!u_Srn5#C zfuPp-<;MWULI|fQ3sgG~od?{W5p)k@0t}|yd3E49YtkD0=iZF7TqZu^doSAoB_sX3 zYlcy6V?@f1!UcyZ{nOmzrZd5Cdr+L_8Y+_HG%^k66VB~}xAS%u&N*&?{b`dV{KX(KbY zX}}6pC*-UD*@&}t+l5)@(1T^S7*AvKCw>SU(p>0!pMw7eBDyQ_?`yx%_8h)!Vghq+tG{^_GB#$`H*JuDN1Zz0Nef< z|5Jj;PrDlT8@VsKEKXnNM-foy!lmpCZvmZ7y+Fn$M`uMHF397E+Iq?lmWG#0_}*ZH z(eSollOXrbp=$21gCKR)WWDFh7n#`67lJOk{AKAO7D}%ytVn!YaH5z1^Hk(WMZ_?nG(A~@Rneo)^-{@Jd#bu6@)pBKq z0GWtPM2eQ%yjBT@(or~%x7_T3Wj*YPa;~mz6b(T${zcRsEQ&B|t2gaIjR{O?NJ`wB z&U4}QkDk6cEk`}EW`$1ew4tpAz-v2T8j9tT`01C_0_-LCu1x!3@$p)XkW67xb$X#X)@hl&;*fp}9o6-DIjoc(9ct;uyV{zOH_*Ad}JP%dPn0y`izkB^A#=6#jEW zF#%amKEBTGEbk+$QIyGm$I%?34}w;dU*w(@Kv_QI!QDn^GHClM2?$DU$UQqmJKc*R zm{Ih}x%OK@QOhZQopsr_hVjUVFo|<@sz@0Z+D?G1c-Z%!%Q_8J(I$%FZP~zZl2H%c zuf9-%oyPf=q1{(M!OjPs zJ9D%AZu%G1pw`f2WA-9{#(;c+bC``c8B_>Ptd%IGEvl6^M{3l8IIWv`@(-GZ- z(qj8|%B^E&-@`(g`$Xr8=4 zhBu~&x%{_TLL+1?K?Amoa|SN5?C8|fo{0rh7R^FisjpCOL|I+V=^hX1?9-Zg_5IN* z<)RQHiF7}+_82CfkK!9{Q^Qb_%*6+_ZFqWa)tB}Lrm61$dCfeeAL#r-L-D$5d{!t1 z{-e>Wk7gDxf-UoPoG6r6>j)f_AA4xMuyD)NN6M;I;M>K{j-LBc`5>?+Avh;|%`HCnajh5Zne$P1D%kuEyVDcKC;V}r z`H9zz>;?gq9+lI^@iw~?%KHy3UBE`?y9>DY{UWY^@wEyN9-z7&i*;x-I>-;Y;?@l9 z!hJI8WF?FBYcQAjrnM8W0a7n9{i>c^2+r*}q^PK_Je{m%{)I?Ut4Vv1mLLwyNhMl6 z7)XJ9^Eid{aoA4rM+MG)2@*7R#*&>}Zv?8J>5VeIb7L%sqCxkOzAsc7KLVJugjZe*({xk&RKf5PqbSY?FLx|bBRXl48zs_ zZZO}XD&qgEAKoOMxZ}{RYa35CkWPVW=Ho!Q8y0K} zu@Pw%PRKUL8;J0!$i2ww({CsDYM~8*J4qQ)!uE2(U#vr2Cw~;rs&O%N@ zq$D`%)^jad7+5M51txA_{=C2R8j^~FodAK3Te6o5{J6P(qEv%}Ek&lHIqq!T09EzT z{UX9_E;q|hPQsM*JvM5zp;;pY0gi&=mC-TCETL+l3pWyxDxj3Y6z3|pg-^fvVv(Xc zy4M_}e>AMeK~Wg8jLLHUBF}sarb=zO`pGG2xl!(yIlDU@4dA_BZK509ZIOJCZBEI% zzH2dzhg&9AvC^mebDs1h(2Cpl1;4gaO~8?Vyzr*e`66_{dH&+-(fzq$9X{>N$u`8Q zND$9L(tbA?FjB_iA+^W$3DTA?f7g$_yx<^`G+8KRuV9-DE4x{rRWY*Mr^CH0p5>&< zEP{1Xjs*T)0_`5nmSjm?=g+pKP9#n`UTCWeZ>bXsCyYrhUqa&q!@{?-nPd28lX5<| z>-Hi^bDj{ipdZyUC_j+&!|gTBOwwF0lQO*e*w#w0)!c$|)1jNhQuF<@-j)vpc86ji zmp{2qp;6+j$Q#@J)-l(#`dp$IR3}4R&iH;cHHqA+0aP9Cdfu&9SD-8lsI}MKCFNM` z!X?b2i6OV=7CBA7F^TO_a7I7HV+BuQqh~VA36ju=+=&#QU`mNKfmxjg@q67oHy~CL zH;7tl)B-K(^5g^qT#n;7g@cb0Tz-hY^-M#e^rEhPRVF;Q|3BCj zA0Bw0I5K?Sb#-{HtYJ=xV!xPZ$j}%lg4gQ>x>EJSlstdTdW>gkRQfOmfUN_)ENi$1 zM!%XiW$BK1~P^Ep{$?1si${U=;8TxW9Jpj$>iZ*ZTI;Qy&0NgVb2 zaoZmHL?%!y$vqfqMr$$5RhnPtudkyB&+qJ1B~x~LP%ac=d6CLJL+KX4NVWFp^5n?y5ug z?8y2dmb6Ba3J;0mAtqme zY1v1UEtu`wn<6mp+vG(yo*mmy&-twKlOK@LlGi+vINlug zQJUk&(=P7)K3nlvSGQfI7y+@w-2$4(!BMS;6+!5+X3vwoClSoXwGj8;Er1IWG#iwC z$daQk7%1Gt`)ha}S(7E*I-+3Ss>u+@Bp=sR!pp!9kC>e@!xx>^R^boCr5mQ9mS)v_ zHp*luY~9%JJOK#(jw~LtKvs5Y_P(wR7=e zB&wpNHZek1tF8w?gNzV{dKie8thQ^L6n|!hf0#m(jh~^5cyg5T3wy?WpRqB#*6sa1 z&DM1?Wkqmfw+od;*cSnnPBN`D-(FOf7X#Ezjd8pcD_&fGeRuTV z3GwprEBHCqNd~@$>F?W6DI3lnmW%j*%VmbKp$VN52ET^;HderQVK$ z%7K?+Jlz(kV-}3Jw@6n#kfsl|JsmBiWb3U`vM;NXVqChnd{{V`SKTsk7{;k+TQ0QHRvx!G9_sM$839D}c?_omw`X^2j%&UByJ z=?&7@(Zi;Q8gCU?9`!=nW3HhlFBPWagoTHA&KH5e|NdzF|08|taxeY8%jy+)e zWqva7{)}W}TD_Q>6d<5ph$=25gMywA)q8l#H@ZS-T%WVr`f zZmki%rR~jaY=e^5I!XCLtEAmMZT;C@sp1Wjc(uh>Vea05Vel|E`)z{Uj)kP1x3zVR zrT?kfMRip~z{%9_m+oTk%i#I4h9OYT*QK*4u&Q@XRem4)^p5=AIr-nX!PJe8jkppb zL~G^F=78U_n?H^FnsY#*JZc?^!zfKz9y2~bZ58#m=Cv{c&OIRSw83b8k8spTM6K(~ z;E;rXfhBFm$8hMAzIk`=8zs%!+rB33E6%opeB8eU8hz5o@d!e@m1C?E1jw8hH+dn6 zU(It@1#3VJo@qj@9b%CtYNUP{^OY_taR}Y6BjQw_WJaDpwrpm<8-1^>9N~5cJN7?< z6!?IPs8aTZ7u1hZ#{vcM1qyjpp%kzLF{65OYM6!I6=D_g`7jcYqB+hPc}NUq8o?}Zp!?H-jWy&oy)B4F#t*2V-;Huo@=%m~E#1=HR z9t*qW`}$H8$T6~VGrzR9SAI3bZ)UwcxDvLy-gl8c@CJ2H87ly!5u-8t1+pp&lbkL`!;abD&ysul2fO>S2<#O8#GSquRs< zi}k#}S~^dNV(TW*$as(@Zg&6M_zWU;iP24n5H!kx#;%$E?Mjm$2wxN9?~_|*+^TW@ zfhd2GhOh}0Q~_?{Dd1!KK7Bh5q8FKvtoxF)IQ4oLe5NW&PV8}~M+`k#*{SF6Gr05Tv_7 zQd$rYknZk~x@*WG)X}D5e$W{r5P^`xZ}~h2AVWYh0S>KYLTFE*cj!rZ(@F=ILeW`n)L=GI07OiIPN!v9WP?4ZFdlz7&D`}wrs@#8H8JQp~irwN64{UGQH z##Vd<6ftqdBNA{70hwG{8&!oR4%bvQl~DqtA-^o3`@cCxNy;#B^mRR%5ZrcOio*^u zMnv7x@S2VR9I{?fM+c|=50CG(qkT!9hXuMTF5c#&jpo7`9zAurDM@C1=5AZVNSKLa zPHz(-*OqSQcyref{PN7w=ChJ15PC+s>qJ4Hes$qLHBu9V2W)O?BFh$@W#0<$D5^^Q z!pLxws7Uvp)Dugi68^s|wpHn+PQOWOG3f}R!sw(Jf}U}7aOuJxT7m%i(HBRu%<^u- zecP9}xNy8*k0fk;$u^}*>!-^nf0}aQ;*j=ahKB}(vZSsJt7i)=IlMXky8X8h$T{`+I2aLb0UlNHi zdT>aFb;o;|i_^}jkLIhuGL#8UmKQI$zg_yMVI;YxbqSS@y*WJauD66QX-^iNir9hx zqVKz+DwjUidP0atugB8c*J0Dk3c+M;(>=%4%_R2Mc(M0Q zJ%o_8D{}8_C9#;9d6Yepr4{6TNzUM`RqsPF6{f%l2PK1szyq=|=7%1I+tjSy{|c($ z*_@m|@|DfQJ?ktuLDnDn*&~b#;{_1@de@(#%KE_2^3AcJpF{+ASQPHm^5uSVRywe! z-tt@e^<{V{OKDgu72X~_LYY%74Ck4*b<4MoF6;h@xm>P&_lp=CdXCa$kbunTLs5&| z*P^xy_LIcog*)d2KaLf{?$x`(^YH#}`IYqI+U5UKxg3%A8vVD4d!3&4ft5-`zYU7q zdP+ENd!F~5$+a19`pe=(L$-1q@p9i@o7GW)|31yuF`jMD`B}?~LQooRP`WmWimoVaBRIB!W8&f9Q?j%JKc4P4Gbn7Oy z;=B-dj?k>jE-vHYX?nUaB6_lU(uqL(G19=iyUyOoTt805Xr&6d`W*|a*oJ*EWAHM< zVw~vi=N{iWX!&48nb+H~cwBA$O9oSmHBvep?Y@Wjc1Db=%abl3Yf4`xoi9ei4AsHf zp^Pc)S|i2y!)9h`){h-&4Cl3}>*cRIsaYBS0}|QPtO)y+A(vQ_&u6YOduY7Q%W6BI z5lnsywvA0tCzv&{%Zt_N|}!7r~TVa@bd)k{&z%enVbqo1zdfdph-h>CiwNtE0A&w2wgu2ocAO!L<7 zfBXp|?=h2l9Y&i4(R8kV9^6;n*c(mN;A)j=n1H)>eE_;b!ATAg&Q8PZCx=+O1$b#d z<7q!)*YtxqtMCu`ATpOmiq3jgen_ynr87pCC@xJy60EF;bOW{)VBrTD2pG3{$vz6u zpnofFV<%@3{SfK$yWy|z`%_K>3{e{R!NXxnx5@ni(gFQsOZRTunS~M`&(-4lG%KgC z##FKQ89?Q(ydXdCXKpGw6^bKRdqt0`|X>`-M!PV&L>qp4u_+!EEJ5dZ0|j;J|E(WT=`g7yCVG= zw{^f{-8JI3`S9@1;E+SOSOel&)cRk3<@`5_0MLxLg!N_OO^&-!ez911WhkSq_@L89 ztZ})Km!``4BzqD{b@NXgX_UQlyd zt?%Ggryz@(iO^h#Me2lP7ai|NzmyI^3yw)|y_T9Cc|*XWxZv!H4?4QbZ8Z;J%!4r1 zZ@@k=_?g+mLvwv$?a>Y#@cR0}#I=Swy3n?Jvpv&smvlu8oAPopOGZJID=%8zUnm@S z+US3HbJK_2cRR=|?>laqbx>pcKD(AQyws6ZF6}2AHYuk6oKs)m&P7Hso@YbQWs)B2 z5<*Y<7p<)uqr)o7Ty?ArWKfnALFcMLJa7X;fwgan0V@AXJ*WY@1w2+Q`9EzO>u5O) zQF3P$kLlSn z=MJ22Ams=ky~vTYRVm@{A>T{DJaiRMRC^2!%p- zvo{#Z-q0$m7s*n+uFJ?P$Lm>M01q+T zL#M3nG6FN+M$5TjU52gG4&Js9+eOW*Dk@Zk#u)YtDI#|e57sl|)R~o?N!^KeC`M@5 z3&+U~BNm7FHj%Ov=y)Icnub))MY*zm@IJ}bjLbM1QWKEAu@m2yhyW&@F#wj1qYL1G zciPG9F`nxo|0WC`ZvKFE;bO?g&PmZ_MI^adkI=#K)?V%N(#n;FkR*?D zg=`bAo}afuHX%=cEs-9=$6L1Ek+f$zTYu@7;uhC|1dXEyk2QPH1^?4skgwO;ES&fb z^4<%BHJ}(cg|WOU^?;h^Fed4b8}Ozm$R#b(IZqa)K&t-@yp&Wr=8ZoIJ{@ow=VT^7 zIY;_U>|ndUsxUw8pROD=ym|OTj^7Y@eGL_FXzP_e8#1R1v+bumEwM)pIi@4@$5b|# zE>2mXhV2d$OM7VYD0jKj`u*F|ZW%92T$K92t#~BF3%{HTBw(@E1l_RwN0;MEgdZAP zC2=+t8yx&GyouPlu2tDBH7)hsC#wkx!YCGLq)+X0Qo_rPCG(G(n=*F;-6kF}-Kpmc z|KUrN5T@itIj_Raj*M>YbE5-3BGbI(W(m8ll(VP*3D2PUvjTI5vLO`iBdhXYqQRG* zpJ)GCt!Tr_J%KS%6W6>$gb869*;tXsFV;loSa+3nbwrFOcOSrgv*gUOV#P#J$2fyW zR}?6!L>Ma;8%-{vymZdTELjKWS**>6=qfL!xR1@*<;aNyKCdJm*n9_nc*Hf{`@s9a z986|EyZ742)x}1NMOkbIVH7BHd`eFBx&P^6zm6=O0cbTbw84ADN}Lti`znR1ynV4A z?P=i@;-KjczQNu~T48vx?R2Ox;Bei>ljpLNeQrdOrcD=#yTSaK!Hj82O}~jbj(c@p z;H15&s#6w$Hm`z9hQ;v4-c9gnvnhtAD{BEu-L?X!P6$KF$=ewm64LZ`-LW5bx?$(n z?`DJxfMCIfmL-0#d^jaKrGG;Hy60&^7-q>g*7kzj*$9Jef;&P0}IIDQgshQ!iiXNWve%9XawIp-X$BcZ}x4 zclKvrB82_IL7b?(bvyS(&ZydDjQPRiFhOn#z0=Cv0J$+;hhASRd0(dNBg6j@O_1v0 zjdLI3@l~FBr;MG`wlL|j)KWi_Ze?4%$P$F6Zndt_g%ey(Higo#d|a2J&qQ|Qbq6w~ z-|iN{t*Iydwg)$;cZOFKguW;0q*QR!8a0&3UWQf@5uFVGN{K7Qv|@G|{(~9srmjps z_Nh4JANmOb;51i_1J>oTIS%WS#Iy?y;tlU;^g3DZs_rSK1sIdscIycdPb?Ho(7VO% zR&GkI9)(Tc2C%e~KZW5ReW7_Rw17K#rqN3$oIlvA&BE`>%TJR&Vdb)Y-mlpONWWNF zzl+4Yiq4At7iB%JX{i9A6CoEba0exxPA69OwfV8hVd%6G+| z+mjyZFP*OxhRMGcQoV?Btk7wd_;*$|AFrd4f*8$7%P=BwdRg$Nk9Zmgu?{rnCFQip za;Hsyy0tEGnLUkK>472!0KE)+@*c#-tBS3-dUfd2=Zhq#nkWaO!6kX6yzws^q)e2a zYTwvr(MX6-;bZS307JuaO1%F+y2Tnps??vaX`b9^)|eWk3PJ^l*ot-w!-3_d z$X#Z*KkFu}s79|Hh`AJXYSKu+2IrV)CbouWtZl zoz%kCfrE3uHS_}sHEmv(_^D%p*1}A9ab5(sU*1S>N=ngVp+=>;I5b)QXMhi9`K$Hn zH9ngSAvYwDfawBGl%Nw1f2|i_;iOlT$eA(_$h_DtA{1-e5Z4E+IF{x z!!Lz2rw}nmifHG}aKpyzjIM}4aZmgSuU6o+&Vm>*V2FJyI$DR$`?D2N;g zN;-Jfto~<3MOsI`-P5w8ks}F_wG0{bVfQoWo-~On`WtQJBtcKx{npJ}558DT|LtOr~ zEG9n%hf-pYi$~T9AvN!zzKnJSsj6(aZ@!?uCAf~8_`cF}s5{m(g z`hw~=*s5!r3`^aqw$$yC?(Dm&w8DZ7u1u{cez&(st499|l8o{zr=Q;Bb=Br;sfAhmF-mOGEos~78#RH4zw2WI^aeO4n=Tfw6< zm7VUQ;Jvt8SxL%PZX$StrH*S2542S#N!Keo@p6t4=)G6EJD6rF;V7C3+OqccLVck8 zkmRZqucuS+E`Qn>w*34N48=ld_uc!CeJ?nceI!~ukt`z zS-_h&AjOw?7Ji1XriMIXhrFBHh+(>24hv6bp4!ST7v(oA?0eQ;dyf>7ZO5W*!k3x69q)_zn}) zJr@p_ieIn2bKOp4m0_? zyd*n8ryrrz5GyVKU0qdStUc}fjZP=o!g9yA-FGA&mOvn*FkSNR`0HR4?C}o~dVEo+ zlFE2Za#cYemk<*aM9HzDbBFAfk60*W{ayHe{0Sk}=7{p2bE5 zo~lun-WmXQB%&9Da!ajn9Xh|1&(z@uP1wKk^T72 z3kq0ge>DGU(0OJ|eHwjEIFYi3ki0-wMv;yNg)lA)3|cuT&=wDs`eTu@PhGNX=V(qY zn3x$SO;uAxiZY&;F&!CekBl<7%fYQ${I8A!=2bRC!{@s2(^!vmA#i;NBB3s_gT|5H zF!}vMqvi4)5Qj`qzwC~;gNhcKjx*Yfd)+6)6N5O^89rX?>X?1}5dNbCF_!Mk4d&7_V_hT6-cW7;qdMyucvO!)WS?9uQ zm~&1roDOF3Gkp*pbXnr5RW@xnXTX+(@uA*%({-zA!w;d+jhCJFTDiSy4RiXud!fzN zQ;;7+eot~9A~YaI;U0qLFSABkhuHlISoiZuTwjdC@z(ZkZGNO;unpCIbW)A6>*0}s z^P6lHV={znPsB9(-B`6rUF^OpKlw}oHT{Obo_HkY2+?(AICZv{oKJ78wSw7tB!3Cx z!j@D(e@O7!D$eXzYTC%E_g+GMm68&@x<5&&(kDNcq#QX^YuC+heIo#r#fm!st@x3U zV+r~0`3!UJyr=4(1iwj1ral` zX=gMqU~H3^*nfv>lBpvcK12eXomY-|PZ~&PF@!?ksmsH)3>3JqQRqVmO0b#Valbxj z#mdTclM;O6`5XOMgk9xw&~>|QJMt!w_at*DGFqJ6j|u53U1N}|CSz?jGyNQz=y-l( zn4y!vFul92S6#sL;|{C1IzOjOntom^qD_iLRASjX66uS6B@(;nS1}ZT6s31Pr^UkB z9$!G$d{PcSQX)ziai@E8&Ch>8o@e(GE^^5vky;WS11y@ z360s`UP%vcNX{J{lFdIcq+(_-YEPlV!J~RY6&M=+xckh1cB(GQ0#_RtnAR7=7vGWno`i zW5`^KTK~&zpZ~^`CVgVfiL^d4PQVqx%(I;&?Yumz!lk~EszIkwkXpU8Ly)F;E3aU+ zC`nrI#;?jIVdBq=I|3@^RqAGSYv)r?I@9N0vWIJB}NXE|UaZSi&dKcWNS?}+ClpA}#!)3tM`0+1(X3Co{5gOdCiw%e* zNZU0kVtwgoZjCG&B&M2P4NvIbKK9}_Aftv|@&K`-aThoNgG_zJkTjg{ZH9fXkG68E z=Db0&N6Tk7f7Fb*RbqJ4w(r!;+8ca`j!lhH2f|h*raK-=s8UWPjh$?GATfogBa}hq zfxCu`8(F|pi00>Ml`SJNtBk)R`^XaJMwPu4PU$bI9)El1j%Y}K{GhsPs;xMuLzCA@ z=-I6wp06dIUsf+lslV5~z_61CD|rqFIN;f~qbv{1pg3p$w+HoWE^Sp;38tnMoe1zm z0|iZk?n9rl)P3}^ob}%mA%~#;$jlE?uo&)oo&THrS+99s8xAf&|1>tvOj|!j6dP7*_n7yPaq0yz$E4sdtvUA9oL^$W%(`DO)Iag)NZ4OA z*#PDrZZHFR#NNz|#raP(0tb(YPLPPlYTyQ6-y60^gy!7mhXXLRm%@5!$On>a-99gJKLLQ;RD_ZQmGDc z;p&I8_3hNFIS%NlH^}IP)o{V_)jW9412_y%Nv|#VKC|p_n3f4pL%%j@Nbolh6;d}R zFrCGuhk(`C2cBgPc)@zUpX610c8VE#mw{Hk+tbH79Px{CLkrR2#shxF&WhVp*Lg6C z!8+x+N^%2q<>pM_9|AbV`d41Fyax6^(A7wA0|m$l=C>KHcVbsAI@A8&Gp!Twz7VM{ zB0nj|?4`Oi`~XiJgeYi$!{qgA0EK&8f_F5oOOi`P*Tq6UcBl9=wTGE9QTYN|JzQR++MpkMHK>i7F5U1)K=^#EVHcy`n@3sCs$!@jIq^G*m@WQ8P)oyT# zEX0C_>%3PjllKB~Rucnp3%G=*Ty!|)IM;kA_y1o`RQ3%N#2grA5C9xy!BKuc^y<4)NtJ6xa#Zw_FbCzr{bN&&5I5tS~jSZio z&rnXq;=e%pzCN<%Yn5LgQI5T{S=*u~5JT!y|8a9baz|_do|ck3>kk{ZhHKSZ5N4tI zWG&y(=IO-pxmeCU`z_K)^HUTzx>cE$yp3V_gui27!+hDlp8vO6Dgr(C9Kba3z{Sf= zWrPF_vO&lVrfx8D{aNI^Jb|QYPwJA2-L|E$UXKiosvf`2@|1Dxy2vjkC{1oj`utfZ zgmsY~qYP-4Wtr1P-EH4{8hr3^e7PbHkQ2Rm&A2bOyh6%-Y#DgM>l~)NHB{Qnb~GZH zSBaYTMR;dz9n)y#k|dNXZ#o7Z;e$?kdhGa`em#hbZ|OkpRSLCb zdYoEjVnk$*9FX1E7Q7WlwL;ta3u+U!%eSZvI05{}%`Y;rlUPnr!>okXuBMu`ZLfw# zI3rGto+y^Pt$H;f9nZrfOY)KRe)r-r#AV~|IRA^7FK6p5tDGS9OFCKYZ#+s9?z)K)~ zgoLO)ilkXK<69D)fS7O#!eY%&OyTl?Zg`bLY=Q#tGieM*2W-d$0c&TWe_q5E9DQrr zntC^q)qEBS{qg#57r*g0Le>0_`!QVXa%nLR5^5H$k;h~*7fdBgv0TFD;NHoVTb^2i ze_?xOfzK%C`n}I~8G6f5(*Jsj4$mJpWbNz;TJ@%?^GcHEV!~?7I{zh!_yDRRhR2-s zmOqY{-J+MZB0 z)bO6RtcM>~&M25felcJbpIQ5_qInHPOLxM^?%(ZT!zo21?{jw^kJug;!ZWzF9$B!^ zX_>8@jA<>;$`}cxRQATB04UqDesFs~D!lv29xv6|PA~?mL}=@a@0MarTWJ>dGzn0_ z5yH@p`moPp%$);5pJ+ z9LkgGcg$uW|Gn1*J1$-k1o|prgWlQy8F{W@`=BW5ry-yoLIG@^RryLNv)W_Ry^W-( zq;Xq5GIpSOOp~R`)=EjEpz)WfVevBs&YAeGIvd_Pz`k8Yh8D6`c&PPDxTC2)0|Qna zT5Zp=*`%N&;!H4P;?|9IuRu-(;PWk4Q8*HlyTPO+L#3}LkD0<8EwK_bAl`Adbhn(* zxz=fwh{>8z1+MxJYg+TDh?Xa#2DE;0IOKhaUZ6UG%B6nvC*Ew7o_hOzHfGOfrLe{C zK7f=FS9>-6+gJ(zlg8~AY>fI$|IgHV<|zjo?F(Axn2r(#$VfJ=DGnAcWvMTl&=ot< z;0dgRRxioAj`Q88{}W6pnOI_k;~Wg#dVHJ&!EV4~TbiAiF;!8DV)P>G&pEi>fJ^%3 zdyQHAhHMG^dgK+(moL6VQnoF2R>i}S^~=|%g?gTujZX3oUq89W%5diUK4|j#H~N7N zEN*?;_C1&X&h;DNptj{}K_R5LVn^*xf{w`jo&pbMaNJMK-~Vh~2-nSn3nh8<(Bwk{ zDsO<-K`YHkj-eM`e#a@j#V^g3;UI`K%-Rh>`7MX}PNn_e@THlsX6Z zD%S4|3BE&6#nuECy$>GmW}~~u+cQbpgB$H{<+t+H&b$8SA|QFcJ9)tKKdBA;=yCXp zk>x-`Ui-+js&G)Ci^(2PQ8J>1a{h6w2ROLB-Wzl^yh*3{6g=*2vc~8cC3}-D^+~!m z%i%K`YqQIvX?m!OqF4$8YQS9SnH#kd6n=iL^6XfQjy?ZCYR&PIKQzQ^8T0TPQkku` z5YF$1EB0E#A;by?zY-P8y+)M8;yDu!i&L=NMOOy;tkQ`0w*iW03sKM3iQCjqWc;oXzff#vgi*dnq4VTyY6*4mh2X!*K54n;B&d7JP05At( zbwu+^7}9T9`9PBQ4XALD;p6=v|DH zXZ}tnmJvH(sUt&5rbjFN4BK+Ujs7P?;EPZj! z&yPXRbgN4=S?e8%>ZCj-_CY)46*av=?_?B#zFO=NH`kwg(7&QBs?#oKakU_J{k!Yp zOs*{Rq--Noe$lF)XZ!$!%5vN&dnNrxH!Y@@o{L_h4{pb62opD=0iCbuWs%$y_v;N9 z(#MV5$dj~JGO1(@jNeqXmf2|uE45N7WzCgdz7lIMYDJt`aT8*}X01$RNn830L?0^j zBbuzEmjpCxB#0Jq=0@^jJWOs@EA}d|3Ez^Q*u!$e>WZj5E&;>$XGyP^<6AejHOwv8 zX)s{dw!!gCcqIbs&JL#rA7!s2+ErZL7|XQJLs&RzTG1cYJg+`@ZfW+Cck^?6w#@H{XCx*-gWy z5JW*CBOv4IYooD+GnCk{?Lb#og#AqR6=y5*1uKkIPi!%7IXt|A1J{~c`kL=k=bA36 z%O$0QEmloHjdab*N5y(K$8xMJi^2}=)HtK5Z+#|VK(d>0Q)Kq?qO9Et30{|*eCM(b zlmGw0;y9c0E;q7Kgst=F+^oC53ptj_bw=^hj4ueYro-#QHJ#JvjovS0uVvCKV{ZCG z1qXYSwCAyl%U|;2@*(FBvhR(vXQYpv6lYi__>4|L7t4-{xeX6q7Pdz3o7WDy$;Bl? zMFHPFcN(3_%PK6eSISxQEs9xl=!wqz1Nvr9i^UuthqG6RL)P$-G&M;-Y^T`YrtM_~ zYW*@HaSL+t-77Ybkg3?L+H0sHW$Dz)!hCz{={oAL?x353sL5LIUwY#$&Qb0zc~JNOn`;J2^jpDwe^Rv?6G zAZ32s0@t~Vh0Qb=agh2LvZ&^Meo^Ld_G2vmzIN9-jqdaw^~N` zg!erlDEJHodJ9;?j9BCTclt1CdkF!LKGb9N`Lhu0rL;!b5yJex+^=9}hiyGRXF$|YMl_TB-S1$-h^ZLzDcyhr_m%|oGCafKTSaM`;r!G0|GG`` zwX>=Dn?3-dO1!G2hYe%0mqwZJMi&B`(v&76bnQ+CIFnN2Xb-eFZsc)A+0a|0;f;sp zi#n$#eb9Qq4K+;Ql;fq>=$k5?kjBZy$R}U#47|&i4Kqq?EkHBK+pg37)2CQcipfHw z%TUl>xHu}_r6*i*B7g*cY1@+xt_5{N%P$_w??-^H1xVshMd^|D?Q(Wc0FsciG|ux+ zBffwBu8?R-ZtmeqnA{H;dgIoJQwhhq+T{VrZ+Q+wwL2H=i#v>pK5?97GquvACIn}8 zY+E0Lr3O4ffFC}wny|~YUP70KiZU!UCUJ#D0KxnpFxnxPQT%pWRIqkr;@2s1F{+ zKCL-9N591#4&XmFr&V_pVNb}T`XZpw@$=Kl9o7k>Bkyj?a4aDUoNHCjwXt-kaMkFH z5~I2K(xQEhDQU8AMgil&VpN;AFc*B%Bk8t1-Zj>)F2aWCOE;?i56^(MOQCD)9r z3K#okZ=fKTZJUkT266f}L|Se0#mN8SqHzP74=h6SVOtF;d!Gd+V3WW@i$4CNpKpCAReGmXlJ8;tp8KW zOBtw$+t#*)p$|t<-QsFXu32u$#YwL8^tImtCVz8u%8A_%BQi%OB!@fkmybt$_|U7i zTJIF5nwzl6N{wgy%?HiL;t$>P<|o{PYkJXs6I41H^+3CVR%fFP#w2~L-|b1K)X;ZA z$*N|2j`Y-o zV8KgxbaO*I;$WqEhINdQBot12hOeg5n1>Cw8mDofW6-Mtljd=h<-M^?*Z0vbP>jGGmKAD=>%EFNV}!i>B$@JQBx1+i zCSB6)AkpuQLXyToG%{{(Jx)v^DBE2GPz?8>CER$!QZ@udk4Tr4@7J?^EVM8Hs(#-*{KnYf=NQsP|Ha|u76f9@o{By6)1T70SxdL}>h zdRfF-f<5U#H3ZW--lJ=rsuSR3=lJc~y+IcFwF|eroDO~_eKv#iZ&~|3e=m6i0)P1S zwsSzXIjT2c5B@3s2MfTBk?$5S-&)!t8ZC9%;=$9ylfDnWdaBfe0K(6c2kW^7A-DyL zd_>%^>~P3--=h8ycG;1yi*y;kXjP%eHAUdJT+5unjj$*iSo+>Q%^rn1Ma;9Q*Zi+h zg!y095w+`##=FF_#y!87X6*WaVv6b-)fZnp{V!WJ??OM|Lc#?VFSY&5T|&F{wKgb) z#eT4z@CdaW-DokT4+sx3-T28JN&b@Ra6(3wvzMOg;$I69hI5v7)fTP9a8J17ak`fy zjIC5G-gt}oI_mG_g1L?!)KL21c!)5J2d(40Mb%Q4CKQI z+#}qsAD|q}?QN7?Zr86E9liL{k^M8xKiJJ8-iS6IVzDf#%AIc5cb}yyQtT=em8t4& z{HEa*v(`NP5-|AjQ}PU4+oMl-)U;|aZ8GU{>P?jNM7OorhjL@h8DbhS_&W~BcOyH{ zncB>h5*U$;TqoW5&II^uH*w@Xm!8wJ9i$N>vjWTPT*H6wEj z@_qRNJWar4?<)bYQ;pH(p2R`1DyNEyKtWZb(-DXIwm|dy$J}<6D)+Bj+2=G*w z@^q@v-rKcGnPP+Zl^I2BllbS$c;hqVeLN?@KxJibp;pA>UZwMe@P+= zor0%Dw}r0!8U$-uQPR~6oKpuMJu(cyleei7H$~jqgwhL~F{=ni;^^~;9jQo}xj+kxYaMi`h0cFiP_+4w{U_sU=0 zG*Vr1ySTzQP2j;1BVeYMXp@pq7xX}WSDT?xtOXFbfq!#6n}VSe5MeM=$I*&-mk5N_ z!PaMK77#E3#n;!w61utqj9i01+1QY?AmN;=-vRi^EJK=%FS#jC)%8l|2 z`W*fNjjr+z!~2oKfaPCrox|shS5+87Sy4F)Xg`W+S^lkjR8RE(_G@Yjsj@o`l%WUY zBkQTkTeLGyZD`@V*F81rVP4EoG6|ZVB(W|o@01P<+7B`^iQ?KA-xoQ+##XT8R#&7T zwO5q(Hh?pZm5eEj>L-)PyPH~&y4d*^v9J!~_B8q`Gw!RK0ND6B=fvV zRKS6be?269<4SE=2k4uCl;VHXoH?^80Nv8v*>+!$KKcFxrBvNSA9q?AgF=`4*PXGq znL;qJs`ANm(LKe^>5CBP_e%R|{EJ&^gi;L0(qf3pSqlSG`9wpqWTH)+10lF86Q ztx?Lo0+s9nE!jlP!5OOlCh|^2Swav_DqA^)6(*)_!6-b*rgR7+YH%S@bXEB}1$(j7#>a#L_YPg736}Mny%<2jLuc3kX1|z`?My?5d52 zV%Q&uL@Y=VBwkw|4@+Qmy7KM5V9V?rct#D`%GKc?AZjoxe1Y9L8QH^L4g#Vf$wt>_ z_pz zU&RPWTS+RWhxVh0xnP0#&FLLkihJhBty-ynJXfrVvr2+h^zr!v`~H$vjLJjKYx@w5 z?(H!jfy93k)}B~AGXW!~il6|SyX zb&M{Kqn8hlz&(QyGaK*jzcRw0cvGOv#g0Lx>;I{4QTJR{dp4%c$&)ky>+kNOjMNQ7 z3|Y#-M{nwX661Q|Vwl6^(~WiI1VrX>ezB+0&C#xj-y82qd>imI4$~#n0dy;Jx&mu(ssWzmp>dGZgC)3zx+xy~O&gRf8-AR_{n^x;frvWI z!FS8-jz2*v?7}cAmCvFtOs5Qn0q~y9tn+}G(|Rxiei7Fuh%{GY)k4c*F9l> zM|N>~a^d3zisxX{4f|tAxtJ)do#xcx_%kRghrr>@?nM`?QcR6MS%faThC1nx9Ks2L zl3j`~4D9iy@a|h-yLjv-ui|w=^h@Vh*yxi&N6!*_+kC^5X5kS=HB4KysvO9YzMGjb z%5>C6!wzp8QJbI$JH=gj-ggSH2KRc+P?jLVdF4NgR0bvl$Y4IVL!02x*^)F)o5^m% z0Ibd=rczfuAF7yZ7KY+UDiZAC-v}uEG~QRuN1KIP2yNI2?O*@7d}_>7ai zrk}=wH6Cfw_@LDUOwoKvKA%myc&4{?Qa5{=YyQ5}l*66v4+}kX9iW%&#y1dF?)>^b zKKDidy{&h*=`1LjqE?oi0bLCY$M-k;8qj9iA;inETO#^F6s!%I!;t3^C7Ry}`Fj!5#Ifkei!M8DZFU-o;L(Q}`~ zOu$3sW7t`1$JGVaKyzuS4HI(Ijn2KL4UQBN+0i`d-`{7uY~D*h>QWt=zM&kd0KVm$ zt`Fg_roD&ijfnj1iKo^lco?qRcAMkAf-HH1mAdfABaSwY-}OUXjX%L zRlEvbcSY204t8J_oQI{B?sOj#;GvpQ6{e^$fe}|mLkQ>hK65dc5Oh@crR92*D2l+n z?BfLYvs^mGDrewQ@W(vd0&;qT%Oo_{vI=~{gZe1X+N+%_{69FxhWFyM>Uc{;Xa%x& zv^iC&9^ZDnODi(0d|;D*xw_-~Sv!5W_KmT2VmpJy&FEMRn^Uy>_^yN+fx||!Q(?;t z*(;jV?>3n$Mh+8-rgdp)X}_~Ti5F0$Kd|A-Cpqw$#B=by833JN6MLRTV8z&!J@FzM zFCniayM~~+0uoPP`v)Aqm4`(g|0Nwiq8>Zj=RxK(5qljUik3VIPxp7C<1HO9O0(Ls z1Qxhnru$#2ce5NzH*nT~D0a@M|D{Rr^7gsdsee}4bA#CLF2|<))(hujs|SkvixIBe zj#Lh+zEbK&gN9wBAtJr&Tl9Z3gl5gSIaE)&L<*Ocbslg>d&1xj;dG0bAAl`KLkBz6 zwz|_bhea!+n8^R#Wnx0-9%^J|rj%Yj*XO!abr!NC8sokv1K{uf4n9t%erR}3gq%I? z9MmFiXV&J@c+O>u@(8X)>o7Byd4eKpe(xZ<4lXLH_Z7}jcnqVVkR79Yp^@YO<42$p zoolEA50#+1T$#@~T4Hmgv7`$Ee{)QG#pG|q#UA?5Yr*O!5`2j$3!WlZK;U@=K2hJm z@7^4k1*@n4DoI&zkXY#Qh6!v4cDu23@jMYQ2wlj2jAYFZ&s;r@vv_-{WcKvD=YK8o zdY0dBSi`0pp>kl9j(cK&AJNwKxdbhc?TmIb)woB8XiMMn)ZVl1Ey|nyhm!i2F6HwF z4K)cnr#4Tu6{-{n78Hr3W}zhaml(z8Ca?P~``7t1X3eIp?N)Ia9q`~tON-L}?Y6u) zr7iLr1nGBqu2mog=JC%?`8z$-Xres^v37(nBN@NP*Uis#KdqK+>&U$ktpDEr?7?ig zt+pckt|3axQ044>feBL(!|S9HM|n!PCUUmR7HJpu8p(P$Ugy#d$<8<9DFWy@%0;ay z9dw;Qip0Hg&jd{$t*7yk@$`WMMV(HxcDaS^xkp<>;+K-8)SpSPG3>(*-xY~1*J!3jMz;KxMMs1oBDr_zJeW^OkFMnS+10l1cxIFWOifsUyqV~OJ^~@6fU!$VEmtT0UORc#$kXfbRIw~9- z;6wkg){4Q2f)m)@Tn}D7qC6GNVn1-KXy2(TeY1m|1-!Pb>3G^k*G&GuNz^?P6H2nSyqM#fi@LN-Y(c5 zCg=VY^UD!Pf8`4qSf>Nxd*%ci2JO|FgG!I+i?_)!yUUMlK2tWh2nrZ?44G|ypdr|i z25=H9FgnTD^#TTHg9Q_H^uGc`hdVsM$WPSWi2mP?h!D;QtkPT8t+ntHCCx zms80o3JxQOlNXWl_xj<$1b4w=bThoobvM6m95tkL-89i*_kL;)Wg^~wOK&HC0b^W% z_p|=iipU$f8pxS_P|I*7Vxb*XU!U)ekOWouqC3ieZKuM+1CKM6hUr_IX$)gMwe|_^ z3hetq1v^t)WGH+2+?`diAwi9eP-GT5!M(7!wmSHZCtQ?t{sEAzb5|3~{9yNHwO8$Q zM|xvupj3N)^~3h|<@2VFNYOX)XfO7h}62Dv-i32$2BV6 zN2#c&WaEehy~O%IT-3idB#=+9>$(fFf`MUo`20rjf|Rn0;h-a@M{aP3)04-2Y(P)r zqJFU*KOY2^1JpRfx#r6z`7FBRA~^R1$R%L-4gEiwzQV7n=KK2IOLs_jD&5@;f^;_s zNO$KUB&1QgkuFK;25AB5Zn)Cj_2TpWz572n=QA^V?X}jd5r*#vxop2dv-`9y&~fLp zr>-{hnpk$ty#?9E!feuL3=^k48#3c)ctEP3;>FsCj|gv&v`@o--e)tm5P}eef2En~ z4GX)4DKKoC9_d0}R9O?^#G1sAoiK$DVj9;S`%;4nyB%M|6xQ}0n7~5C_ROsH^;Y@g zorK_^P7&m-GoDx}njk$9uzd82TpIJ0VT{Jt^}AibJ=5D{SLI!PeU4rTp~%;s6GKPi zz)yq9aXpkI4~yXr<&!#UQ_g>O`88xs-oh z;}XD8*Tj5WWSbn+JXG7xp2K2KA6R_-oxz)JpW+BKt>9b!Z6O(Ys(gj~7uS2K)IJ~| z+g?Asq3Ty^L%O{dYJ4L4XG^=N^66y)|O#f2^?j;P~3k9`}$= zf%T=1rGQ@EXW{Gdr$O=n!-o`L=4O8GDKqDV&~Go%_WXHgEc%#4=J$0`A zuY)R%8xER<6i0#Vo$|A0co!qs=V75SffG2op0%hJTlW1X!~DIvqJJZh76E3iGR6!I z2rq}BqkAKgeE}`3FVEdC1vYpt#{Or7|lN)zzn7@O>c9fatSf zC$#QUe(7HEyR!}Ji{SP{-PBnKMNDK`!V0OkVTK+{xMedKptLq-hxfW@i*-Rsy>OUB zgWhds1=(k^Q$&-ZQ*4_SRZ$TlZF&-McO5Z}hXj_iu`~xCpO(uIHZq#*hDK47TaX-L z>pB#lw`c}G&*}`~RiEDfvABH%Zu+!`CntF;F<|dP60CKh!wPr9;MNGCT%yADBif^$ zmDpE$lQU9#a|7XbOT&**2=iC9kL}pVRgm^FiUJPsq6?;6+wsNKyQ!b=HL>D(Hsclv zariK^Q_fKp(D1jnSyr1A1C*oAXol>9|Y=}`m$OwC< z{}0Tk>0DW8N6=H$2`#|Fc2`hH>>O^m^H8Snj8q5Fu8Qrwex|wY;ef7#@obv>?X|$3 zrkcd+lQ;plAzUnjM1BHjf!?NTWv7MW!BpRdwfx`qy)-BgUe<8jtF7f(m60X! z1U6i;^8VNX`J;4;JR7#&rbJiFz7nDs#WYI#43ZLp1g~VlV`gT8qntJ{qhIZxqS}z{ z(OD$-Un;W=(j`NZ3C8V32-gWaNF+HAzvrL3DA#2bLulh@1k>cTj$5o2K9sR!N)`VPS{M} z&c);`aC?OY6iwJR0^XoOB@%^T?#E-@Wx}=>A3aheIe;D{D_V~wzzB40un9^eJu*~+j1j#}aAjD^E}mnU6SS1BRb6 z=$2?c#beiWOVnLQ>8r!O<4X9jOBHZA7xvCI5YbL67fsB;ZL#gLJ+LHSII-~q;}ZI$ z*>#;LeBsA}yIVtnm03l`hz;E>6@Gl(3YVIfN}_y*6YXzlER9)|Vi(EcdsGU7jTwN; zqH#C=_~Iu--Gk!8q?fjSl>0P438;*d$Dk`pU?ucYH9Mw(^cCYMDv~oAg4^DK4Gh7Z zJ}hsV#U?-9`dbK!fwQ$ymSoofJ-%wSScBY{m;GRko71dk>}7m1dES$=pZFrDLr+?w z759ow{yX2QA2gvQ$<667%YygoctF6DufK6DG}5MP=Q8cyIbgMHRQcS#h4xiej+GMq z4r*{|w?gny-g^)3&vRizb(zBEJKy)$OwMqzR6O2Ug=d62gtw|pu-T8QtJvk{4m>wi ze=bd;xm9Jxl+uyR90)=BZT>U8tEvs&LOs&#+suNKI<1Z57$(OiV*|W_6)=x|xPJF0 zjUZ=V07{EyU<8%)wPFiR9@TEvZcV7w+W&QN{T_(B`(xch>MA`|%dhm`uTb=SMMdYL z%)&904Hy%JR&y+dqC3#PqG;_R!~Wd&&@Ku47nPfHil%+-a{^IV1EkOB=AmTX8|eMV z%89idLwOo6n76wgO=5sBZo)&=Me|JOU&hA*j%)SBA>Z>vo~X(-h!@&8y0lr}#7*NxCF~mn9+UiqVF`d>H9F4w-KxL}g z?6ab~&eMmRpNiwoTO5oI&=binmze~0EY1k6Q*s|A5a&fyEkKKjd1c+xHeJer!EjMM zWO2ovI6f~@14lZMqcG?4>9a@f6K(^IRb5ODHuMV!7|kD;RsNWBD0`l0a5G za*^?ChENnQko^p~(3K~o`K*}@HRsEbZ>E-i_k8$mXN$HnR~w{iBUV*cnOAP<1*FU^ zhb=PP^ura<1X>4z!fWpS{_L1L(Dv8n*A!Lw@yFF`zw`V)4>X!&z)Idw)cVi*@%~Qa z`ok2fSY}md@BoIk%JN2^CWCQz#SWA?>ovwn(%VZ`|8(;%dUjEDXpqVmtx@JBJOI6X zrJ}Ww=sQlG8tF@H=ZcqnL8U;^6r)B1d#mBT@-g6R5aB(swjQE&W@|i&G14%oCvaMK zs0<%$Mqz4RvaU1EbA|_fJMA1w;%=1j-&c#E6Im`@S;K(OiYV>_klHZ(Q%iv!znQ9m z>mLLa=o`LRVNo4FZmY@%1~^WZ1@7O5Q@q!pTPHZ`LU}b_)@w0u2U%o zfDs(o;}dzP9?d^Y%4|xw*)1mh8TU_8dT zx@!0DfKvI8>LEw9$%FgOV1wq$ce^5oi@ME42-amDJSMuHdvD9t-}{+ok3n(-2K4T4 z+d%|)W*ikiTrQ^VUF5`xvymzbcKGN3XFH5vPi}W6?F31V#fRynQpD2kB-t0xoi^~P zUXF9|3orM-@~6Q$flH4ySmZz|n3Dfhg08`3J}?Jzpg6n$kK&8{AlkKw-^!Z)DU?#_ zF8kaJn@0{w)FN3?7B8;xqbsRqPL2*4wFy-pAjvFc|ah zLSXr7RfPnEPB>{EN$#-){MIJVdxLz!t7bYJ(Z%op{8a7iHAYuRWsa7T=B&Grwn^uz zAeIl zfph4H()T9NUs(}!5Bu^SKZ6Cq(LdLZ)#9B*p6szFXRR~8PtpmUFx7VMod4$kYiy-^ zvu==_gH~XE&!%44TB9EX(Ph$YH0u* zTsh1@mwUdQ;z!5lv|m143rjd`Th5z3=qZ@eN-%Q&2$}EM7b4%|`>-0oj=t5NXz7lw zu%ewN&{-Ep$w4>X%Vv+VCd(X^Fbn2h33}bQviI@r^IeDcc}BAjT^OtrdxFCk@^J=d zv{#WX-c?5!XWm?x9xZu|Yj8u<`9MlV+h)C%TJ5{H`%R)&7oKKeMcrd82IuaRh8qUpk-8wj=X)9y zz{gJE1uO(LG7bN&o&-E?ct05;u}9F2R+FA21C>u9h1R0 z{u+n#g}9$&yEArpF1>EM!oTU?NqsCwEcWY{>hT-Uw>2Y~w}y-B9#zq*dj|~PTfhh9 z>)k_$r-h!u=-M<}%^;xu>ftR6{1thVwznwwS-$wXfw(o(tgLFcb%!9X2A;S}k7fSRgzNkN7BjpXXhBel;TO^*@bRR7soS`gi5HPz zq*=01zj<_tqj?42N@IdI!ysow818a(+4M6Q5Bzb&UwQxtXNP){ox_LS`S`=(_#whS zKRVd-_m4ur>sFad$Qbn0$&K!*vK z_Gu5C1JcQW?X#{Et&{e^z<0{pevTJHX`cvhD^`amgzYRqm4zCj0MO5%y%Kw)A@q3XV^2dC9IlloT<9<_KC9F!DYhTb)GJ&~jO^l$BCY9cps3OG9gF zE$m6q@XurGB%?mGwGay)j(C+PiF_7bhG(;;zwws$OY|?;=Jbk+s*{{O9-9g<}PC0C36;TeLi_3vKrO|1I*C}9n6#_3+Bajj!$Vi5cfV>Zg_mU+deb1z?M`o? zh$P#;+<#To8n{C{x4vVDIJdT(s7>3umc#Fl_oQ{?JW4nK7lhx3P}q#0jM4bE>jKYo zV$1hDUdeO)uO;2m(M9L7O}%^t#H#IRshw-khxKa-cG4w*B+6d|!#RnY{U=DwopYiy zOKST~?NdJ`AKq2}Ue88Dy&!-e{1$Fz0&`U!ec*RN$;1}%2zxswE4=bk?{gDezI|UK zsd>1i+RiR305x~s8kQ{x5I&bD${WtesBrmj^>F*UY51`CaB^NaJie6@$7|O=0m8EKT_Tp0DoJy2#!Y`h~k^qP?hziar7&kLV5QmTv*@{i(A-*%3v6A+bAdPUHz3d4hS}t!AV142F>m59Ja%!EO3`4+O0%c6eC5c}F8NZ#bmBcQmVMH3U6v zBIB$D6g^SGHodZM-wZZQb@uQi%vp|)Zy~cqC@6^(9{f&4&>v?+0KZ=2C3Oct>&Y78 zm89`PFumUmWbhDXQE91tyC!yHUq0#65(L`zTM!;%c^M!F6kPv7&n4iijEPb8eo{bX zQk%-XMHa*5&-34p`kc6F9{=H!U_8&uN~A;W2Nbb$)85zv92e5%fO@s)T=741{M+p7 zoP-@EV`PX9O!=hXq{OY|lVA1#=84g&=}7oMMaRv+yR@{MYYYPKPXH|!%k^S8zp)kdFJJRikwi}XM zasV#3?!uZ!{V+~Y+^z-Lx1U@76_xR=HwKN0aF zmM-3!n_x)py~SU%3Vo%S$P@ZwmK%&390XBwy$2{XItSsLT2-Q_LOi@1;sG6e~$U_Z2rbuCGe8Z2R3&5&Xft^|B%6K zAI0q2hv;Q`l!@>bjDv>f-xa|}+>RR>Bz_2zpdi5S*YCzrxP)|&KzPU@jOhG9{lQ)& zU!ZFSs#BU31pLXYQS^iF|Ac<;;?0mm;Zt4x!%mhmq~7H@vf-*EJ3fn2Cx z;Jc_Xt?Xt~LicsyE6QuJe@5R#H;f&W8LpfFfUqi;wUU@WLYHnOuxtM^y5ESTBP$C_CZU#1! zKN=%4UAY7ynwrQTpTC4!4Lhs=W5EPsffY&k*9w*tDovRwfnmLcoL z_@Wmaj`?=DyQajY&W&%D%iM;7@bY(LoZZ&hVD9Iw1*`ut*X(EB0B?g<@7laXoW<8O zftH$8#Oi$}Q8VKUdP{OFOw_1-+XEwuq1qUKcGxaa`x@4ac1v_~LVrU_ukj97fZs0+ zHt`GV(0E}TXp`(2#3d^T8*97Y(!`I@3GUEb5y7gLk$FC#=pqy0u?TeGfs8~AY*6y% zcXgeI&$3PWUtKl>DAg%b*Wc(pytfwp5?vJDS{gfq!-Z*MbaoCl!pj&*$K#eY_I6S? zR_z)6)3jAP%+x2C;Gk+jN-*NclXedd2H~ue0d()xH-#_4>Z@V9^D>irW}oXO8&@Ws z&~{maboJ&RUjqLR2Fss@_Goe%X3__||IT(lvIHSWO%mxjD$AC+x0o_0mi!u!qE6Cz zZ_o$eKPc|W#AEb7Yx3kd(8ZWycA1|l89CgGo+?lCVv(ge7C*Dp!h<6h!V~LmZ>zii zIv{jLc%tqL;`1QNRXI-t-}4~IYLO}j?KDliTDw#<^K9p0k|BQLB_3)-yx*D((s6$1s&6jVxQpEBK-n3B`9vOX` z{M*>xHivEHK+0R@$bGyccT-c_$^EFape;(w3N_kG;Zu;g$gBsIZK7Y|FbZcTOZ~Y@ ztt_VwyF^D@;|eu}%9E0Ya@R-)J>a`17zlL(l7en~Gcad0zt)jB4GKxk?9GL);b)sz zPtnu;y0F0U+vJ&RcdOyAa=n{=pq_Sn^C}>$&~ZsX#0zqkAWo$q&C0!xRl%)76ts*| z0)oZAass)G$tUxZ>$Vx6NvXwc35(nE8wkkjvsCR)#fM`scq$%-GKW?409`k789TfA zET+WgN}jo9t6{{CXx?o_)sUTYUDR8|tw$S|YUjKbc9D9Rz1y;rZsIz=DAk;9h^0=v zI2jJO=x!<+rua5QmVAB&%khoZtoKBw^Ia-vKjij&6*BQpY;ki}cz8W?;ED@Kj1`^k8z~!yj;xax>-`dmv#E+&;}^Ha!lhrsK8PrOaI z7~5XjdtjEgk$B`?k#y%MNB>j|GS+2bBKmEn($w>|jL~U-6dx7-pgmiJ_k{S5u zIU&`MRBGjj`ZALmmwl1qv=m&^Hzvy0RiL&~ecg~ZAtFpfdH#CDa%h#JA7BV3Ylu{p zPaVrOzwnTIX&yiV+x7FT>$_nV-KPRkQwp6GCI(y_LQ`z$tU9R0Bv4&vLC2Hx>O6KT z8mh9s`O5=9$Inz&J7$UwHe&+ILGYHp&R7}|1=K^SzxscZ{U@5_$OhN9r>vny*UD>n zU6}IY(Dwj+H))rb`?-yNHWOhpP1Sz&PlIIbQht-JfHE#p?yzNTm0=;7KyuHGj(&b| zIv6&267T!|cTU-ar4A1aB3Y83r*DSKq2xwC0m}*UC)SCvIaO#quhD&32M;%AR?t@{R|G74HY*qRfijiBPq$-HXE`}yx z&{ylO$IUJqLzpYb%U*&ZFb_9p?u9cL@xy&AH|`|CGG3e z2ZF5DWk$Ksx#Z{NuR5p>&ByU4UONASiIwPdVU59y3WW>11@?rlpuQr$f5Cc=a`v~rI4x!Y4V%EI9E`^p@h2| z!E&rxBmyrFzpEGp4EfTuy0?h(df&)w)$)i)DuU>!=!Hhk8?y5A`{#@9wtfRgd#?ZP z!^jGloP%5nh<9%wGWdfeh_EW(`rT1YGCT4`jX&AE&SgPz2Y~E*xDr6qDW$)v;D$I! zdbstlP?V09A1wt3b?E!BwH#gY-A!T+fsJwpI!L&yQG@yDToJt@V({;G&?SEk(@EI} z1Ox#u)QlCnESZIEP6Zq@D4vXdjP4JKuK9CU25@jSV+Yw3qop(}x;cVD7W1EfyK&l$ z5%OW2dySN0oN+_%4{&w<=_Z8vg{?&Xz^I!8#?1cOJlr!dH3w^Su%_cRs}(%G#^*c= zOyTQmhYvH{RRnyGLgjHVZ)FV9&J@2SGvsFqKQQ}tgT8-Lli?@oaK*=wWN-TD_g1Xp zjjDID3Ebh*g?Ipce{dJt!yLB3U&Jove=1-89L8bwKKYsgKoi$R-(}UdHvN8KaKE9l zD;Qq|s)1m^=oH!$fnNDsdl#RIG|jB_a3#hUx+rL+7^0SxK;j}%mE^mU5A%^rjsrU| zGE#xkb&_yx1wAlmv!X##sg!wJ_vGqJ9sKOPu?y7_ZxXbcD}dUZ&nDM&B-P~0pQjM& zyh49p_}#J&Kq2jpRghmdpy)d1)hzM(P>c_))!_KV?A0^&Ph4j_^FF#K3w$3y_e&&! zP|)5tH+NIf<8(637k}EnOm(|+hFl)MB%89HUDixEWTWP1^MznpewRK&WA-Cmoq4S2 zACKSzL^&fOe3y!y=*Jm%aX-J7ns6#LnO5?o(+qE5`*~j2bJM;r6eWO=(J75@Boc-+ z?Mpfu=rPV-DdSl3b-Ja-rFb{&yPl|_X;iu{lMU0Aloc?KdWk{wjv{M|7+0h9>$=mH zhd*Q0y9JP?iCXcJg7@wF_qCZST#DE~?NmyTN=i>$=uEggQAH+FX=1WLEJ52UU7s7J zQ)DoKaI?v8?$Uhrk?Vr)IbPaN|?)qfhGJZTz6 zZk`g{lmAl)ZVK&BS~TOy;C5QW5aA8Cw3@Rvsn3S`AcG8JtqnyB`p&7Fs1Q zO>^qr%u2Gud;82^LWr>p;!%4#3%8gjJxPaHAApnlbHyB_*YP1tLwm@0PU6orsYUWb zDd^UZKD?%@h{WmRj%<5$WPv&Vm36;g-!-U(44E1NkCg2#EgVgn!;x`Msi9C0D0GL} zi1C}m`>s%*~v+K#t2bRm0#eYe71<=+Y5($X}HM%^SH&KbULl)w{GvYW2) zx$Eb?FZ@9rSUmFzXKYIwJ#E2PfGL#hNG(t>^tL+_99@;vetiMsu;e0+T9uvOyxh52uFM-+)1 znYR$W=C-MUTQZ6giv@4MU*D%?H`Z6oKsp4je2Zp)6KdE+y+ZWUNEoOz0y-POzpavj zmNjBq!TLmE*Y|HueuOcg|3GPK!RRnKAYshTj()^s9k%J1D=afm*HsCE$IuKxth zC&;!Y#rh=^*WZ8s6~N{`H9|Nvh5U@CYT)O`1*KfhaTKG52AmQ;w5QD;*l!pbI` zQc0ad!F)Oo`!R727gtP$Yl_h^=BP$++F2{s#|9r02aSZmIRw!0@60iSYc=Hk^0M!y zFBjDRDXsN3WNW*utbi}7+kmO^pK6008Nr{1@DXL3x5KmKi^jRy{Jd%$W3-{2ZxDq- z)b^LsL@^#SpZ+5Aj8yVyGN(YSSwjo8N7^0A+Xe$CH%nLJ@0YiS>f1c!4`=*l?&gj_ zdlb`Y?xi7QfDy1DU=ZlB8+lg(Kd)Paklzq@;@9}U-hYfk;Z*$uN5BErZlZ53Vys4$ z@;g=#thTU`H3;CQ>;|dF8$GZ`ZAF{sJ%F}ZZ+eOEz^G$qX$N;czB3=G{H9>W-Ak4U zt0G38zM&`-W^Q-8FRz<(8x}&moc)-<}cM1{~by88LsCScLkcz&?8Trnld)HLfpsk zT3iNndiQ;^&Vef(Xm*UuxmVJ6kG%YA6S$l);FB9CMTb^JIaa*QM^wXM|G$Z|!^611 zgeW0z(h+*byO)avtc6hV?HhPYVr&$8(%rhV4GPdj-ndr6*#r~F`tJNU$X@7wy1O!K zEB9cm8R^Hv21ESosYU7QK#Ps)zR0M?fZk5MaEW|seo2#UVep>R*}bL6!(a)?SOLSj zd&d`>M9tG7jcd(SSXw1~cp)AYfb~(A#g<+9OmCM_cDT}uLKim%?ZYsGS_skt&uZXj z{nWpC_WhZu*;Bum-%LQ^TIsQgU@H%mSMfN+K%u)ryG>HrG{@`GT3p7I0Oyd#(7~M_ zYH4d~`S^z^`~Tdd$j^+VN_szUf(oREE=>L3<@&3|ortsX7)|_u`l|p67UbQciK}BF zr!HJl;UQR6Ds6?aks}i+lClA?mk9aT@;7Xr--Q%3(?+nnv67YF_#uCfmTUm)R#qyq za1IMM@G=heg*lm7M-|Pp$I@0^oDFxj8&O~e$W|`@uiu*mKOsM4dO59HcC`%;lxG+_ z^p&YhJr8|~YL>a1TW^;p>kcw%cuIq zoY1g$7|UHAWa@t7xX?ti6_>Qf0r~cB41PX~Pu{DL=1=^^4m|TqGtPNWL~OZRO>}gD zUkU?eEnz8ywtJ3Q&;%AoeixTr#Pm?^YF1@iUq&|aj8>6ye8;!k8@Mc7(_3v zpznK}d9R{ytOxTz)x2D2kEj$QFY^zDbZlGvKQ;?<#dles(x!(?&$ZH!Ka_e1S6=l! zxB6-HepIn7MBL^X_T*fGR2!ruUbI&EP%cGB{*?`eF{?^baZ1JD<@DLBB;nSV> z>yMfxe$y|{+wiX7dpu8uah_@&3Qp3m`_ACkY@;a29a{227BZc?ju{@_%`}A{kvkWu z@XmVl2n_fdqR7&OyH1XqyS>>r{{;un{3_@Q$;U*#Y4B zA}}VM7^$Wjm^D0+kS^`P92q;ZtCsvOlzxZnX*A87%$M71Iyvxfd3O}m)eInj(yxu~ ze@e&SL~)2`q--}YxMNQHGX0WY4`Xx(Y24EDKUDmmg0K>sy?gkZDTtmFmH;mDr7OZW z7hETm)!`>0q7&#xWR6ZV<^}=m_EgK_a`z4>E;(BZIieQ+BIKram9+7f+)91=#f#eM zVi+$Vx%#8tM~R1`k)byv?(37UxnzN|47wKL_{Yci9N8D@*CxMUNz&bW+1TVSaO+s{ zuyJ8NLFHe51$GHNEU*;tSh$EC40@?0SE$%vH#^M{>2Ro9Pmv((x0eL`T0CKd6&wHE z7mRMGFYsm$kdw_t+)_y*Ur}IG#pHbAJ20h{Wg9w!v5|4eC*8C_c}p^}kaC9G3wX4hYBnTsN$ zo@kpm?8;kiK1DV+7*9Y;nLOOsbH+snnNKH~?*C>OL#r0pk?PK_&hiyB(ca!%$M8A+ zJ8Y#6*nEA+1i0hlpZtQ-xEk!v#MWU0(@` zbJiLpqxI#wI09S4RvcLcwO)J!U6-2^e3h=r_HmVJ5VH~BSPG7lP~nvip-C03Z?tIt zVJ+)K2W418Umw})HVvRu7D9l%oDrRL{?#2fqU?)ne1Y|ZQ!F^Z(}SP!6icvlm^0>M z5>BK`(3X@>+O+gf@0B_0?F&t4L0+@$CQbcqOGsOCBgIZGw%6j$J zF1O|UR9&pXf(=0O>tfa!$6NimzOHg^=#c%}ueA4XMZb(!6KO_ncTP9Ie+hoLSr&}5 zogb?v2*SW)JU_^2W%*1&P~)vXs-7upvQJKly5To!8bbvOo5BZ=o|!q0+1C~epldS# zq}SkOl`J1W!|{kV@2G~r^|T0DR7#>n;I`iKqS)Zu|aNJ{ot)kAR%=^T~Gj+kA&Tsfh#$%WsyT#7dQqpoG z-qei{zJr{5v+5Bb>?W8?_(?&;lF0d`H`u(`t^PLykb`MqiO!hq1yF4kyLJ8;Uc05= zD|fWDt0selK#;3XU;$j6u>epy=QpJh^p79>DeF7C90TQJsJpBQw+{z-fX~{-^)Fdk zKAS3H%e8^u?hGHXH%Uc8PK9S7^Iz?w!OYZiChkLwm)&yC^AxP`O9uhjO`UyG&raJE zpI^QPU_D+F_(TuLd%t@L&yt=d--ru)(d=&2H;?b*tS+dwN5B=?JB&=YF^{EV+xUYl zJfW1dllOnAJ+QQ7JU}3Z+L=nx7qjrdPmhKZN>jrmqO)A6P?DPjKa!=woM$ze2u$?V z0gWIoPiTew5J3WmIV}%LvO@v&EJJI%t@Sx7nliCMp<(UQ0gwoIkq56(>4ZX`TFCd<1a@Cp{^ZD zREBfgxl;M`Z0DsT$sb=|SSfCs=Oy*y>mrha^1B8SscHc=-*J@1g!`>y+kV91?S1v(`Tm?kMeyN{+*u z1~RFiBrj9lpDYhVC{2~nROJo##<$4Kj<{7jlmF@G==vMg52H`2YW1P^_6?2lh~@h+ zdmt4ftGkSUM07h9JyO(|V6+h|DwZzTzH z@WwCxbZ_=ahvamI^*YWsP`KcXRp)~P^_^an=owqd(WUKV%}{TJY_M^Cw|L0uz$8== zQ!hEHhrgzI9wyxSs5r;YdneJW-t7?hC@P5ev-&rr18F$d0G@8*Y4aj$J(|XF84okM*ep<PI8t z;*YLK>ywN2ej?p#bN)3CAty{cDDjf;N4X6pk&L-q6Q* z?gj?C8-PU?;_q9=cWiic_v!GO9V_Ty-FD#r;f@FQ@GVu;oVbzLQ}o{;{UsouFsM(s z;qAeI$gJ|*PnN|<@*fCBhSFZ#nO**YMhvI4Fp32 zHEXfPtua4JH3W^K>{e)Qp`bo@i;P*)C#7t-^`lq*i^#vcN?+^GlEF7)uqD7 z`PGbN`pDMf`WoNHfFB%Y1Zb#B-f!CNIhd{5u-Uq$>oBS=89hv9kIfeSaZRTNl+N=WBHg_ zyzlpf1^cDi7ovGqX6I9oA^G7Em)ob42bxfBM1(7u(fcQM#22RJH}vou=2^ZiEZeb& zEp!|Nh&hEe1!T(hp6+RAa*n!JV*XLf=a0RmGcp3Yu~6zngdi^AdIMY5p5B|Kkb-dXyfIH!Q@C6HI=`s)9g724_i z;X}V6z0WaTEmE#V&49RuI#ub70E5f{^|DV_+()9vZ~JyQ`m9>ahd6gK!y5s-(!jk) z>5~Li6-oe;B$s-~?&Q@d4@ThvWzxJwd!$8_zD44N#EH|$3$y1epDrm}Qp%J8c@ zI_#|)#)|AYzi;sgO!S8)uMdt?QXen7gw7qZ_KY*>5>h3NzMZK#H$>xbdKfO$4YTG8 zsT2Ospy=>kr#*C%q?Ruu5U46imP+&PEI4|1JEQ4Im#kv)V^~i8TdMkI`6VIz@1fxu zY;qi_cz*=Co}!9^h=lK7zHTC2K>li{ z;8NS};RpcLk;TNKB|}_Llhc2arAsuMzVN7MFDV_Fy6_ z{K46U_ZMoNfREDSibnC-xXzBhmU(7wJv&+}#FaA$4j)k`GstC-MgBqygr93Y9qZuZ zA-ewkY z04p9yS`U%cx{Kf{mSGA^IL#@hS~9CusSRd;Ucn(ZhXFyGQuiWfCvX;HzdCxZx_{Pdavr67Yb;>|}CekSmyi!=Q{S#H|R zRt*CY0PX!guNPIwcpSPiIDyNW{qCOR7eF$iEKet(;$lxPRP4b?;@O;uO?3u@CbM>aM$jv2q-CywPXLO0X7>nF*U9T}0;YrH0=-GcpP`irr_pkUM73wnd%AzHHorb3vPOAWQkGE5pb7{)z7*tBR}-(=D- zZv=#vaI%iyjSS!W!~Jf(^$XIJiL+1UZ$2>wdssS&Ph9elT^}D2XH@Z-UekiXbOfb4 zfY~RSG(P9s3@=C^jki4z~n7F!V3#OWqzLy55b;^WGNVKm)QSypFD_& ze_RaK@=xOu^&)gC@Q6?Pt94sD54NqL7hs0!|O3pgM<>V?X6WpwEYBNz9gFZi0Iq8JS-S0isC8Q=vH z>sI_hkGattDh)?Yuaetn{Nje664GG?j+E(%a^*+(RMX_TfHB@VbVGMxlfuCsChzjH zd!A-7G7nl{*c)hN;lRxkKc;-ZWgCLYTL{0hr}}R`V3M1mob4(+tC&-cNi8{rs1! z+u9lGf0i5WmCXKY-VHoo z?F}&Lp+3p6&^l{3e4NwOw5-~C*0VAE!W3BDL=e3aDco7Gj+WWSRPaRANV^5M$d!$< z9c-lfE|sKs93LrebE_NNc;zJ5Yn%Fk~IkR{MFkV<@|ohA*rbf_r|q*ZJu z#uIE>NksRfKwiKx))TxD!v7$XT^j+K+PorhqW~~esD;;Qd6n1N;A`+4mljo~nE#P{ zG%=GgU_*{g1X{to+-L)!r;LPtrzDdis@~_)RyC*N51A8hg&k*;;8Pp!=MmbhP=2yLZG6`BKrkXXABvw2Nq-EjhuD=F$^hCiVRpgpikD)Y&;r0o{ZU zbnXF7Jj1_7lGs9sDfSh1sQ6^o@-A?Gia+@gu*(K);S43oERt4b$x?+fgITv%KEeek z0xm~U?IP(%LdEnPPRzT;_?UOzc~)ZeiiBN~oZ6fUg-?zDEcFhuL^B^KN=0+N-E-gT zQ?5n``1aw6PR=8+1WuK_{kg?Go%_iSCXPUxj<==1Y?vQ4kJ(wNCyC=v%@JmncB%IV zVDtz11fUvYRXU%KsbvroVQakb6V& zD>}7w4r%KCwRz`aU9W>`B}wu5nzi}=@e1vBoBD5M7W-6PFew6ym~ER?s`aKGH_HvL z#3qlGF>{_Z>us%F_Y9y-IU?T?yvRaM_^t*z6t3um#}zikVKC!3Sj#j5KiYuPLb)*wm;huCmef7LZVQqN@!g1HY3CeR6k*0$AKl^-}i7gE1BoNp?cy z?cbENgy}|SvF+M3b2r7op+6rUUI&MI#7$Bzm2A+DpO5z2wo@*^g zzbVlapsi%gt>E?+CIjR%_}8aBIwG$b+q9d?z(_mw4Q`O4bnWU8Z~Buvd%4ztb#LXM zvQj(g9s9Z3CWbzyas1{i8v!byN3Z)BlK-Y`OU4+5nORs2*_;^BsR3dxO@`#<^iP4PiHn zO+n|o*-i=15XRuDnN)YHEyxuBoswvHrr&@)eeT#d9uRYC$J(EnuI-dD{#0T&W-0C@Q;Rl z&k7KWRdSfm^fmll8TdRpfgPtgZxwoqAr>7I!H}C(tZkCTi2&|oU)`=pZHW-IF?-jp ziMVm;#^t2#9_c!rh(aoy?WO^D>?4QLy^q3EhQ{&(=mbM*)EOtPdRplSKlz3O!LU9dN|zF9qB z`~#15C&|&^c~^UgAN3ZQ0J}OH!rt1v$Mc?zGQgCj*MG*v?*hj*th>}dW*1B|{QdMd zQd@(PJL7QSpwG`kISAb+LW6;hDrH1|vpclQ zKp8U2%2<_vxtF4X9f#`t!R z-C{m+p06&!e(PPkk1AEwL)((vwbuwb{BZe~``s(={o^T2IrIz|;pwR`*bw&r1?diS zhwffR@9#nIeo}O8g_JDWW0!t+zuSQ|tywjm&Gy>{`I%);BY|R=GpycrZK?a?23Sgq zA0VCu!Q?`yl^P2NmBHgLN3RNPz>yn3Q!4h=2@A{*=i5 z3|ug5ZJ<-a$aH<8`tt`yR8oCnv&v-&)gLK|XiwypaN(Of1mZE5r zNh~me#)_)uJKy^n9^nhURNix_G?m}VHIY?cw-Mok_;#G=+F~~>utIwKt2tZ)`Lpi) zsKqhI(SAO*w2TG4xxiF8wj$JL%`*h*0#Zf%(Pw^j6CurP2(Nm!G6!VXK0f0;I8ijB zKc7w1b)j2k9vafIAjj3D@&(jB>Y5Wm*^c6OD&hY9ASa#D#_=YHJ19H$q$QtmJ8aeg zy5d4QCx=Amqp)><-{WVrL3&a$f%W3uMn-UO!GyhU_}};-9rtsW3iA^}h0Au@5m}D? z2*^KG3-OW4X=C;Tz5>@5$-e^`Qmeq#iP#@xcQ#wl3(MXXpZu{eMWdj*6tW-TGu~PZ zTHtfAx6e9Z4#SIY@{-o2#SD&`;w=5T?+C6IjYdD;aAMZ-dSXgg8R>m1R;6 zV##PT2mOVw$f1XwO!h6_U%BRn9679DFZ9md>qut0-{^2Yb0qGB&8nRG`ghqRRHovb zJ$fdoX8zw1`zidP$~XX4&6g~&fME)pGRlE9H2*AZW^l)Vyvt9Sls3e0=k0L=)rv8> zvbh52DsNaJf5xyn*A8J7KwkO{hFVE}IhXrGg-Faeub7j8qi^Y|QI`R+`6qvVpB3Ag z(&i$-cjUkjSF8j|8>LAP;?STg<)lAFpszcuJuZdsm;Z<0$|$4bGWNBhT%*_|i=lh9 zO8f_RRO#E;!e`P=E$J_5X1f^vpn1{xb~GyBzel}ia`AgYnLH37)gt7J6?T=1W3O{W zU(^Dlm;yZLS`z{DO6#X9GT3Jv9mXa)OUMOBuN=9z^hZ+C&7wSl2)30th;r6IV2Nz3 zN(|_ROfty`5~de1Y(x}B%yPL8LX@QvhagD$jc%-N@Ud^-nMjD+hjyOsMeq^`tVS`V zxZq@xQt69k`x3#tzs5<|H6B$VBcxq6oPW*iB*$)ko~c)Tu}^PFQMRV__W!a)o z|Id&xijyx3lyZp1dW*mo$32Nv%}F+~#R^%R)}2eGTKT?tkFIOxD?G{tOOtg+?;qNR zM9!z+&)qx0TY-{D3R#92yHWt;XM9pyJi{yl7s{!$r+n5BPT1mQ>A^2=k|Chc?u2*K zC8-yLybejHQH=5)iw856`3E>w-T}XXp5TC}6m-+?hSb7*$vgdrClJ~MtePfJjcBK; zSxN519ZE5LW-^l8eHYJ9@HCknt@ngei@9(ABeg`B9fvj+%gbMY78%vFWzY(igiZrv zr5X7uu9!u|yriqf>JN2fP#lPe*|vu(u>fj2*I-SEb<3cT-!v^#7gC=Z^58>gI7F@# zpBds;C6N4Cm}q6g&)$>{@6TRSn0NscmG{-`~Cp>R)?HbTgD$AX@gKZBcy!IO~|! zXQ6>)FQPd=NCUq9z@2J6V&K0XN)B8I=p2~2lPJn1pEJApvEe|k zTr2dBsyn~Z)mmn`|FZS3NjAaCC;TG&ssFz7T%{=^-7E@7v13PDgS*`{`G(7;%O2(O z)|!{*!Mta9MM^*{>5o<|jV7Kfc9L675hH>U){&NqDh{(!!w&&FN~z9F>%Xi$Hu^Xq zL&M~NpZ?*>^3CI=b9^@sMdp8+8+wt~;7QDm`c*k{m}LS2pJMq2!oVZ^Ct+M6au&&s zzJ3aSUvtLVKyF^BI=lO_J^;s3&5^sz^ zjyNoJ1_nDT#z#sMwM29=bCyZ@2XZ;epX(KpVlMi`3{Wf+(W-@@IercwltjwkRH(-Am#5U*iz7QPe$(3SfR_tAeanc32*;v% ze!?bkAgF>m#Teei+s2PVY-%S#sCMX6#M;z1h`vQbqcUlX;Xft0N&D?y)Izz;ZlTpA zQKsNbe{WJ&x;D~U^absC4=%A=R}>TBoC_(@4;aCoFy3O{MgmQWB@t;<5Gcfl`(8xt z622p93s0o|OK^dApLcHZUJ>_$zcni&r5^2&+%?Q1GuQ{XSR`Z%S^HuGF!!9d2Dc9C zB7DP7sE-U`)Ewi_LF1AgO#zy)_m~-BW=^}Aq8=615bC8m=bE2Msy+(Ixn0N|W zG#6|X%4-q~9AR^I+--Gldh%_v^sDTQcLq{K7rcGkXLSdL$d~@=L9b}ukDhk?>vhC) z1#izzUNmqM9ZW~-gh7S_e9ay<=9-xdCx zR5u-qLVIDo@=GepnCfVB4yBWjaD@V4IdL+XN|IywQ56}X=dFX`Y0OL)U%BCWadQn^ zL35u>0mI*BV-K^~T<|)jA%y2#XNE~ZQj&?|iX!c~`5vz;miGFvephLZvgQk=1;lGw zC~wsYpf?Kujr&U6^g6v7p|lj95~|kj+w|S+X4U#&kc%1UeXpbg!Lr-i zW+SL*(4Xa?KOtg(h-sBkJB+B(7_A8ayn%iTe^0hs1QLnq&hYJ2&jh_KYW_CygNJ55 zarlnUvR+|q3%MK~g-Ql0+EqL;?QTHrCZygM6u(^XHNG*ZV!E5UeKw?6U{Fu(FZOVh z6$nS3-deiEZ?r?eM*s1!QV;bneK?iwbTm)*dhWQd$4109xYz8Da7lF_tOcsMj8RDG zx1l#8GzPUKej1!arvxf>HRZ!1#61*A7I#Tnpj_N*nP7yCcK#?C z*s~*wB-c1|R_#rB)e>Sw0UAe4jLy2)3C1Hr=%`j!ZZfPOoZD!yne4A zRG;+gv?Ft#uQ;yg3<1y3L}V?GxfFg5shuWkbpL)rZ(6jx z6&5ZOIP#Po^-H^atl`}pjP0EEF@rQ6!a8r)ZGGn%8RdQ#XVo#L2l3dQx2+e5z_$6d z2fkcZkqZJ}AFx|5m087kq}+P8AW;XT_zoz$I@Y1>pO&gQ^^w(1tP|8IEtQey{TDwu zpz!;gCfj(`N(P>pswh9=q7_aPsP#+s_kjstvDK)a#m{u*1)2JTaO6lIuw>z&Ml_!* zJL7WY)?vb??jBNtFzwC^b>zD#!YWVqF=0D4UKzj_tjQ-_jMPtCn&3I!xK4| zTNVAHr_ctwizbU9d7Hfmoi7$TXhlj@fIyu#v%zxAzwwI=My$dEOm|9kIc1z#eAC$Q zv$8AyD!@8dwo) z_>aBLUoO7v9@^~b#H&@!0{R`v^~fcdZ5ngdjNp$Mdo>R_J#6Df8HZ{+835IyDED(4 z$y9YdL#&6V+AhCEW{|S^2fXN;ppSdJ&y#`P->VA*{*|?O)kM$0+TcR2Ho^>TDcZJ)0`f;nyTmpp7%zWrAx9ml5*ZR2Hh}zS z-p}{R-z0)Sn5CzBpyY!1dgN|KGkrYr_~n1Mu6epH!a98_7A<{Io8sY>`Sk-(BxVeA z`ol}*^~|i>=^_)3Wxe(l^|A5vB&9VGiwRuvk!)8iE&KRP9>_EZJqh-+84&MJ@IX9n z(+r-)z;;8+3B8%4HDhj5}!l zi_PQ*BOFqL_q5M@FO(^n{qKrP3728+K^>`d47MYy@v< zGAcM}+_i}+N<`i<9%dM=1+CSU9r_>wC2pjd)?nq9?sVXq@bBFIV^p$dA>Y^k>G!En z5^L2j3-^3pez;9n8|M^%mFiNjuZi!U-Q6$`v@-@Y-7bFnL*zB__QmjxRW-ZOg`*Fj zr_MvNFVUIIwPA);=SNBYHklF;IdLewqSyWo6Kle>j?S~4sR4PFw(gOP87ua|;mh>< zZ9P2MKhA+$&4@AD(TO7Fc~Wx5c8kw!+q61=+gOZTV5cHzbF6__tWfnza{Sj5ohKh8 z0U$>iWMl4fu$G)}j0_Ya{1yygXKX)3R3X4`W{C9Uw}r8+N`Kq(AV`U~OPgs`MDe-| z;x9uy&F?WjDP~b_hOP?K6#Ly$D0|N+(sWC(3(*&hL!ylWSrKI-&xxn%i$6l_K=)9I z{N18IRbcRnY>B3PWuA?C-by7+6K4dT6gZ~7(9$g`V9nNn>Ub>T9kx%r|Jn#gl z3zVg;ID>esw(~!suZKsEi}HSe?c7~tgohvNmhdp3zuO=o_pD|3^B21@?EB*;;OOUS zE|62Lj9Q@x%bqyDt)Rv`!Gg3|vHRX~dTeCw9vLPkf>BGTaN*t!KznGh^`)zfI_*ga zMsNEt&LWuYaP;d_>6F*Ial}7Y&(pY|=R!J{6`pp1Py~a&p};O%Wx^&*G)ZhJpg~!4 zPdWY$5#~Bs()hgF1Qgg;c9jYg59cOnAPGbX{i)hfuj3=`8^oNbVaNVx^;e+SYgz7f zge^r@RlJ}g!1?zY<+U}_EYsdW>Uz^`$1wR0IblMFZ)Ox~@k0$OC4XC&Vw8}`^N66Z zV9&SMzpej`gP_rZH4-462OcJ7&II9Emkm?F=k6sSC|hP>YxjE~XmflbOTv`4>yW_% zu^9OQ?N|WH`Zl>jjJXBvuTljqu(doy2BAm*hU3#Hzjy}~R0$x1DqU`v8$S439rg}T zN4qs<&fewlLKtAj_+oBK9z>=D<)%M!bz%uE0FS$qL9nDXKK&eX3Y|6b(Ifnt^cr>D zIfj7oF{YdTCofaYhH!6X(6zt5Pb+a%7xPg zwbDyU0CwCk4NUS#w=?OS%?s>xYyXAE>v4l*3;uua;@Wy{?;mzuU_m0*5Th;Gp2Np>*2TKp47kb!%P_z)MIV-2Vv&$T~e`cjX?&>uD172&{# z0Atc1*_VA0wgwdXs2i(9+C*RD=gsa}i5Kd^@4rRu%wVA)EaSOeVS&{lt} z?#f}aVuj8T#G6=Pl$%6(@3a~+x{LcKh$8VpjTiRkCd3c2-7qoxGO7)kKKR{$`iwCI z#o}b_AsYTI!O*=bo0^!uIdy&~>>Pmi1(Kr3s9&!7fG}`;-2cVn8*EN*YFxs6kdNY~ z${HUIov;HTEtZ^s^Zjh46EYa0+4}W)FM|^Up^Ph-AOxrwU$x2;6}a zdV+q*nm@vZeC`LcbdKZ^_4-=$jg^R zsYPG5D)Xy9e(O6i0fwfHkT%m`?fa{;g`WSK~{$xlsLV(En zkph@?Va|wAwlIyAnBNca`qY#?#QU_FGkJ{l>o$0MD;xA&UvHJcN}uh0Clv&@^(W$8 zEs^=p`kMF8t*~(Xf<{OzVEpexG#K_I5eR%yiZer!?)QCSjY1eo;O+h44Y4<@p?3|> zz-nSbG7T&>@ik|1zt7R+Kfv89jikH+ojX{6`KS$#M;OpRSqt7JIFC1~u4vJcIDYHD zR|qXYUx#$w2hTy!j$p}ce=5ieVjVGrxWIO2ub){Q2i&pdj;B;UM@`Q4UMCj=2|VtB zEidHY8cWbVf;%)Rx^0*T3ZDuM9K`GF(DQN6Fk#^c@>40cu4NP2dz8OQ_#p%2U+$(S z{25?h*bnM!edFXh_rnX5acsXSW0^rsG=NNsK77p*S#6@O5b)cQad4P7DTTG5t@#`E zC~cPYI0ZBD#aqgmJGVlHcbHH2{bAp+LWqL((jz;pgSKcHcZL(&#{|M9{F zK5qPIhX)cL%bjGn6W!2u@e<_7o%ph4PIJ23*|{@K>Ey3M=0tP^5XM_H-h6_XC@g1B z{3twg!D~#%boJQb-Cj8Z-ewd7tn2BC!(ONi*C6=NGs?(|NR|Mz3 zCUxRl-I6LEs_6iFYZuj&SMpW_lzhl`UX zq8UR-@u7|(^9tbzB^JH-b5KdLm1dmg=qIAcdRqp6cgdfE$U5J}QzdBm8iyWd-S9)8 z#}K|tm92SgrlIPxiJQ(%U6|;GuSCn!W+eVBe0jO80AqW4LwzoeIdoSpGNZ1HLUnNQ`^r0hycj#! zNW2_bh$~)TSY*pxne=E)bsM)w_n8kHd_he*X=brNq`n{b+A6%pMdcKx+n&}v>-F~! z*_g@DgrznsIX}} z_~0cee}GKl&z?5Jl1CcyMK zs;z*A$dxbRQdjQ{Se?mO|dc5T6iP?Ys&+rW{ zu)-#IR(OpDS{PC1tt)ik`~Klw+F5-aXFsANgxYj{Sa8ByN~_y&vYB>O;K-G42U-1> z9Q(h1q|)${7^G0>r=TA6njkkR;9gzbDhcF&#HA*#j{Rj!AA`Ga)atBp{1fZZj?{gt zMfnK4o0C^#>k1X-I+f{kuCl3Z;AKLOW6D!HrGOt|2!tCw#q!;VN6VVEUcAkm05?2^~L zyr#l(qEg$D2e8WW-Rv8ULtghon)p!o5$n=mSevZa)V+VgRym7s7)A+=nEM6)lcwU; z3re_e#EC5J+0$hWnvD{~M)%Sbnr@{TK8GFK-IzOU_Px>fD&o(P zmXov0!MTQ_XGJPW@ilO>M?y#dKQ`~}ax&%S_kQ}G#;hv`(&4T}ACbd@93_}IG7@4Y z6dHE}mq4DG{i*kbS6ssCdJ9zT>30T^O-Va}ylfk<>M>E50iL^sfZ(Z>lGoC-P&?b- z{n$ri+u4oU5;q?c(K2H4rdnI40i zUM7WD(kI`jXmn=TF2O&y0(t2YF6p-@y2p7VI;ytdNPW)5AU6{B!;5L^fj_ zb}1Bl$PsXzOQ3i70q7=yQu(X&O*6Z&5=pv~cw~B57h*mdy8DSpFDNSvjOa{^r_~x6 zU6yk(ksbUD;L7+@;9X*Fkdk$k*=p`b92z|JD=V^@EXWQi?!lI->5qb#W#7exxnsAv z?X3AnWAroTIgL*~9QMSYD+X~Po#bg^RNZrReqTK_EqoGU1R@dwZe^gk0-!tdQ$xT@ zMt>@gr$J`}1MO+@EW91IRI${2O=8(wnf5>GmIg7DCUl)xeC?!2Mq|sKP3k_hV3IO9 zP%o%!x-a5yv%$FVb6(*o+C@cod#X@=e^Dg)Jne=mvUZ^~@}x|GCpA$^&8!w4W7(V8 zfBv``RT%JG0~G#q08jU@2KT4k`XpktRCeo2F|~cH8WB&w{1$rR3$oHGWrI#QIU@Y0 z&r&}+^URYW7(xz{tn4t)L40FKAh44?32ShI{!YPptn5sEl5pylT1PB#$;{}!mFvEN z9(ET5$E#S*wq#fYq`<()8Ni!P?M3AIxbZ=k1W_;>T3oL`~YbjK= zAh*UgmMw^YGyRl#g59>=sD9$=9_GgKBF4l_L8VBP<6af?QPN%ReQV$nZEYdw!a?Cy z`>!Z5bvrAxG$qs+#qipoVmtM+*VPO{vPa>gZQ<`!iDD-iK5Oc6m&;gu3;v`wG`K?b zb9eekn`g*nAc)E1q>SxI{JL2n$$fLYsL-Jj<^{zCT*v9`Z{3{fWznCy3Y znGB|QeYJntS|2U`o(rDpMk^^7YHf?hRJ|4E68A#*J57jm!BUCqGO6YmPy{=)U+N>fiwUjp` zfKKZsR_ontLKLpXox!4vpb{VM^%I|`QW6Hy0~H7pl4aNMTDJ4f>7jEYk(M`yK>C$H zGr}AHO`W(bHiYiy0hI|?+nDI`wC~F;Hb|(10^t}&O;eS>15;KEW;=A~Yq^QS=@R*7 zBkjlMUy_8X&btJ6H+<|1=mJ$FOYJGGKod+9M>p|rLpUTPyBWv4Q2QG=5|5HeA}w#j&Q(NHXz zp`<~dp@#1y&O1M;pj(+swpfCTW>=B3Btd2VL*4?8&!!lcbRR2uKdZWk#Es^a11xFH z5%30;!U326g#Vvh)Xy2-$do(wm?qpqWmSloMx*|-Z$>f8Oi3nWGb`<6kR!_*mWU0D zC$`H;o;t~oO=%B;Ny%+$70wtQrk^^iLOF;ob@=ISP&PV0psc-|+W;e=!o<0RR@F(9 zWb%VJBW$q^a)(rB0x=&?5;l;sxa?K!IVSfii)FR^(MdS)&HEo7wRymIAwz7d zxS^f_W6@9!()nulbKVeX-J;m7?sHka`H(YGTQ^$TWQE(?lpn~#!c~l3au9JRFa~y- zUe#aP4|Y7IjK4SFLILsXuYv7kz@x#l+y6g-!W#Q^>~bL7gtpllX=00SJp3`GWOsL z=H5Y^v&%SnGW=OpKik>J=Pxz99a2VogD1+*^U*^J(oNuH#*Sq9_V6n9e{4yJ_) z1Y!J?Y?_1Vyy|+wN`#sur?nH0vD#<-qfCW4=Wz%tVhb(NQ5kXzmlIT z*!ZEk?V2qnovPQ$5?v&8ZE7lIkabdnR>xDUUxOAwI&aANWNX`l+ed;z+$<-He!%PX zqn)e~#Fg$h(z{Au^f>{DUrG-y?X;|&*P4eCfGau_oN3wPzeV^x1sSye@(w_Ie#P;7 z@0z-uM??0=u=JUvG?y44H@uD-P7l#pCU|C>?|q~o)Tt5Mr+vX;R)_0{nrS892>A3 z&0xIcJKd4c1p{56Jj`wxCwFb7Jg|`k?lNSz(-1$qLaz*(Vh1iK9`vhI!L_NA7q;eo z7IJ-m2O-f8vm4$srYh*Zp}-ts9AytHMXu_6rp&cLg&31LeT$8fEC$<@44`cn@xW^_}iL4WWt9GT#1YcwrGBP!O2vANI*(Snnpk|ET9{l z(59Oxjgs&)w%^8^P8rK}lv%a+!XwH6b1iM_uzH=e+p3HADe{eM6U79XAoz)!NBM5F z%wZtc2r+}k!=WQ<#1pVB-S&BnnZENK)p{B19{f&p-h02y=PFz3Vms76@*=)QNPbEA z=nm0+-$(vKa2LBjX|LzN``oHs-wP2$Ha7y@!9Linpapog&_niDTQkL^VQJkOYWZ23 zbjhx>HaM%Td@=};BAO14-s4V|R-C+P(ZHINX(zy?Cnt9*IR{#YW6NwfHi)~#q=nz= zdMXd8FzAtQq`HGNwa+4rJLzFJBl(c>JFT`gA`N*j4+6T~-9)Z^f;m9E+Z2ACd%yA4 z@;5?`8e51US~~w=2wtrVYs1H2t8bVfJzu0E1QWbU>TbNcz$hFW_^k479ITN`RJJ(W zH$j#OKd`(#xdZ=Kc;~Ix+u&nK(hc^6uSB;?G_AS(E;|^HYktx=h3YxTm2#TmuP@sh zi|-}HL_0h1eV}WzA?|iV8mK;a>}q0OMvX0}#x6Nm!H*+X?b7KBbnF1~dk8yWg>9|` zkf07~Hyb3cnEWd<9Z_PRqKX%Zm|FIf$=az10Q)ZyKN%iDz-FBd@%FEf=dw}uF+uMv z=!*q)ud|A$j1DHX78Vrn>AdYbz^Br2#l(#aArr1-SIVlF;^Tu-W3`c)a{&_KyY zAV_*_N$cp67h7nK^Tg^|W^=D<@6zdFcSBZ$4S3O7jX zON%*ncsT9#n<_W?Oj7R=ten0_#rxn+Kq#PYOGl&K&Lsj`NQ=m zVm9l2{~$0CD7Jt~yZ6w46aKSE$6amnENQit;ei|EeI9(LF~k9mNqtn{i%Pd8@l%bs zHA*)MO=f0;%^yFWxjU{2AlL11qG9|GaEe_i?&eFIp&=d}AcouXy5 zW!tsrKk&GF08o|Uccq_N zT7EQkzoUOG^5ot!#fI25fItLN8f@RRT^M^6cpYLcY;BkK_Sxgh;i-l0siSb;^Epls z1LHuL|L~zf@f>W7WILXDdCy<((S@tG*<@zBOjk2*TrB#e5=+h6@Y#cjaY>|DX7kV= z$9pn@(55409(eovgwP{1Nng4WjT9S+QxMvNfv}CpW-ag6djIZJQ%0?^GO5x{Wj=cU z3+LF^ob;?pNoM1miKv9Xb^aXTv$(}qbjdGSgF11k>Wm>eIO!k*GbrMl{LH@;Q(}e0 z22kZU8U8TnG~2KTpF$5B#Sj&?l|fTu4{hyv)Z|zJ>;Q3eQoYU<-OB9S*^}4X<$9#> zLwOcu$A56#zRc$->k0quuKtshkA2h1GT9x{3%)uu;=+hDh7Ic#{Pmx!^t?$Ewy%hd z<>RaC^LI6h+gUK);@c6^3%{fXjQY&n_1a;-KRr|35ISXIdbH2mEhl`#rhrm-oJPWj zZw9uYcLN-xgQakXwf@E}S}(PZQUnc8w=Q!sC|$g+p|^OoW&=Go?xCrZ;Zh2EsMYWy zwXkFkt;UL1OAAn=ONX9I7XMHnBZchtOBgCiCD%kQilZcX*Jd;pHY<0GHrtdAXA`3_ z(dTi3BI0w%dI`)gz%jyKi9Q`X0F>KBnMRy#e+4{&|_qf8lN%{`pY&kqm7C0RNBw zXWhOjJ)HtK=ep-*hgg9g_TSXD*886XWt!~QtLDjzP>hAQ815l@m^5|_GrF>B zz^5F`?-*l%J3*0jy`6}s)5_IiND~P?SGi83Yx!GM;uJQZf5)_# z0TH2lo|x_hP=N=T%r=Oj(eUT9eMJ~mELX(l6sGeOcMNoy7~ubz7Cp|>gRuu@%bGA#QN z(mz(u)p$Yj8$5rHt+E&Y$qd{)A(4#A(^Yj4txo{JK2om?Cdo~J_F!%td*3y7b8XZq z@p+2-DLU@@vP8g0=d5HWE4E@r>$k0MNBDj9G29~@_am%UA*I+l@A69~;;NZar|XdD zpKR1`#`v4wX*ZT#D9^EDKBuUqo28d}`{!(ld&GCZ9NxS-OL_YixXHZh5%3M1x;6c+v+n#F)-Q*!l#V!2MW_OlJdclSgDtl)iu{J(Yx>&9H z0&QN%^^TlJZg-;tnTn_qL8Hen5JQ^Z&d<)R+_tHAp}Dp$$4Ezt2h-|T0SJKqdRUdR z8FJ8^)a$R#!;f|ji21?Lan2L_?S0fISA7f1?&M~s50&Qz`k#fo2KzQhGc&FIbwjK1 zSCpA*Egkpl1v0=RE(T2k@_HGf5mP>BGD2IEsKU^WCf7da>yM}lzBez`Z+k$@e>h2rT%0lg3d{eoTz6D1M4X+cg4l&4M@U7@_^$R!SLnEYmbg;$2}L? zpztHz8ef^t#NzY0*5|yALZ2`Hz}#i<DmJaJ@Vy+HzjA|WbYhP@{Q_1Bas zej&XgCrGdlQxb;Lr0ccfE@k>33%}k)tiQqmg~VFzH*s{82dcD2EBpLwn~ohMZH$|= zCf|i|!8zj;A_8_UBQ7mP2C~Af7B(cd#4q1g1UDSbYdf{BAizXbgW8Bv~Uq^gCQ^C3G)ILxfBV(wq4tT2V4JW zUeon`=_167*96or7D)p=@eF%}_dPd7BL#}`qtm zO{XN!LNgx!JAWk9zZ`FUuifmgcJ^QB4!6pji)JiFDQsF;c`4J&ZZwrWdT>H8YohIG ziqPgLT%z`AGHvJI$-7RD-s_O_5l#|;L&t_Jpy<@SkcB6zMyL)pw3HkrU|(mu04cGJ zV^ykb0g=J8#wXJ_J|GQ>ZJPxj-JMfi5%+f+t_ky@u;35Y1I@Hcf88zSWrJY|zuW0A zg$KWhNVwK3jxa{mo7$S%D?Eg2FKY~1|NS|ye|5O_ZQrGtT*(cL>&hhx(d~XJH zS@4U`4s>qqI@|MPGCDNO)a5cU+NN8ehdOjhu~?@)${GpFCItdueyKm{Bpiu*#fUlx zkgs!P?;_tB&IVo|nZOjUH7zZaBn_H(ICV@P7We3`FL>b(w-+g4TBep2Rb$71SYIS|* z>J7s_yLW7zf=oqLL|;%zm>k9i-!S4boEvFVKys$#HOf4NrD-i%aH+IELB)?tQ&|V1 zF^C0a3coa$IYg~K%Qv=XNY-Zmw2o&NcIStxR6t#Hr_-0)C|>%}hU{-PnehqWaL}rf zbV(hMwwpUlQ$SjPDWK0G|LF_Y;T)=Tm^yxnIg)#xRQ;i=$3=Y#CrJ+;dE(o)+MLKC z-Ipp-j&%R_I%4Nq60KIEk{6Q;k}`NsQQslOg@|+;dNj3u7G9qycZBSnoV4TEAw=kw zsk9GHL@d3qaoJjosWt~6%hE`Je&e5pHd=Om4EbHU?+*s6T!Y;F^7z>kRhIB3acK4b zwkH55w}Fjjsb^9%XAs9cR>w~PiF)!Iu#1GOei-~Nboc&?&0T4|sr=ar1>as*4kJw^h&Qx4-2Vx}2g=X8Yx zi(~3UmD2Ht6T^)gYiCo3>67HL{D(1+d)?_R9*6FW=|15NtWthbf+?L;S(s5fekiYj zn(%%(utn8`sx^dKATJm*mQ(8fZ&VEePP$0l+zaW-%|Q+uflP`fOU06 z`XM)T%d5^hXS`i7duu;Fdf>Ur3hVRkWvqz8MKvz~O0ExRB>jD-n3I3J)--9%95*3# zm?KSQwG~tc?b#3gUJZAP}#qm?=zOtE^ zWF6CHH!}l>!se%g(tF}0Eq2bq%M+evL8!q+)>vq=`0SNV)KdltO7Bp=56_9TLwq9@e=}~Xyj}2X;cqrS z$0g^sLrXEEz!*qggA8fXqP#Cdv0kvkuIpeo(nepCLR6N!2j9*0XsPptbv+nHc31dj zY7gK8h{gGjDh{Q@hUsIRpeDRhdK0R2-HuoAwS*}Igq>)52^6K{0{wD;F?1F?&tEs{ z;L&39_`|sj#-LPVSv;J!hsUc-W&gYz7)Y7vKUov5_|9K*o?Bz^D*&pAeg^)=^Gx2X zx71^7@LZ7562=PJB0*v;O0(@nZ^1}UN)^DnP;q>noTMQx_8Yw2G+3Z#dLU^u*gm@a zRGAX;>k~ZM>t2%x6BT&u2|0Y z4z40c41C7s9QUU%eg*}_g3C`2(LI6|@pca?I(+SN@jEWDKYIgod!|eut6iBosWynZcOT~y1lVuJS^=$Nrf^8~c zYMgrE^x$-LY8CTL#h-f?idJhAOOB?Jz0C|R^5(w}9RyU@_)YqJQn0Z*>@F6EEt+G% z$_>s7Q>tNxoV3OMK%rm(+H|H z!HgvTu%rLmO0J&%kzmYzftbFlD0?UMSZPVqsqCgwu5afxr4LKpyc245Bs`i={E}Ev z`XSfcrSuyuO-%Pe@uh_3{v1dyEx&<7>k!nv!KmWlXTok}VeKDxWj=-=j^u$Xlo@mE zvV}f3@(^<2(Gf0M2!|%Nz60=lOJ;Lc`xadn{UEqeyvG9BmfhPD5KPqd9p1Ngx^=?` zuF+si{`e%TRV40=p1`z7@i&#+W_B5p`V$>K-+fOG{g1*KahjdeFqhv)VP}2KF{h%5 zr3g@#KUr6}NxED7ye=QxELRf4dc2=f@%Z@;r>L<8%TLXbh>u2x-An+QQC{}4frXfo zqdQ$FvHEQ{JdL>|z11IsJSl!tgk?`lz!JeyB|O54>kp~Vi#~%a)pB2{u!Cq48Pnaq zoDfgz(K;@*Jyj2E;J_bX(H?SR&Wo8+yzu#M5J}%(=-nh72VGMW6y7Wm`nO5D^x9^B zR>Ds&*$OGSq-SAy6qWoD;@Rf4(H z3Ej!SnTz08E2U)Q$iw2^igN?>>S=$465A6LEFd^8DJrm(>>B!2tD!Ol0swhUL4YA0#$eOL}O$+-@p$iG_%eLoay z1tVfih7>%TEidexHhUc-%@^aBsXHZ8k&Dr0C+Gh`!BM(HAmJ#p`W05!AHWj9IMsYg z=sqG~H_>9Asgl~TX;#X!QTqP?wLnV0?-0nMVVF^og_Krw-4GZU6O4t-z{xsX&|~<9 zB?WBq$n~HNQ5dntj}(52!G9(Ec-kknrvUJ2jmG)xw9(qIx21re^c@p1wkf8e3=e-^ zO{c*6H6s>o9Y$Z>;kCqv6`S@b7!Q@Zs*inJj?1FZ2KNe+`cy$Ik zjo_g?R-}{-HeVSxai5c{(V^w}A zpCP*II-cXlwbC&MERHK*te?NVR2Z<*LAphyU^MNuCW;%4_(CuAR<-A*7042R)DzZNVR4>S_dZCRxa_M_ULCbaov5w9jcz z0pPMP$siL<7@lD)yMn9<*!{gxsbsJ{GFZr|%2ix$^?% zwXY?~YS}m)T|7xe(eZ{JjKCqJj}>(2WOa8=kIcep`?I7GP7^Bkv+%?K;(X1*q0v-{%aKYl5;0_xyYvq~+X`F_hSzIe7GH2Or5Ld={c1f_ zxKoR+{-Q`7Gvo1|RcyhDz;yj0(W247sgULOrFLeVG_5(85n6oLV!{@{%UZ4=j+l@S z5sLv{h@!V{Pp=p%Pm(J(ByU_ie@I(MhJSMs%Pvv@9SmEw=C`EeX`j%Z0>FngOW11R ztj#!yu@Rqw1&4lcIr|arHY`Y_&9IjjP{-rjy;=!{yv4eJL?1Vwe)TsIdYle?>-azeO4)%B;V)DjM2907vjhV<@O|h5 zU9&1wVs4DrTRfRneb&Y^FY=1rSIr`{M_na5A2J2B|S|Yw|-rD-bTnK(ZQ?^cm z9)YFDFZmp+3P;cF8&9SVX>lrpfl(?abj_#&Na_myK<8pC9~z#N(>B%jh!=D_OE035 z3KY(IAd@NkNr>Ko)Zq5C&WHp8&Ipb}o4Q50UA`KD;o% zQDtjyxPHngOMZ5u$K=rV{vOh@<%w1fC@yiqrPyz|FZj0(WU+L~+AV$L8id8T*QFI| zq0g!l^n0$CJ$p+-maWNI=hF3j^HHBcX<9`sqF=smJ#`vrQ5Vg!Z+d~dQ-HtX18sMguk!5uRB2` z{g83${UYOq>v^jXUkI`2&+iFeq=}~w0K3gkcP}>GG@~_5q}#JP$$}a++b)> zK;}l&;&s^LW<$fznv;IQS1f?Jp}b+wqLrBrcdQ{u%KT;9t6L-u zD^-xXk+W`2uSg@zY@G5=WoYtB(}AabPJ0RfpVqRCj|N6p;|Fm#_t#!<7W8sm8u;6x zE;=ywspN>k1a4};2!9g-d$a@qY-z}1A8Q`Y*PI7}Nx?(Cwg&4Vbi;WdSjsV-CIPe1 zK>xH-(LXQ^0eiIb7qd;L2^oO(t4ZN5KIjEpwc)t0K|&c|O+d+>Mx*FxM@kuJKqtDQ zFN#t>ji8tbDyS64xfgPm@sV<*KE@U;@P$1kpW8ux(Vb&g-+!d}9rJ#P?p=MPqEF^T zNTnp@L1SZkJA%3c>xE=Z!hXpGP%v@$XSrO5NGu4Tg2#?RS zO3`7+6LIGyLwQU7Et6g#sA1eM&U$SpIC@n@9Xkbl4K!zJ%wH z18iI|<<*8|1%LkD`qOnI;g#wfu?jvL-XTvfa25cwZ5S!8VgzN*=b2^Aa0jjfn=E=4 ztwIIfIO3bFmzEfE+=}h(%v7R;y2O088%fEwCR6yLe4>8O-O9RF_efuHb%`P2O6DA3 zqT0ushmctpL!w~=?^h@Jt5M;)Krz|(u?o*`{gB_(!++Xj5gWk7FVZfJqISQSO?d)2 z$lD^JO8WD8(5+@g&l9pUXfiFjG)ZqXYw7eowWoS&35z;uC$e~&GH3c zH+@8}{R@Snr|bl22Tovq6`@!_8tTiFiL3okV*)H*;`8r<+6Cj)3}nJayD0L6yuep* zILT?*`G1do*93Gvt3WT;+m?mEDVBfR*|>N8+ZEpSw~5!{VI|7-3D)-hzsLuRtl+^8 zs%O*0@0M9J{9bpq*WZOSUfWN1kYhw*&b#AF39{(3q)-KsCs{KSyUD%qTi`%~^|pwOC%{!Ub)NPa?I{3!T3hWvb!SDaeJ`$6w%>Ls z)#=N1Zi^NKI)H-7OR1}uffTM;)p$i42dQ4Og3iDos(QU5mfr&~2H@o|c1IRONRNN9 z$A5z1?Bw7oXdnqjZ?i#a4Db6};o};UcCD+uvIE!bC4IVU0W$WT`;wzLw0mrsIU(x>?aoxNA_t4&VG z8UYST#y~La(`!(YI@LwBRg{4gp4JS;3O(t{;?hv~9>L=rB2nU}1>kvCd!Fb>?B4kx0rpq?WZ56cch~ z!Zmyd^sNNTow(8wvk5VMg4mMpfB1s8@k95@Zze1)BiIq&f)c1;pde!^N3oajfTC>WS`p5l-O_@#jJBm#>Az)2xMo$1?vuV8C5fV#$D z3EhSlY{r7k07d;ToR9h#mQQ3Y^Rw{CE0C7f<`N_7ngmXbL8KuFDVv61Eoe}BYe18QlOvJj1tueqV z9%ed_js@E_Hol&$Qg<>sak+`^;4$!50<00qbilS`ehCa$6(!bJ^zRXWiJljdU!qfh zfdu3``Tx!L-!JOf{gZ!H4A|(+ep|d04uGJEl|==a97(Fu8I{~93$k}FeZ26K$yu#w z;GP{sfd^bCKnpNmwSNOvM@@Oml?j?ALtp}U-3eMVJE#@hRm7ywT1&1WV_l^cnvj|I zPF)th#hzLk>pn_b3U`ZFc6i7Hkh*o3wrW*;$z1*VUVlGgSF^2NbN40StMYK%)98xO zL_ff{1quYWfQ$%;yw~zUuF0nqI@+G?3{NhgTrHij*_CGsBQ3rXb5g2~;(*?i4GB`( zFw^+gwzl8P6r>qYY`wwG)A+Vm2i$wTDvyO8;Gu1g~7zoq$qy-MWBLRof1F#!= zU6EZYci?cY%2^rDuP|QO7ZF6t?is>{EMq8}C~ZhH52rTV31kROmrNwsU<{yUvc@ri z5XVC2ER0{fvuies!&@E5Etwa8ZdzBv5Z%$8F@IMbB=X|qzW@K#j)q*o&bi=u;g$DJ z_7%u|;WlIgxw=dDAGp5*t$TMwcP*j(lovl9+=I^rNoSeG!2$ z>E2Q59iyJ+8qeLcf|-Rg<=V;73*rvs(V|54J8E9|i9Uk5ULwcUNo>uZIz|$tv|y=mMvo8m2v_1#Xfw) zVc*rZqV%1f%V-CTzNSwxyi!)b@woUeOAoMaHjA&2bKNE%2OH7Xlz&Qj+Z;O`vFSqE7>yC5@R0H{$8a^RH8_hNQd+RMKWEpc{mShr0DM^c zv0VPD13bFeUQ+A6ndlvoFjv5I8);OULxS6O@Jq(?G=Xf*BhfZvw`6SY=6|PmrNfdz z^jT_`#Mt&x>JEr$wqf_Lj*C0n?l5M(GtGG3#t+V-c}fN)>|Rf{YQE6q8^#fit?($j z9Q+2HnCL=Us~G`agBB)A5&FU`?if%sxR)&qbM$>(ZMp6WD{VoN8y|JC=4_>c%%pzv zDof@n+(K!q`S|?2Iv(LOqJJ?~q`%62KxeYv2>`c^fbXjl% z=;yuLu_f6^l!Bf3hs6X2-(6thSgfIw>*Hpj$WnCQ=BaOdrxZj8(6+#W_*jr(L@92a zuyEZL56NpI0@vlMh)?!eNW1R6othqqu#1BY62w*J3ult#vz}7Vr8^=);WbqREB5T8oeDJYI5M7SG zma}0WXoha3-P+et`+qvO8Aj%2N1W3WpDA92*z2x!aIl*~nd<`lv-KAZ&*4gOf5H5p zc%`}-qU-5hME}h%%dOH9OmKN_d-WE)TI4bTIu7*we)ttI};*qR$N8?GD@WX<= zc2!MFnOg=@kXedDmp-H|NdtGTc-o|$n~*L?$rxVnuYVR;E?xc_?uY82^WO~n-i5jj z@h=2r;=tA&WaU>u(&uF_G5i?$)rElT?{BIPHdOHZ>?NoAJwWoK6ZzKZ;-fg|Kp-XS zVl~M}CwRfL#O$8a62e}(QtfZ2>cL8oH&#e1AwfIv06`<%2|C*~}o@~-kYj3B3N;$4?({6BD$TAj)_Lja;(L-W!50|zg zhkh15t-=TLZ+ZitZkVqDC_@T}dS*dJWrY56MW5J+nL~tX(zcj4s*1N_A9-A!ySp2M zNw4}W_gz65+q+Eyv^Mh$|5w>B-33$|5_ZXS%YT`nJQ#B1&T{(!P{70kbJ#{!@6tEk zQ)YXxtfBIf9{xPOz{GA`Dt?Q$iah6IAsFknU%6v8P3#M(7ON0ucSLe18ugXKC*7VM zI&2z}EsJ(_o>ZuQlFD@6-q!^7keAWLTV3sAG=QU4_hJmJVJnp7&10^;O8yxOWYD-L z)_)<2&b0TgH@a)<9BukFX6rGhQO&z~LUC$^vFOm0>#hN74C#VmyBxLG!*7XoD#v1& zDSkURhwEDQo}3)B0!rF_AHCUm!}2{x)Gjri(^~1QZo%3NtF0FQJ7~YZX_02PJBYn> zQ^nRl&FpRufGOuB(?^lUUG#VR%Xr#HwST7o@NsSZ71o*s%60si&K<$u*uA(GIT9}{ z_;F;G#Rcxt_dmUWC6JG{wZx~95Celw*@IS_jQ(C#?fQJ$GP}WdWI;Srcp!He=wQpn ztf5kt_cEE4>ayC6(E+bwJNrr>~(pt!~^9hT)>O#T=?}~ zfDF8(ih=y458o4i1&?jAaDyY?(C=6C-Vz)XiahyVBC9(wPR6)5uW&~b-kk4;W$p+$H?ZnUVm9{TjNGo+d3&f2yHLv(~x?u6)u}I?=(rF zQJHXg+M~yrjWg)gBWn#X$$tV2*g~~YH-J0Wzxl)W!NAVpMVIpV;=Y_dXxe(!g8!67 zs%3LeskFBir@{3gqB%ObW)P?8BSh!F({L(y0q2Q}mY&jj&-LXtrD3v21h`9VguroY zNyA}#)U0d3CQTqzj27g>k3?y=Zd0GARy)wWI97JmZ}Tf=`FrOlVc z$EvzphV%90saLoTw?7x$E`ccU>+f>{;KSNe0QkK2*DwGyBC^)Gp@^Ojn@SOcAsusRmr}@*)6@h}b8fO2fO-49o4Lm7ETSdPg60y>VKhUy?QwJDPej zfMXK|&0#yYJDE~W>VF+NaM^v;V`;s^6ZQ<9Im=a?JS7<10h3Wn9o+6-qnwr&itY|A z2n`{yn>f2!)mS)ijgm@1A2;v0p<-KzR|>-Chy(2Zy2F?slYbFS{A?7QvUx1y6L$Ff z`RG@@Pe6454z(Y))&P>{KBGe_*Kg;sJk5E1bJxidzy_nGm4E!S>`KU}eQeLZ0!bU- z?6X8HCUzMUgV}N$YiVJG1@vk6dhE-_J3Q6AJ*aGI6hhP0)(yCUJ`Y$LqX|Q2YnpVW zpE1KX-|f&D!p7)+P;TF}Pi)B+FjAan66Mr%fZ2DX3?bSGSbFpz594q}pVe2c=t@v* zAPW!aJ5`_0aDOYk&OxQ`lwR(An`>&nVxtyZ2PeD$a-wi@xvhWe`qTqWj2o+$_3N2b zwrvfTP!by@`i212Ex{Sbr-XvDZE5~yRs4y@M9h%E$6y91dxQXmN`KY{y2R+GB6GrC^XSxm{_UIRYda~~}uKq24?^<&^b=|zCGz(w&c}-w_6X0Nz zbK033KTDYLc)`$b(-Sc`th+<*)m7=7rN`?#10h+1sWKXVN9063Prctor=E9Ogt}(> z=(bwrWPi52cQ1N#N|Jhw$u&Y`3`(A8bL&=+{_m~Z(|*-u6fH!rh78KDW_Jg$C$v`YYj;(Iof%&9}y)5}oe&DR&li>Yl#e z0GRb2fIcprvTMIPUpjUKE085)<;5LQ$|;KjRe10~U4t@px8TJ~?w?#9r1W~z2UpZp zXMZeP^BSsnn%%mkUf-+s78qVl6Ay9Z?D;AkYpw=Af#zwCW>Tj!dLps-X~JwM%2TIJ zsnlS~3y^D26w-G>@nVSb(?cvxpV!7m<-6ONz0ZV$>zcFc72)8|Ph1ZysoW#k7OR>;Thb6ydVfVtBuSX?DJ?+Nmy?!+vHb-BahW8GvVh zET^=&W}!}}cN?Ks=ep^PP-Qyp7yNoTz|oz zx}Om|8HMq9Az*|(g`l|L1)8`28z+8Vj&LIpA4(jlD%ep&9A|O)nG0Z$9$`4@H@&gK}G1|ycgib$3NW8XmlVJ zV@1bxqGC(&1x7F)Tyi(0UcxRz;(xA&N7j1Ng?OiBr!xnniSf|A)P5=7*Wi`nJneCG zyw{Hg{L6USN42K_@Nq5wS{Jduj73ap88+Qn*VJ`}6S{K!jo!C$8|Q?BfkR)tAuO2* zh?H^WZhH-20&mCZZ-l*id@*r2G+ADag#L{}q#IJfMlJ90*L$6N=B!#~_mxNy|%#GW#?MivaK}_wWB9c^3~G+-1?g33H1-YHWhK8qq1&VxWg2K*aXT6{I5% z^r{4uR~8n$;ZsCw2Z93C-G826b#9G>yZh+M)mdE*9ujoIW5I#+Y`VLkq1Z2@%=s2} zXT2HcJB@SKv8ic&=F3jE;Lk%@U2V-n(Fw)2c0d}pf_tf)%G7xg2YgrYwtKXES~L2m zdAwdpiS+@c>=}aw3}ai!+%;0E#`SL3mzfK zYi+BU41tEPL8ofyy>>A-7d!d9a>6R?FZ9Kb=oTPszFh0e84R#fbz=Ge(IfCu)r+u~ zEcO1$LboAFn$@Qvxx%x(leafNrwm<>sKHEbbq!5Vq|$<0z8T|o5VM3N3^ISV_HoBq zX@g#HCt8aDu!X($Re!=A+6b*oxQEVHl259#`lE&V`g-ve#bFR?Q;7E4Ai*&S}#wVz(wdUcNiyL7@x{0<(e z)T&7aL$1~j@bHGAb#t@oWrKPnLAj*%AjC!qhG0JD*85&)?SFMO=CkyO z-SO7t3({BAv&3KI7w)?Ao(G11X{Rj*w9!{($#EKt>wi27r|EIc++jzkcA)ul+_p|R zXBQMaKtrF2L(}UmWnAm~(0H4*aqNVcKY6O7QD`JwQ1KGE^a%2CA<&myP}(VFo$!ge zRI`1n?n`mrpC8}p9=wsH@$T|62*juKe;J2zgV=FjKVuvbqd#nXvOv<<<$$FR3%E`5 z^65>l9DiIY`MgHZ*RWk@8cU{*@E>GBQT|GUaV`qE#lB84*IVRM3xpD!ma*w0*57?! z&Hn5CBIIw-rnyzwdG7S(xL!*1(vcN3zaq{&lRlY){xsZLhd}4!r zJW?exQ@dGsOux4#tcwR&2d!&Z#|m}Y5VL*P5`THwIMWaKkyi>l!6{W%g2 z{lE9*70Dh6-8D=zn{jni0jKOve5ZC0yrbxGoW^=m-X#7Qg!{6H&}J70gE696C9o&vzfwe{y*cI&jaqYlmXr>-{dsp0J&y5te4sMSij zhkgoQXT*3c{5Asac*FWT)VXW3##l{;>3<>xg1eR8#a+>Xyy7u;xtuo|n(TdQh6{Ad zqyudvtc|M|CcMxx{g=1%4(J{LOgHVLjSg6FqgR6kJ#jGUmVYE@0H5us*z`hh##cZt zPC|D?u-gfzG#*9y&IP{erG7T&_kUmVGfgrtoT7#;3(sWAbDkcZEg=yDcYpX& zou1tHFnjV@9Px}g0B7~?+pQ<_=>60S<>TbVXfT|pMt}BZ^}hTAN2aF^Xwl`Ke$@uHaHWbY`;k*uOse*`0KIZw^7204-(oNj4kQ-APly1n?u zm-exEr?aa)9_t6+Odi>5D_s*q#uNHn7nySM02gt3R*18-MB?RiQT*LVsxzOjVrrlhcya24{)b;>P(%0_k2{QwLAWSzG5w7;OpA zLGgrf6dyCexaM`^h+EL@Su_z=DWQ-_#ba7}8l?@*`Bt~xF=#%lPv0{26E8ghg{QNyRkZq{zyiGPaapyO4CwZ<3? z2xOm2Ve4pk|i(S@FT zaIQBNnvN?jDp$v~tNp$oV-9jw^TowWSTXPrpRBY(?hF`IS8wNp00>7W+u0Nx1fx7o z*!TD-2u}lKO?U4WUw=DxEBTnlty^CbTq#y@2fWnPQNa3!@ai1~J%vMbpaimW=aTK> zOg~}cDR=WLR2?cXs{33g!Jr8o-iH<*n+}d9{@ITTE8gtNxjMj0X9ho{4cvAaUCsM` z_QlpZ`JO`G!pP`AdUlLmRuUibpQRoBCgr{)FLBvL%e9BZ8h<%TbleB;VF8MZMLM3^VD?!jHgZl zB{0AQG~idC)c&d@y7r)B8Dgu1NiWbDBcUrenU;ivCUkSnU{2G2k*z+4z`|wQqrL5P zF-})SWq0j3;D5;F_7rin-KJYbv(e)UcCa1wO>kA64xRV3$T8PRw!=nW@7usJbJ8t~ zP86*ZvpSJPcHu@T0q_)30h@8b3VHQFCs24v@BJ8o;w2JR90UHZzaw$(LXPktl{esT z<3YG`inE0wq*`00qs#Fz+JZLdo<+|Q6<;W)1r(h3(0|&CKjq_7PCkOaOMJL!tbJpj zqRSp{Q2Vh+3m(~Mh-1}3UspwGw1b^EgLc~83odX7K1HiMCvfAtz=(!%537>USeIbZ z!l@LBdcYzstyj=nJ^5kQz<4gVmh(tz0e>7%`>6I506wq%^Y4FXG@=$@XtEc9)vHH5 z;fT2WR)2J2YP%4%Qq75^#7cH3>Np=0Qae)ChE9JPjOeU(k}E@uhei~@MiOWEveWZf zM1rYdt!9w@YV9z^BS!4m*1 zg9DMn;ey7gS;cH(F=YWdU1E!V+>Z0bqEqQ4XMbr2Qr6GFDf805SD)|yzLvV5D#B2& ze*E`EPuYZ#^?K?>b}3SVH^@_hB$be@jB)I-gRbu+au(ELKoR|fj0Qa2VPG&rh6}3@ zAjNDApAJ1^!$!E-HV1*w3I;jU3Yrn@!sPMzbf0Bv`>}Yx;2|)AAYzTpR^3SoTjzMB z7k`YngPFpE#lDRGHI4eK0wd0gI2$g?!(nH8H(7$P(0;vIn|2fp+a{5&Xgz@D@n;gn zoXZnn*-69kc?tJ!x_L}q2pskl}8z6dmlNUm*Ts^&|r~*jQ3r zT3C2}Z{M85{T24hQW!&hZJ9EDT7P$L^R&-tPXXZb+8=YV*P`lOUkyRR4Q*eQMeDov zVNk@&h787YPE0U*tajs7Nv73UIL2niN);CNEai;~Z+UYplTu@qa_h{R;nGK4059rF1n3 zRO%t8Xr0yD>m4nSsfj{#4EVsR3rvG0b8a-yo^a%!#M3^iJq3WzYybS@)^7uxw%~f# zXaxhpx?)w;=+7Nk1f5wQk&$|Q*qUZRDmesqZzZ;=@Gngc=Tgcp^~mq2C{?OA!l%Ud8Uzty_wT~dtEqS<&uJ7f#H zF?T`}wto*ai47bt2-9W1v0iTwKea_72T9iRW@8U0Us~^}rx6BAb$;1AE+}sHyc!8U zrc*kLmw)y=x4?0_KgzE-o}cmX?! z(+ThaGjY^o=6JyzcqebB$J$k2ulP|crkx}aX}t9DjK%qa_LpyUPlYMS%lb$0{W=|^ zuPkWv!cG>{9I%hKufCZ~zs;L+Dnb(0+q`h!n<(n33{mz*N{aHj7JApe&2!s=MR{Pu zfPZ+SOK40G;_Em?@B~wXZJvwRpw||!P@$!m4L-CvJ(5g&#DZEB9Ko4u3FFt;FH&DU zVF&H~j`RINdC8#^5&WI-&4aZr>~H?f5i--;q)D&kLso+$Qj>p*hpeWyP2GPhtaW8I z%*Q&|=LEoqwWk2^X>H}7VDa{%!!e$FQGenm@9a4viT~V8_!V^`eOEooJWAAaGAXY6 z+zDCY@atM1F_oY|l55A!joVt&+5kocH7R$27wPGpcOyBM&Y;kXZ_Stc&l1k{zCC!{ zL&t6k`2yp;dJsmi#X~?>0mlw$P}zKo}wdH`edI=cXd@1o3&wFcO3QFQI8k-@=77b$|95>#l8Tg;NR>%PJZNH3^VaVx4?LljJx+|FE5@Cs9B< zy0i)6eZzax{V=<>Li%8Bh3*R0nBuFyF?x}YoP6LGORSB&@6v7d&{q_upnnHEogp@5 z{E7fEFk4&xLQbh<38a&oq`Zx<&>i7TC#k}8NyrlNvmN%db;DJ_qL<6&`iR|p64>kH z$hnj&RqTnfJuLc(owAiGG9oi=H^1d-HC>w*>$N!@G1AiX4|@`d7y_NI)8g=!<7Xiov#b7yv_ofFzD55sd)$ng||(KWzniGa#u%`887t@!G`3wt@F0ocYQ$PXA8`c^H~u&t#mcc- z=x7(zyF|l!{(0?7KnKaW0>PRG^-box?+7w_C-p0+EJw>x*9&z#_6LmO^NXj)m z7V2p0E|98(6<+X(YPJYR+->a7VI$V41Ufo60qi@BlU=JZ4=d#O{3-?gK92eIbtl9m zsCXfPkUBupullHtoUDW6e923_L}s$%sj|U(&__%noV^_=r+)+|S@=O_+2E;)@`mi| zC)gr9@{Rpj*ocUNVlDuCV;wDcG>>GyS)I5NV;f_)&H!-T$26YT`QTOm{ZtuR{ ztV!4HC3pkQtAje*wWK~253r-G!CgQ=YujF`3rW}Q*g58-Lc;=UCZ|$VyV&-xY>C*p>ncwptS$s-!wUoHpR(6V z6#*9MZ@k+K=w$Uzimn)M;?gB1TG@%PxD~=!Wi!JHM}Ola0J;Zk&=Q_N$HVy#*1~RS zA|Wu9ZYw~;PZfUytdV%e5IgXwkIjc1`A=Eh{^e#~8Zc z*LK?N%i>>Mck?|WHY7TsCX<96{nM8b9TOTQPA~tqUTboWzLxmb7}F7jW3B80?S?1W z+7G(9{eMz{(uu)KbZoGb@l6Olz!@Ufu_AYsgObANQ&m}ImOJUX+s<{jIzA=e2u5tB zvPc-c#!%-0e21J~Q@y;VUjsnv@X~6P@X3l;rgD4X+LnyP?AO1~O8`HtJq3UdYd_Y> z|8XxeEM}TaGXcG{WVesE$2A&Nn3=YOc2ueWAb){cYC#G)1P`=6)3G72;I1Sf9D)ZL z!lG53rUs_At0`?d1##vEo6b!ft|EZoHG9rGR_KtCxM-n8g9ecxxm*r;7CC^g2is+( zS(rJ@1INHhkS6i!t;P{G@)x_RLaXqR4yBnYL5h6My)SS^ki?%%BHqh+iU2|#_4n7W zzJK0s5y6&L#D(`?(L8TCl=>vto?e@s@3_c_{YZ*4!yBBs+Rs|M{ z9GT(vtq|9wZ`-|!!B&}{>*bmXJ1J5yYkwv-&T3P*?t;R$->8-~G3f=e_SR)xLo0ec z6rKFTb*6!Qt%)s27WRux^7pb7A8XJ}!oLX; z`^0rQ2gwBHBj9IRLj$(z2C=BNO=AqZ9MOd_p>|f|!_}u3y~f-KZ9`#4*-h;48hr&JU5k(r$C1=*c&d=n_FZS9p{BF@?;zZs$$j6Q^-T%hr~iWu za6Cwt0Pf^T9mgO8g$mfN#9EEe#|M=L{8`I!Uj`Wc;0wXlgLbH*!PbeNG{1J3qy2~T zv~T&0=2Mg|;U)ggeE>Dqpf?Ms*?)t>5{NM`m*VUOz0_i9#961f4&1f?hc3E1J)CEd zpR=D#>V<_;d2?Pv2j)T+LV%9~R(rSnR@)tgVRj3?uI%KLrHr$tYZp4B8;p1V|MNh_ z(|*PF6aYT0t@!gF%kHm!th|5YUYuifvKw0V?&bZp?zcr@QpVuuUXbD|0)I!7)O&Z* zR*=dYwDDN(q%5hdu@>o`b^;q>SIlFxQb?x5`qaE?2*shWZ^}(r<&=Rmy6y09dW%nm zyFP|t(Gr|K3oMEgU^L&iT_SX_U9l!m3ThQ$PG@DZ5|hoUGV zxxzaJRsk_5n>U8gGqMGA$$wwjlnctQXy%SLcD8_wy-T2Vi8@mgvlvja&?KcR{Qc+( zlEv@O_es%YP=H??V6YWfF%cRdG6uqjSASPNW@_)Sov&84wBxeF?~gZ+yOQ-|$0BsW z0kWZ7t_ygk{_g%d6{U1Z5{L(S#00W0oA8p|VujW3Mo_qc10A;tsDHf@5Zfjp>p|Hx zQwN8frVK)P0lBvwG`ci^dJWvLj&;LaZpp(a$iHvGT`~td!~LH!#s^9$SZoZ3RkISkrd4+Tn(IEg!OM-gMGy>mXL;6 zy{44cB-#D8)`X2dFduzX<{~S|Tn}nY-Vv_Y8TA>QPjzJVVK8gU{@9#$p%8N)xWmga z$4v5;o@kf@2fibO+VQ45dZXsp_b}E@5hxAQUdh+CJ3|IPL4VKIjt-RdPIbUFm5Ji0 z{7{>sZQ#G=b;UochuP!)thetjHv$??0Phs|hTq_cj{h0nM&IO}e4YnfHeSD(#`q%h zP!?N9p~3!jy|76H1~17v7uY{?n)tIF+o%1S?I{3!TFd;4AFJkn`|;^-nZ>+rjonOH zXzjR@Rt>{p1b<;{yP~}tls>Mw#9!&LtTjA8@eWO(x45Y+!{$)vMcmpmfYItXl4)=OZ zmQdM#CKh^4ndSh34zH387*Ws8u0pBbJTG$gNIo@jA#Ny|o_u)>u2vU;ex(^k@0l7~|PcU|xdn2D`?OqwCig zeT=~P+{F#EIWIic<8#CkUJE}n!fhY=zQWg!xPJ#Tt-w!dEskhnOFoG%k)FwX{g|T& z5n|^AFUX~Fy&1v+AYdqc$|s>i)Vn|Enw`sOHo=v8yM%9iSArm5>mqsSZIU~$^Og!L zyr`^#6Wb{+$=guqDYqNs9CRG&(=Yq8f0^6gz;zwQ$QoKguj;b0%vdoloO~?%s5w-d zEq{HNv)*`0P?KH59AABvS!?U+N~-sl$a27g+JYZ_k^sl+cX&4MyZZ?j{);)y(|+Cd6aYS~{a9#!{^QU8`eW_< zt*+oN8tTokX$kqVT<+TNJdgzd5oT1hl7D{R^J9DqRfL1p+8i&e{t}2Q44&BqAqYD` ze8z1a4JMDmfyjKhjFN+)+zS=z)s44^!UD(Vh2MlG&$&nQQWLJZYdRg9Ksx&NKCUbG z;6#P-fCC))R_hQ)%n93@Dj(ct<8h7~asMscjwG0n#Nhp*F%J>X-E`D<*(N{{V}E@$ z<5aJvVjQdGoU?J*oTA9c0^yK?%yh{3oPx?4d=ymGO*DtlR5Y7e4yJ>|10;EG-|d60$DaNu{UT@cU<7^2X0+FG;qBK$Gp zP5a3!#bZq%n?B$~(0S@jM?>(4`+q|}gdxwakM+C)y87n0IB-4K$_dEcj$UIZgHwcf znvVLS{rz;>wB1(QI;;uhi|rt*J)F2~5pn%9b$SZHwoJR9C59L>?f7vm?Dvj1&wzO@ z^^>yT`e8nmxyp3YwV|Jy3?f0$CBbQR&h$R?o2Fxqps{|~!eip9R!8})Hh*sLV1sk8 z%`|;wSX6BrEhR`xcXxM}3K9YXiU`sj(p@ubxH9IiX&x35$5q_g!=l0S?rq^Y#k}POw8YHEnk%VUGy_M*H{{;9MUbNc zs#3YRbX1jJ#<3c56F*9=-6oFxVSur6>&s{9N{rX=8{lpuR}Ki@pZ3rGZvjQ}3sS z5(P>eUV6$CK+w;j+G_aEe-!=d8)6((MqNaYH2 zFd8ut26Mz&oaB`dN=LD|H9E)x`y_WcK}#>gi+yh%<6Dmwn1!}AMb6CL3s+t;H}2gB zrktp@j8v5B3wjy|^LP6Kz3Z8R+3s9gpT<^V;9@v82}WNyQH1;| zbi378i>?%1Q*GL_gz}@%EJ4ZGzo~UB+A;xW1EF;LXVXNp-R- zYmn=^7}2)pRwL$yx1Wf%wPNU8z@(v7?(%;8Lyd=kjrh9DxAY~k9F=u~ny2EiOP3l< z=%RlY==GJyNAs3UT$oR#qw6T8j8Hi`^k^4mx=)5^bRzcAP0G1lShaeCLR0}Bp+xk-&w4){3TQxk%3 zoGItZ?thHS(em~!guCEKJeK-TmXrqp1LiZBml|8AyaizXP2i}8VE;{tJAb9U+utB% zMk@a;Z9JBl=g7!(I7{d5s9*mmOTRdjmLvN`yCfEkJH}y6?#~8yhQWP?M(SC=vMi?o z>`?2^MFIwYX}xK(ile+X{uN^yl;+dYeoESw40KLwAILf$ALqQ@BHO7}K+g+?kxwD+ zCcUPtUs3}FP@;|@p;RVl4mCIqHf%j5;VmWS)+GCt3Br1)>Q6{OjD&69FG4-i7?uZ9 z?>5n22r#skrcD!I{X4|5DxMRx28I|I#dD&(1&P0}H6m;O(1GrQ^RgbP6#VLTytqb5 zNwMW(kk>n0(d{q`7oB3oG+vD@#na2r`7McS_7y;WT9!oPw-gXxubsMcc6}gt*u45% z$D7Nl)30mfzR5a>}R#}^H717()f(EGiBXnLdB$a zp$_++Qhr6<%X?rTjr{K}$S9_lfe|l{O5<$LO}1P6t~hsZ4^zXCjzO68B8A^}3ecOH zRsy)MKKYc+wTYN!ouW8OwkOBk3B2+h&?5E|S7`5`Dy96<)D)xi)?Qju{E1vW6aCM# z;YpY3x#r1U!P(wiSIX8<|6?yLokqv%%--r8p~(PaV4asJl5t~oo0O-b`#(qFTuy&< zz`7<40xANm-V)HvRy``#{Y&<2m3@A)odN#;ZKa)f7M@~{p5&OB91PHF;Jv6CxebF_Wb9RsDa!w`^23+q$gg|Lz$MO|I|Z?2I#D!V9%jt zEQ1LN_+&Z{MPHKc_PR=-@roMVHB{WHW-02#W2>5qBp|!UVLPteoZ0LUs_(sY zSyk=dk9y%C(6(X-a0UyWDAb+rq6TzD^@B{12XHtQe|#Iih@~jz;zTV{VC^Ak5LNlL zTElZvpYMvJ=_7=9-M`c530x+Nn2!q_ljFQ!74hl~o2sd-h$R}GA2N-rJ1 ziYjOn`{@V48VR!#l@4_>VSZp$Y$4BXGoi2|Ip6Z$!Lj5p{;vy3YNvKO7T?GRol1{j zmWu%O0THp?oNLx+%P3=`dtU4U*Ur$cr}OrOLkSz~M5RY**^Ab0IIz9si5{{5$ObtYwtfqfaSz zwroYAaX^%NuR+x!|0=LI5eA00-YweZ^6Q47j?E@YEdPF>Fj&AdAGXeuc#J@HGqQ*J z2;lyLRR#);Z3vvlr9{r#VZPFc%sZOErlAC@Nq%1Q{@Q>Fut3zZw5$l0b%HpgcoYqW z_iz>$KiuIl?CvqYrVi;G>eAT3UM}a?G>W~*5KJ#$|B2l%Zr1u!+M=)(HoLpjQ{b5u zBge7x_Op_6-eCrAG7pkU>2y2tA(^_6L8GhiiRXaDq#4n+lGH>VP1;)YN5{zfEgwmO(tdGCc$-ga4 zOnw^W|7%n&o!FIYq= z-02Lz!9tGOL)Nt`_xA6(K+9`!ow;;v}3`pU`^d$fomfW)M)->l$QN5ybL1T;I_i_xO1jg zs53As+Z`P^=0Q^G@YXe>6r%Q@3~%mfcVPbZU!3dn*ijt1*8sbEdj({18_BvZ_TVD@ z+LnYxx7Nh@a!0nx8G|>4n9-J498QCj)O-ohAXharJhJ*L`dyAZCN>9a6jpJCtf3#7ifMI4yY-XpRwjN0DOFSXBRO<-FhRA3<( z!Hs^?2SakD@L>C-u@fuckNB}L-@ULGbbtOEa*zKj^e?8A8(-e&Rp7U`f8tAtp&N+M zI{McQI9KrZ#don~qZ+!g6D8EE!ryX$p^({1DWDz6yStNUVrc0)>YDuw@z|f3a~vZA zcPIqswHr2mu_%9R^&mXpBMS!o>e;vWb6Myz3%9$Z^Q3;Tmzlhm8DEVI46Kx>GU*8T zYBdbW8IFn7=&*3}G`J?XDx(h5iZdb*a)Au=%$k6*{@xtED*1iY-Syxfbl(oFMAG?_ zdQ@Nxns&>4S(P?gTBt~p#6N1y>(HIuZ}z;+-S*VC_q=$W+Lm^e%}aSqQc3MHA>y^b zt+Ub0i{BuG?~8@{N}Ay+Rj&OxX=N-$`pBu~e|-5h<+5rrEUQcD;d=!R5wtCBPpKPCUQzkc8M%=fC^7&-Ln#;bn-Pi@fE@)Juo}* zA{+!WkuRzA#$g>fr)p1oNRrpQCBmgJM&pF+?k2+RExATdJYxJVV9HhZAf#s>2^=go zemzo|cYjwOzy8qtB+@B)ws*L>g5JB)ukVi}YN0`^hWqd7xv^7n(emtRh}0j+x+T(G zfN9!|@VFTN{6N@#a+dWVwVQC(dy?zhc#OGhXZ(C2rZ)d?f~E#el`D3NeELXkt-o38 z^E%q)Yft`37+modfO#VM#VxyeEMJCaCsD{)V`Vjp=EwjXnD$1FqL)W$67r61Fgiij z-0fDohgf+!_>|uC&xdSskYSJ1w~6OtH$;-px}DZ|b7K zlHVF(a1vqeDXt z&h9>4>}I@efkz~ql&T#xb~7ONw})=DM^)qg^1leo-jp+#|L-xmyXvf`tEoD=^{jIKB)BWQ$)g z3tpPqd34jJUbj4MT_$lQvZwTs1S$c#ZKBINJNx@QVfA*u>pE~}A;HTKV}~q|qt3YB z^zAgzyv$O@FrY<6S88mt#v}t_hT9Z@;{D(}jo)&rK(vRx>7Kw;b_k|7)Y$)7cMO*F zg052M^O;3#h^w4T-9p<@?URRM7|9NZ9&1yx1JG}oXgM%c(!<}75+Ll3)r z-4Y&jVzp;FuX)s(8CK3MqxH#fB;=UP1TSzP1!8#)qxwdkvB*o}l*csVuYgE#@g za|wsG4Y@FlfNnqRpdCZ$UeexMu17`buqLYs`u-TEm3y;)aG-GeGH;;X&1|CX`Os&y zc@%UtXm33JL88KM<0ozL-u$0T*9Vo{eZ&q=dm? z3u_ec*ijZ_Hs>I|rso_&TTN4M+Qf*kl{7Y`C$*JdJH3B)!|{LnxO8I&Hm7G4jTi)f z5;Kgg9NN3fFnh)1u0wRtbt6Bk`a^cl47TLl+XpLR^_WrrM#qri_plYZczkz_-P|>B}ryjySbtbw@DokB&j&&cQd-&d&@?+BOEsB!Q}??+QKn>|HAyLtMv1! zOmVNe86HBQez}TL_*|gP(tHeWlJs|m7;ehkSAusVKA3=(_YXUO&Ch=;`gfWGZdrCd z1dR@yofiMXam6>!Rkz!G7j23{@kr1lZ9 zG2O9F%(-L&DHp=QlAYx6)(%QUEe=4@$a|UPEPmuk>n-)P@3J@MLv#87%=+biyU*b1 zu>14+pNl6h#Do=@=B3qy8wUJCrwTn0O~h)aCnGy2mI^)UJ3^GVRFvOAoocO-lHWo~ zx*VMv13^S8z2u2`k&#OiCT4{+LCt2v7deJ@<*;i&zaDncO4fG5lm$7tm)bcrtpED> zSfLG!`vf&qxioaYXx+1FDpfVOSwv4#u&2!ajPM*N`p%SkDodn`OZomtcg4aRc_G<*ha+%-9tzgE`Mzl zqJNJb_$xvAN$$@pY|U%#<*}Ek+5KjGmo9l7W<}Djqa`-bk%eoQ+F0?mn4DQEQCz^=@zAZ!&~ob3A8ySb z#UvtC8S3bs9~^13Nted1NNBIcQe{l2y{YQl7Jl#U;4AX>@m*3j=hx7=hMkKTU&E%c zT@7;mzqe`}z9?2J8KJfq!L8jaO^W8F4?WB>`74+0d1mgSwDRjj&fNii9HWJqtP-XR z=%Mi*mijWfugfen#Q3c{_i0UOP<|H=h4-FuNPhWX@4sLkNwBYezfxR^uzsC3ypGs} z)}%VJkVc;sv3)or+xvWSaA0uqBB0Xmu}^9C$vEEm?jG^dm??u6J}!J>iQhFsR0%1? z#ngIGgL@BClUUHf^UaIc``UMlGBxDu_76*(CU@2~=N(Lp@CN-4VP<*iT z2~B(DRiUB8F}vMzAp21kID5gjKojY@2Bl;DmwT~u*zx{UffnQ&3$eGiZOda9DD%8C z-g2{nZm(vkDDWV)BmB`1M)$d$;a{arcG0AuJv26A_$BB&zQ2)^DZ4@jq6`y=&{hnb zm4A-9503I7{{HUMFkf}+T$ZoBYNC!UL`s6iXL@qbpL1u~DHc!Qc*DBj^jx*$Ugd;W zW(s$IZV^!io$f5|aWPmL($<%*U-U4xmwPF4y_93v(X3y8Z^TC`cucI-YgHGHGWPZ0 zX$E>Q>QKlk;1CT7_o*XLv=#^Misl6_2}q(Kg!vjp#B>YS-AsZ?!*Irwb069KR+@jC z@H#zfv_e8rK(MHCT_ta#<9JU&M}Xd|ArkNjvLhwM`(U^G<4+EvAWnp?%I*SHRzp@e zXPUS7*7LMg#7wTud6;M@$O=h@K~SWWN%kE+#fIqLtYhng=2_UJfE>_yOY%VtZxyn| z8SN!9pVNqg6+OWTEdv(?5?;A735i66WR)5jdyTGoAy>$vpHP}9jiQa+MA&j> z%Px{`t`4mu-vc*%mcZTGM$dCz^;vuS@TC#bjjPVPabxe+r?G(pxv44uiyrCuisR>P z^#nI*>n=ZSSO?kD=Z@)3-qYI|{1+He8OtPbl5q_{?uf_gyV(jR_4w>QnOH{}oMh;r zd_KGTQPW%?>^tAam7fQzS!KyGP5nu7v#VXOY@~~)xr$PpF%T9f5?fD7;%-^08a)h# z`R2zBe|fIH`B{mVMO-s?UzDILTQuO&OqHkl^)s=3!J)5h^D%2nM45Zk9iGWC!el~i zHj|s3cGandJcQYJ#esX=b4ewkY1t{7Abl5O14^uKU|@#(odtW4lborJza&0n_^ltw zNUe(X67z9m6fiyAP31kY)Y6Q_0n%Kcn*#Z98+%IM8(sgQDZ%pX8L=1A8(-avMEt%y zZo1e>Dx0;~iu*jUX3xz|Cw;F9VL_8-1-9-Z(*H?ABLB(8B(`3hn@E07!XYb{Em*ns zKz2ueeB+P>kNXMFbsx3<6(5726O$-zMAT;g-Q2?Z5qPuGFAX~=)(T?XC6g6J`cxUU zq}POFVxL)6#J;k@I8DEx*~Rmkbgf@^uy@F5YR7Bw9k@@SkNHGi_VYtD6Yb!gS>_(w zMvig%heHpMGz^tRy3K2qS5`v?;*Jy&y2%0k@DNm zJLu&*#SG?ZC@D%FpG1ClWeM|RA6y&%TBcsb{n?&aG?hSYv20$dU(cZmMe=XWO3RPdVJj$)_w%E)+TBH{uViIW}W zRi;-hl%1DsEW77&h0b6<-UT|GuZ9kO__&vUjl7$;(kC&17}`yAQrI(K)#t{-BIj7o zw~?I{#zY7R?>7zPKUr_iV$jo;5OJW~&^FWWjq#!vO|R9r=&a4w(Jiqdp2=f3gGDVzQG%qYcovP!kIlA!$JN~F=G9463v#ud zc*)PFXAiyRZ!z?@I%pfWNHA!VGC=JrY}g4zl6(+`v5IbX z%U_0`T(XyhS5Tl~RJ(DVe@1c7r9Vd5E!p8ZZYa$SSfPyb-7`=iv&l|`^&?(h2V0>k zke>?TztzFaByk4V?I?gfmo|Q~ zfy3wvb=4XrQ9FlA6V_66%D{r~Qv)HtZ=!jh5H?>{fQ{cKv-fp0p0U47J{z&h)&7R` zM_x-Uukh5RhO?xSvzh%x(x3ZelV5&U3h;j3O{$$)cvZ?~X|VHR2@p|{BDP+L%qpqQ zz3KMbcbZ3Yo5swo&yzPpYAw{b?WgfXYP2{TJt82;dWBfX?*)Gx#QbydUAMTKx2z%1 zo`4|CP6i9OGhoXa(@GM~+VC#XNWUkX=G2H-|N9)iZ*l9+v&B961_6{K>-2x}5bOErMmf>QnI zFnabTWZr(mU%2<{sY-#wH-Sw^4+;kiD1gPv6+!fj*LzE=J~;A0thV~e)MyB z*j4a(>Yjw>*=SY=LZ_9a1ep#_W5{f4Imk$W$h(np29T8UfWqqj%hpD)IzK5kPn1UV zz4T>6wr)P%=qv&|^T@cF;i+z!4-)i^8*ky>Va*i{qTmW+8Oe>mzO<~oM(Nan63$jK z9_r9KpY!d1T}?Jy>wbx^hO7BSMlBB&{T!~0-D!;>>SdXsfkJS6Sv86I9h!C9R$lHK z$w^As+f+LUSbQowFYHfvRv)xp#TXhULNVNHAZtDm(|8D&|M{JJELi{K$)NT7ooV4(HxY)6o*JgRvUmHc(38fSUq z$6YI`yP}(;f8_iTZG6gZ!F$}d^=epH#wQyoSPB*%TyK>&49yHP&VS{ynxM7NmS=~t z7@i*7xS{{Z)S9%|$O60Ra}S1oyrCQY2Du|vv+;{;u7{@ibVWDLQO=0(o7Zcq2!qOw z8w|Nl0d=?qcHc_Pv2T7#M;n|p} z^sJmf5y6zkN;RtrzNj$VOu7V?cO-XzEfdQs55K~hWe;R`|7?~S_9@6ge`9a>B|sz(tjBxL>q z%7El3T72!7Iqj~z9sD|#VOZtsL8K~NaOGjMbbQ_Koh@Siy3dQC#O0T8jem^;%HXEAK4anv9~$lqe+N|>zuz6m z?k*VeOlCr|LU%6x150)Y7(wwM)=yah{ML#GbSMnSCR>U9jHnHB?Sf9ANR!cQ**9vR zHv^)_&@7HOOYFzOAFfd5QX^f@H9B?`j9%3L@DZgcH9jh-XuybnFPQ#C?yNAymiuXc z<|Wpz_v_pRug&vR8dP&fd_(S9Y%)(he?Z>!o|p7>{%V6P(f)JZo>@uUq<=ja zz6Ix@3bgUAjtR6kOW};eHANwItYq0-)B!%hEwTQ&p6{C*W(TViUrYtys~T|2ZFEaD z%|xEqQw``k28G()S%>v_2y(o?dsXILute|0@dCzL6@9l|ag_KE@{UzwpdQXu z3_AqPI)A9<^+@x@+e`zCiY6$Rx_YjCytvsc1T&DaZqrKV!1yD;K+dnCmwk41#@bLV z>c&MJt#ohfUFJ;MPNM5VH*22r2JZ8Ef+?QPY;=9CW8>&hQk^0B#C$5r&rN>A1xzPY zpy72^vexrDiggaML&ZT3AVhZ0W9ME%*1_V5{#y%pxd#+<^M&YPY2YB&<5l)==q`ZP^%|E) zl5K%kI*L@Hg7O$vYm?fhT!?Vp`-zA)JbrHxJOlS4)Crv+>g7d>!syq$eaCwAgC?w^ z!=u1!&Uy85aW~}&Xb8y>4Sy5TCTlv~Fytvzw39MNOwMH`T{ycct2!c4FRoaDH4vN+=wlVy>iZ zpWWf{GZrR9etzHdB0G-RR?+nKj#Xl5Ff-Jp&ad`#KXIG#ie?EY3mTg4{olYZC&z4M}*H@fIARFZ+3FXCb79d)CEqhyO-&D?g2vUyrxeJ$|8KWp#jg9`cMkok6t z;>TZ$e^0ZrC)H?i|9F=Wi9udk`Fa~qeR{0s%h63FW5Hpr`DH)r!f&8yc43}VxnqOxax%8=0k*s+lL zl2J2p?O%ae`i}PZ2o5yKv5Sjb|JEl>=RFAI=Rq6N=^tK`bxtS$Q}1h--})k8&tC9R z9eI}@y!W>PSF22+j3fH_CzPUv6Levd!(y zrNjm@aWp8J9x3@m`Z=0UT4@46)Z!DbEfKVDf=`zB4ByFmkz`yxnPUU5Bb?sh? zM~?dg+F%Ox#U?UQ9CMw`Q_l1FWk+D% zJ6bb;b}&q&Snt<;^vtX#Xu!$soKmWXbY!64S9&`!;6(&P=j-a1BRzS5X7T6^!N)$c zz5J}7H|++q4(J00?LVQ=<1&JMCU5;3L8FLwbHq~hS4AEY^}0llCuClYy`n*HCZUUq zYxVE+B7@y&<{-$X6bA)N7dS{U)I%UKVxL#Hg>-*0V>zvAU(S)@L7u#qE8J-EC;r;efEa#qx*4S_Bij~gBJ8kCeEj_5QdH^6e)O7+(V{X z3CQKx)FH9d6egzD-*MW^7GJO17r1lm)XnLwtXG%qCBBw9()j>bJF*yKa4g5Lb@9e) zm@q%K_Xk%j!o)nor^uU5qD?cG=__x60Pv*;p6ObpLooR-I* zmBt_&YoVwwT9ZwWLq>?)KBSEq)z}7F{j(4;~m5DdBZ#CD9f9^ zfV-6dUJcO&f1%*kSSiDoYg;QnqmvolVtRFCY^tfXufi^?J+<+rzi+kV-ZE^+L{s4$~hgFl?t^`|bY|)6GcS%#zYd`>W#I=n@1Av~3Teg!~5G8?4`wWlsFC z`4Ap%+)N61y_j!lt0G6A+1GX9#+zVClDG93OKq_{j7^cbiIEcRbkf>f#6em4sbX)& zy5(-9*s}K_>Php7pSm2mtfxIKgUUySTtm?9rz3kF{Yc+pFqoonovb!`-N+=TAPjq zkNfb*ndNk>G1^};Et)$?^_fVZNEA9~-t<#5hUPXjgx)K(riVpk?F$8=}yl)6~Xu?{@1s=LkwO?ic=*<-;$e0IAIBD={8!)37;M1CeeI{lH}ep0q=iUSapYGOsRcD zTT^!Zxi7gj)uAW*_ONv;Z|;fXHqJM=tsyjOqL;lL)4W^fUWx4D3+b*}1%aW0U@FkK zY!^fydioEHDy1J1zac`0C;GiVLy|j7OXu;^ST%Rz^Hq?}BhUTQo>fND#gvhSaDb|N zX143Ao75f$-Xn=fpKNP=(qk@+o_$nW7tfhvfmqzi`;(ZbjKA_Cu|5@wylv&l3xbJN zzwwNK)sit{YXm_|=oPKQ!cIx4>_zydlMQ zs6OPU)RmYZ8x^AxN5w2kBF^wroLq!QpvAqZ!I#%HC!1_^GdtN&Iq@g{)E6PRDfc+f z+aFXgNCscYem*aA;c(HOQD3?21Sf>_zagt(kMh$X>@BXkUgfZCuKg*#-v!%$nqeI! z;#~rC zf!9>z?-1*ca?Fov+et@yskJu_q=@@;csJxN^zJ)+K^NM4jVfw;bfXYOb4J?am)=~j~w z9V%sfZVKTsQOF@RX?;V6D$Lw3Z*xPwf4%IbTuWODc^$H#!_EyNNkwo`+jwzC73tan z3+eJ;e$a3QX<48rfER$ep_UTYzf+?+fcclcyTR!nGBMd1?G-wD>9K6K$t% z@7FzgqIughWC{h;>E5lGSpQWm zt)>R{H|(`lWETkxou=r{j6lymPX7WSzF{OdSeB#j!OPlZAV{I5wh}B_ z55sJ9?`S#i-zys~@>2R6@Sp3?e<>sh>dCcMyZ2r?Y}junS;#St{vyX{~ufk1Q2t(XFw>ldkjr6@4ZUD18O;bzEOiO0zQ8~waQpR=P0_veg6#1=JrQ0QR-()Y zeorhp8d#!+w{%R;nso3v$snS!T(cNpH6n@KbU~LDL4_tYRt`FfSa#R*SWWPL8@OZ_ zx4*__GmB^2H>;)DBwR6%AlIcw*XDI+lPv-8K+wg7S=1T=K1%beGgkYf7Bid%r~TX~ zH9xxK6j*ed?Z#B<1kk-xvi99%bU@;J!e|7j#LHr;FNa(Ry3($;VJ!m7wZBs#``!K#f4H(+)7; z$lsUk=J$O7;usI_5#P3B`v^4{k6uf81u|S7bcrHMh|G;7DT6iSB|C)NUVUaaR=20C~8Q3Bx%n_ z8y&_Fv?-^hs3tZ?fr&J{rMNmVuD@ujel)n5d#7q~q-FKv&A1-4_8bd!-IdzFdFuoay1DGB@5hm}+ z{orCPFY(xk68y;nWzFSLr3(&K2iMcU{922g94tOmZrSM+bi4_GE{U997WJ5k1-VFY z2tB@b-+V)=SM()zf#}P`ysoxf1s#PO)jV3U;mGOEC(WpwL7}s)Jo&rvs{qk{8BD6) zD09ysNt$5B_1KzS0qYjrIzZrN&PSA%DuN_Qx+2tS*fMm*CBJ_+x5`$An2x?Jv2uZw zZ+hYCz~PW09U=`lpZ)GIcTHr-)Yu|(=M#0@{lraBNu1P}y?c(IC4KfR32?K)0K-fnJPx0ojHJG8ZVj zvopLOmFk)pD4jM&QG2S_xbBgnmI2HDVd*2w#ePL@EN{6^^$fOP_29>Upfc*1ryy(o zU1`E|p9N-EkEovmo!&A3okV`UL2T~je{fp{mHm>wp+k4_WZ(EM`1-Q=KMFIo^&5X> zudyT;2XB&PZXIr5aig+ws>?#lEVNg)W_1v$L!` zN7sh-lHGx$*b;Zx!FSkjMRFUq-*qdyt4pk$)3cdT&GuPzb>}5%c+v?NuHdQb*7-)^^p%pnxbhUT zq4ix+uxa%S>~e=gqvj@@=yiZxWOiY~l>jJS?A9q@?~}=>kN5GDe}T1w`WDrgI#26> zfT1Scz4%15=j|*7xnE{%Dv{x$8@JTHE2Q1+#Q<>WaA8JwMI;v5=;+e98yl_zro6hb ziV|B$8_K$!b7?=i{F3c=zvPueGIKP9V^nD&H+26V&UPx@yH@VM<8OD_)@t%Jypd~M zj{Xlkwa@$~BKQig3V}-vcObkU4GDJ_t}j4C*P3AO4{R>k0b!9!H0rQ>Zq8)zRd%;A z(B5%3GtTSPCuXD)AJ7{)^*PQ-49#8^_*Byb8A94jF2!`s2;MRaaj6@&+T1HKj600*qb{s=}{|2jPJSPzTN(@`>G9>%W;>c`qi1# zt0W8@TNO6tR;-AZbJ~Q}oxyZ+B;PaqEvw=l@w2aM|$b>qFgrkmPf1!@7TNl@#sML(E7%^U~At;Vh+(yH>Bq4 zZU>ESBm5r5F+(c2qE+iEi&|DW}IqgmRuFP4}7$xzDa< z;_5#BU98AHPIi`Wpbrwncn;9kCA|tBU-JuQ<9G1nzNNOVniLkB#{hET-cA0zdFkNB z&Fq9F9~XRWShma(2xFd2!ega1HAuIYG%j6_+RS=>IVUj3N+oueY@U9QKI>V3x$;q* zR{jblal>x`jIWP-f7r$JOC(nX;+Q`++t*W=9)YaL-to8Q)io6gOJzzXsF>= zd%f4dh#UBzAts0^bNBd2-slc$Z9lYb4)8fp-q5Vf2BSp}d)d!uF4L>fO0`dMd88`f zm_JCi6bjG_me^ka(K`lxd;U~e5M#ND|I1uaS0AVOEZ=jTJxo(x_`zk=sB69r{@_ug z!!=>3BLyPuVR>;SV&*$cU1=|5yf_;RaHVN43fZ76@C<>g-ZL~aF`}^I+`D%kPp3<| zE7{-8E%SOJ6V)=jKUjcN^>Ypuz{=?8zB;8y=S8u zM@pt|S(czK@u8QvG^{_*>w_P>UR>6B4qS_wX9H2%cYhV*1n`WEn`io6=MNP@?T$$? z_sA6;R?c}00@V@AG()W-)3N0;?GlRh0=dxo)L1WzK}(5A7o*PL(;dmC+CC*XuA+ZQ zJdTH8h%w)~vdzlGO^kXxnDVa~7&t#u`GMc>x+rIa!7XW0bN)<_O?LE78TLX<+ChGK z6Ug-4eptDjvpp0Yq^cn6T`i-tfckk3XxyDR$eo`LVZut0E@$}gu7<7H=v<)cTHAXW z=Z=f9kRtPqmP$Xv8#S`ZLxELfHsfo7IPrcjSfSn+4Dr{7J-Efg zfUT6}`@4_-mod^O;0XBlG4({73e*68tH)f@_mn>&O;X_{vMHQ_=^r}e^0uyjAgF%Kh*+0kv>{1uJyj*_u8MhID)%90&w7(|?ih=RPa1E-|I=XvAgc_QL#@-0 z>u(s^lHXxwUoeS*G9BGEKQW>ZwT=wEIWy6J1+_I!G9!MqEy*}gS~C?3(DNJ49XHvArHpF>b|4-6&Zqy;*+PCh531y|QW2m}oJNYQI%^%zoG!$KUf3 z^KDg>?HjT)nmQOC&ECxh+})S#^t{B&VdLia(;D+vR-=Jks=D7xYnhyEjQG-7Zcl?s>7JfJZn zZjC(5tv%|m_|8!irnyRck^-Y$_|v ztb0zo?hk8405s4?&X(`fjyE44ee19yd9SF0|Ap;W8u2<7GdTHp_aT;Mb6YJ4UDk{> zN{j|1fsQNB!$P$j9gWApjj3>Vxv1+cRkq~^r4T39+{;}XI4TTu;5{n&)~n+p{4Y35 z9t<#kPc@i>u?2CdFGn=gKPEhcpWlYe3`otdy(3CJC^*8vz2_g4J1h#`3;}2>36Y!S9uG!(%Hw+Ll)`3eMf_0OQBv)hhhrc^Y4@XVg?0!9T z_4eMz&$<6yZG1jkA=aof9d|b;WdH0z0LTGAZC$8ugvMXQ?=CU#=?GPrXU4P2mI~Ay zG94LKIF>UFd1vOF+}z;AyE!qsN&yRL<4j)vE z{#CeMv_vc~2ld{ZdY|Ib?Dla5;UBbes2Gf-20g4;m-y@;bjX^Ww56ODQq*ml7{1Qz(oO@8@ zwu0B~G}e&CImulxm-3G1{q3>`_nC?PO3Y8C(j}dF#~|Z{Cb~_YJ-4f!4M*>}{)atO zwjWxIrE}p`zE^Vbdk)>sUJxo^@XUYVa2K=!_b`waUw1e>UybeDb#pE9J?&rzN0GU} zr+bHdpyrUwtp7vPTlhu&KHuLU(gG^oA}L+cAq^5scSv`4zUU6=l9ul76j(yKS-Kk* zmag0P@AJL?hk0BxbIm!=Ghi1M6BcAhi2U1opS$=HZlWo|M@W03NfoCjC{ZYO(PfAb zVeH)K&!f#?niW5n^U|5o5ml6d!gff-c7OHNevMPUGdO6K|LA;n7g2v@xnlek&VK*J}h&0k<}9q zRn3C8t&88bvT-%_>2dz*ivU3^u4UL`-|f>p5<1JncL_^UJ-<4N ziIf*`-9Ugf#;agcobb-BpW~m29_a%5=>;ew!RyHUhuX)HfE)Gg?5l}d;K!QHD%4pc z_xyPwbH?BCYQ+d9$D{fRdBmn6UF)8%z8blq^?JE4Q1#w2uCHzC&RnUpjsM&=#UgxJ z?mZ1AZjKTWa>FP}-7ucM;*y)AZCXISAEvsB*nzrGy`*I;2yI=GQt^_tPD}(pk0ITn zAMc#w{8u68_G zza9VBMFbIgtu@AQdKY?ojr-pw_iA57Z{oKJo#5_nxYxNcU)K%WI=LYf0@5yo==wmm zO;*$E3{C*^E1xJC`?lmZO|RXO6M3=7wI9juF(pNnky~u0@HKE*dTbK4bBoYcY+@%n zH*%AgD};yieY+nrE~`$Vu1J}9N-qGMCk@9Xj#FYKpD23T@S7cXozO553Wp~jL*?_B zDo?IzrMqTGO~W(0a{hL%7u{WdPJy0=giV>$ZgV~37`RW67!Ss*;j+SDK5;J$~d)X*6PFH$XQ9`}`0*TZr-bXhd^-Z+pb} zazS4~$d^TOy+g*h;R3b3xtSI^W~@j9z+N~p^awPry6LC$ zyE^byq7TAPSPd3+$i{Aqwmsin)Av!?-xlA8wOX7Y&OkM6W%i0Dd9J)cvd@DakafSa zHQ9knN?+I-enU2Ax6u7y(fBH|D}i^@bvFQ=x~^ExvB{b^^SM)_0QQB8cP3D?@Zm(c z89IrV`yh*e@BN%9I!|WY<+BJmsAF zd7F1YN0M4XONz zh_e|dsrzKOJx?B=ek8!W7mac5UIGQ3P=UE?>xV3UoQ;!WuC4rXtb}P!x@~t$si3hJH2?pk4w!t`4lBa zv6NFS#hr{>^*xvzmwgAL8wr5A(OtMxU>Z{;)Qi^E#>ypz&j8fUfmaNDfQqXZ{YQm} zKah3m2?VLzbzy;(#4?x!zu($H+~lys%BWjQp~T)Q0e6-i8k^E}{Uof6dVJW|m_8Ov zH9s|K5OGBcr}0c)vx#Ya z8T_}Lhac~kIj;i0UdNZ8KopyH}>9xCM zD1QApnl<^t!_eEqs+?mb7lE_K;YB`~MI&XGErdWW=mG4B)2{;B{7EUh?R?H{w9}6G z5IM*7M2nj??$hHi{B7z?{U!H>KHQ!{-QYXH8^*9bp+3%TJJy>9K!HD|GY03>fQK_f zUr2cAw!uME`=VK1o$#trH**bI2A;FLn1LfeNu0h+#<%^B>fRW6!DZVU^nyWVYC2-F zNV4c~!#keguknttK&D;j#ZNytJjL=+Kj_gS5ay3!wrBNR0l_bReJu0LXub+#q+5{G9uhx~Spn90o(yX88NZ2m1fUeg=JaL_OfCcY7?y zx8o&PcySGRi$&N3Zgkp`4n7^IBNpUD^rOe-c2ZLo zzOWgfVA&abJb(412p)%E8uhEUXQ3TKj;l^5C3n%zC;@j^KIFMO|}E3I5C+ij6dl>h4AHo#a!>XA@}FjiDpCa(VB1I0{Sc8;HX|jUVzUjNgJ_3 z&E3%(`*NM7fvr}d$ai5sKHFdz9;%-aDWJ_VTMd#LM8&u5{2}>RCTLG*h=>E^J-cy%RSjUS?O2b&4?Ur$e9; zN%u&=ETo3mxx-HECC)|^RQ|kpK=*0rgC%lw5*>hHmMBmr^~j<{5;vwntkFP0v5|>d zRR79;wjp*Xyel-5!N6+u={N6>(LHyIXgh+e-ggK|b-DQ5%z@pPEUzvXk%Y|4JD4|6 zP8{Qz-Z~#L$FBuXsdaPA_eXqIy;09hG(|uzhbX?3w>W)4X0~Rcct}h+vsQCEPZBr)0FyEQ$W)lxJmjJnz zjd(w+v3l1&*748SQ&FqwIU)L}YksIk$I_LGNPXpqlnu5Vepvc9RtqJCO69EdVGs^WOV zWF<+iNJ8)Gj9R1((pQn7zs8Q@^gW!udShiBexqWIXQOsJ9e=;P4&DyF#^fkx!Qiv8 zbH0Pt&y1hFz>Ck<&-CGjt^=$1zT$Bj#_3O0Tu#bcNk6kIXt856dGm-U62G41dMP*8 zB3+ApG=qDV#rK5RNH*g7US~!E>$}vkQP#ZVEp+)S+-+g?mOSRfai2`)F=;Byb37GNOwS~DZm?Mvt92;9bKXu z*@`|akcYAjnNNbIbjDXqi2l>|R8F}49#t!=hrjaXrmt`M|GsoUqG2ShRp-KMug7r< zfad4F34RDKyxqf-EJxq;J`5a_0>uFz9gy#}hdt@4G4b4evOc>-$WbTW^l8j?>+>k zHzEi9PW~XcQEtyncH%boHQ)=B!-t*nT{`xo71{aKwHClBavKXIKA)X!YC#*1cbJ=e zUK&sRHC{b`CYwMg@G?R`aOV9&Y()H)or(?!z%ICZQehBIB<8kuR6(w&Z8)Q9puhQ>f>y|I^}JPTuH z-{mit5rFZ)Ya{FhdBvjEJiOZe6ML9<6x2&BwEJM?K-9!j~MvqC!IK? z_0)hBT3L9b+1qQx|Eb04p~U_I>#`r93uN}djpKd}q$fD7wV!uWo)J&gG6ttur^VSh}A>mrBEpN`RbWLz_ zs-qQ76E_&0&>u?NjAX(4f+G!PxmOsoF_%b69{>%vZi}rZzQF3m3~6q-$=Rh9JiPII zV+|y^-LtAw=RAreFc;-Ncsvfxlu#U-g~X9@3!l~rLCB1L{4(QodfVz)stFin@#gJo zV(_G}_NB?@K#WBdu3f6#)`k-e9GO&Or$X+h7f5P?*b5LF!FBy>i%ubof2s18*-p*9 zOwymKh0;FhakZ~G$Jgxpky(f0*22MtM>0hJ4hHUb!f;;)>Myr{TYI6&NoQ9qp6iP@ z03P~?=f>Z(R9d6zvwe^W(hNDL4IP z$gV0~%6y2cHu1ie+xzGQcFBtx)+e{{cpvVoc-@w~X$52w-TPgGd;ZLsFS!RUSP4hw z^wqe6o(q#X>dEBm7kDafZ-gD{6a+E$;C~F_BJ=2ddSOqcqtr}=9RLm3F!8l3ZbA>Q z-tEy#E8j-MsCT>IpGq~643-+1IlfPi3(M6@ZejJe*Ny+HDwH2Oq+1_2fg^aL?nmg} zIj#B%qF!g^?@HJ$1)REangngNPFFFFnbA_p1uT1K_ib6F|5%?nN;dss!6K2H@vzE7 z6bbd>nCswo+ynj2{#+5KH}A0Zd=lX^^#XBrkzk_9$6kYmu{VsNGfktO zrfi?UHIJa}7}VDiaa>yjNM|8Sq*enF&*PF6PyLVtVhylvAFA6xxSK@@TL7@Srm3`p zO`JdHwO71+Ul%vrDVqum>00nI6zr$rjb8#YvrJmoa{!2v^%7!kIVSmKEp^W|vmc6! zM5qYNo)(V`!4GXLejytSqz>RCstvfYsnfbO?Jl)26&3u6O^QcUa>rW5J>v z5(Xwe(b~+m4S7cYhH7@^7#V1Ddf%y^s4fS)fS+J0CIgo|s&a*M9Y?}8f|(q3&2tJe z!J4169l#tqCOmh3dW>|@s?WIUSm}c;$~r6N;@`uBbQ`S7Q%8gaz7??4u;d;Hu> zu`U@7^8SwP3x^evF+xmJ`LVwshLwVlHfT4KX7tK6P+{Y{R;bSk-pRX6iL)70q}ovt zunj-+%O25>7C#Q2K934 zMtQEni+(%4KW7nMdz#)py?uBIO$Sr$a+;pJ(V&rptC~qTm!n3d0*J>QX9;Eta*~EV zj$9ew$g$_?+s4tJ{q#rP9hT!dc}~%)Gw#3Pw$S>-HU-+|Mu)cqrmkCc;t1O@tTZ8n zGLIzg^(&tyk+t1L37?7L)0L&|`~XhlnE*dwn|qAJr-R_yQ;&!7VO6%s)R`a(771hi zDh0h+^Gu#krDgWk(-p#o%_ff1rfjv<97L1G!f7j{hD>!Nxir6J$zhZ2R2>uc*fu|| zZ1bnb1jKhVFNWQEOUv-ID;aRuE|4ME!50za7nCmZq)R8G-fn+=XJl+nU4Tvt<^+TR zlUu@LEvU`rdI%0u(UD@B(Tb{;`$UD)?7{rv*iMD%7=B4-`KPL(nW=~pl!32V` z@nXS`Do$I9T~2JmsZi%Y;4nFMQgcbT!+l6%m$DLl*>jY*RKVx}Df*z@CK1bAKDY8TdzR^=Ry{TGDX4`~FHGV5?0OAdikOxt*Nz>kFwp()v?F zd*hgCbaZiKRD;BptI(!s^j2%X^G0Jp3CqHj$T>Zws*>1azQgVADpU8cZ&c?9wdZZF zd%qF(3H;Fny*)Z-KWsiToOqHRPhncNzk8J0e77`u$rer8reXp{4n%c+Y}{>Ic`u|J zCB~g8$?YZINtHSP)!ddjb&BCgCC4X;Jd^i~_rSYQyV!a8smZq-ea+8%-AG{8e9(a< zsOsbSLf;-ePf;c6pH%zAekiE(#2p6!tv`)+uma4PvVF0Gn*6;C)}j9$rXy2NbU)ln zZBl+a!xCQeW9b+LPzLyAd|Ki#WBzrhT0%67CE=)A##PS>L=>AD7@4f5bil_G5Lzcvd#v)tsY)?Fz z4({>+7Pz+$X#}`jJAvwlKp9aUGV_ZadhZ6uz(HYPsiQW@zzD7L*YwK$%dvSeDCwU| zf2gQ|rjwd4`-pOa;0+>u-1+|X%ouS^o`aF(JihXNXElrSf8T6JYEwKn-XTg8=D-p3 zzT3OwC6U<5+>wolu51ydK}?bMAFRJZ<_b`(c?Wk6w?tcsWF+{>95D=DPPEM>f=J*J|4XTwAZ~@h^*~v#p86MM8mxL|u-^Uqk(lm!brC^u-Cn|=$ z`em0(%o%r_3CJ0_Yt88;L6)V@xWb<33YdkLEql+>I;=K@t({ip8 z=Vt#B*VvxQZpvPGo@f8yckVAfwH&9nSHt(=mv8&Mlb|%k2RbSpeLb82K6BXFPl;kY z`$fbw*fC7xftw5kh{j(u7EF|(bGL8eF=OM*z&-PK>=ktjOd0zg=Orp?J)z_?pDnp1 zAFS{aVTpjOtwIw|$d-P2!7)eeHV?e%enPEXYxZx=r2smqY?O*gsA65uB_u`%S_iF4 zFB&ry3z-F<*s-VjV}3wKu=uooxaaNX3g7rRZG;qx&-u$aF5X|$BH(p=3b0^HD7()+ zimN$RQM5}M>1o>KGx2LhOlAiH%u#%`9y1*%Hj*yov=|nbSD-> znM4kC^CK(#Q*|BgA>)R0Wd%q_)i!+Gb>7X}BBoZ%I$L(|gs#*6TDgnF{USO{+0kr2 zRGPeq1+{0>;;R1iVm1ynP!=|PIMRtJK0mhpe{yh-VWkR0PEQE>eE91XbQ4R+?uB-) zm_`?U$OilmaOq2*OCFOK^%rjJ+1od_HUMo<6n>*;{x133YCCKIs5?1v51^3R-DUa) z>`hIDzep@hb~&+&bnECbjQo0X{wDMJcu>U=v*g2*pYyYassd8^r{Uk#mj1()p`@lw zYo{)&X1(ztA8G18`~Mq$Uu~wf1v@>`q5`4587}zbaztCg6^W)!IbEx;a)v}7=&E`v4+m-*c6g2OJSovQo z-od7JQrM>7)JwhxP6BbHUL}9@o|I^AwvV~Cr5f)NxS2HI3}A|(@78Y87==$2dCP0G z>$4I}M!=Z{>cquz;en{vadO^kHN9y>VTc(J8x#}qd@q&{0mASrqt;YcuswRhaf5nB zSEefXFT%zy`(;o;Q9)#EXf>@Ds(vCD$n}$;WnOXNvB0g2y^ME|r+_NHVFW^cyl8T? zPQFjyH-&eoec?K)d+d3gR+efbJ*rjk3EM}(VU39)gnOTsEuwCpetMwX_k*wukOL}W z^8Bzhkum}W0as^fpBU*Z!+0yvVxN%i1*1kr#=j{Om#ItvhCWSyJn9bEmtEB2ejOg} z2zwq$SOg$X;FeJ1Txr_F7OWrm-gXUyQCi9~VgNcC?Y8CXmjw?W|< zXMMFtHM4fllZuT^Lfz+vFW%|h2^eU3sq!CjSk5Df0LQIY;6750u&2dOE=9#d%s^6i zNrQztA&RYDa2D9Hgf|=G<%bW)?cyD4C&V)Q|K9>S7)$PaGrkMIxq;G>zrO5(fmeck zK5a&dCGv!??moA3jyMLi1Y`@s`VQU{ZmVSAu{E;wUD@A6;J|#^9~ey@%0JbdlJ!#n zIpsU`R?{}CwQNMBBQ90MMbtv+SzCPOB?Sc~e+a#1*ri*{%sL_^t)2tx)Ztqu1N0~A z*B}tV;rA*fjl;&!5Rj`~f5#AJI@6kyvO%e=Rdwgk(28ydVU%1<*fd9(fPjvpngsH@ zqPO2o6WVBEFO0zch?dY+dEIHS#RLqP(Tg+6y?likG={yFRhI-G{m$7^t+fTSNr9%#j;di@+EeBUp$E&e>OOgzM1ws7M(x z65c-iZC_?n6OUn2*_;iEdKKdquX_>Uv4WjWO5V(`Hh$h3w)>fGWD$mqQD~dA>9U=_ z?mo%g+}f9tr$;8SB#7Ki5b3z%E*1M;bV&23c-1%M-X54xNwkUo#xf9cmVYmIwiRO) z;>RWTw|pDgqNvs-j27k^Z%qea_DsP%Jhlf)WIo~RV$ySviBDjEXWNmEGxU@FaKHjO z8?-v*??l9Sw)u%QnC6;qI$Gf5$Z(p|Rnb?~6|)Orr@x#u{U~>z{ur&#TsF^dK*iPy z0X?e|0T%s%COKdp5iu#AUidZ&B?gj8-{x|g+z%EbEHQ58KeQzQTYfyw2q&> z3aXWmN7r9^z8p?7H_`kII0(I@nRR7?Uu-w%o#gb}>hy*q zZajzl-dJi~!8F)ak|e1hF%ztgIPUJK%&UoVbyj8>??f_MuN#O=ZCszz$dKc>mDM2eM-0$sdmOOE8hRmSAAtJtU4qb@Fi!ZlA}mI4 zea_HH#YaZ69YFI){Fin28fvg_c=On|*2e6X&+B{eKczmqO@iNWMY_G%e%=t8f>QFg zw<@-KZx>_=9; zf9Rfzr&v*O3^;x@dh^O)+m47LKxNrPhU~hUO=5I=)Bx|pIE%HD`#09j#eYjdyk2cz zqI+N2@oo_1pc`q#&867QWlcmXn@MkMY#auOnUoGT;&8u=U*^W4-ZkNvE1lFDhU5%HRttFs_e+b=g|IhPK z?MAJsA(GgrgvX~e{CaP*r*wIj4$cDZ9gmw2(N59E%QS9&7qvfbAjp*ei=)TuMpRpWkSQ4l#vxstaaixt1!M zKRYn;kJpQPCh=1rv z$SQkhY`rzT8X$|wGSi^@*es=YZ7>5;KUQm2KfzM&WPwNs!^LP}Knmdca%d7t)74i?^QnZyw9Z z1nOFSXdW5$8mb3Gr1JYK7tNvk(O7_9()Lvf=%iuGhGE^j~i6s@aXS#Fx%0BAuzS=>)ZO@xBhMw@fo7~>-0lMDp zT_N(Zp!{HZheAd%*3PvzzFsf=7jk6mOl0BT2k_^h;9f)o8Jr(Csy#)sBt<&}^qA|j z&k?0nYds^gA6yVWLLX z2QoTtj^<2dSV?I#uv+Mw) zS%=#)bl+K?X%7|M=JHqgK48h60s(xB77R~v_fH69s0M zNz2bJpW#Uu&wMm2HHAqq#)dC9+^Zo57NtAFmcR8zql0`(qqVy@V%1A|5qw$FBW~-C zlZ{dBN;1STd$s4}nb6)1$XHdI-uC`I(qYVBcVgE|%YD}<2hed+&tu+xExtkhZA+nY z(dGK@(UlpnUGS^G&;Mvr>dvdiqcWHzVLICW(bx!n$mi0YpQ~!V@SN|AhdKR3G-f-I z_^6;H^ivpPT2@tquisI1+m}^}?O38x@G7hRo$<+`7DkTGS?aWn&iE(w;07X(y@nzD z>UvsO!q|$JGmt+v5kt(e>=Y4pKYuFp01I;Nv{N$wh-@sHkATU1qCC9ZjqAJ;+k?{q zsU2~3KP&dallfH3B2Urhpe(I1wO4u$61KVM=Hl8NrfSr4zNS}S`#)5|N@01jt2~B} zf@qmp=9REV$73oPw;$xF4&H-YR%()eNX~ET45(00_ieso6?&5tJ_L?~y~yjp!`-9jCwYRQqsH#Iwy z7GNo`{wn>jj3cBYtoE@8BeDwDugRLOnEr_C^tZy)uv7SH=U*c>$2D95T%&QR$46Vj z0Yu`uBd5UIWzU|#Y~?V_C^JwPfsTZl&mV+RP9(xc@%-Q?zNu0;`pkVx|0Smq+>%w? zogP%YuP1_2IgUIPS#5(zNgFNO4Cg#tIKZjyBA?;GQR!$ZU&4T z?C?zzLW8HCHY09rSoa&;hl$Nmeo~ft$fUJIuD*3v`*%C-k^EzMI-S-8**H`61VH#H zLvA#%_ilmVBT;`~~2anF2DT4*mEx=)d(cq3a?iN_A)u==i*xLJRalgK>(E6XW~y=fhPkPQU-jw}$wFfW)4cDq&4M zZ2cTg+G@zUi#%`e416c}CP-9UE|7M;m63z_XLeSu>y%+HcU)3ehkD)U+l`63p&VUV zvw*{fjP=c1ah8)juM?$%g&D8*=LImKB!g5MvG8}{Z@ISaFV4D>#t(v7DL>ap2*tP* zzDLg>DRoJ`iUzn8$MxrW0$b8wXQG1WM$8~Q-I7XA-x(YAP5QKIrzTd3o$Fc)kbOkD zD9iYS^qW}o*s&QvFaPRiYarAX(mBPq+9F;--W~Q=-)B%%=i1oYno0hHZ95khd^(jE z)iNiGZrji>GW*XV8MzDNm#&%Nd~GJl7yLoXBmemc)#T+>sQO$XFqq$s<=HKZrvsU> z|8|$J@cmr6_tr1=6pe_4iCo_D7Hj>>?Op4iM!jsN*qrzCFas%5gk+Gaa~^xQ+l;V4 z2MbASHg;wPLOz|~pB+)Uvr8wF=m}%b;qFuQ1rm&pp`*3S4QH3^0P%gGCb%7 z@4CZE1#&z;;dLqofH!;tw=0itG{iP(ZF@oms@pVbVIRTA0jw%?qoo1DPG|Wnl$1!O z2_EdwJQI)$zeYo3z=lT6$qUsng}yr>e>Qk-G}_TEL$31=t2da(p^owvo3`L~>2_bV)Y; zgmlzHY(qkrP%HwJDg(de9@->iu+H;jY{PsFP=ygpgqBD7LTo{21+ZNH_$mY(gC^{H z@(5RlbGAmeNj+Ak$chWP=O{KYj;+h`1OjwQ4%%DVaGLeW%NgntmL{nH5i~bB-?VY9 zS&M{5U`N|2&tLH9xF_@JF4e%wTCh!CZxZ=7(87S^LbUh(@*7M7k;$^CLF-lBgNE7U zkG?-q75a9%N+nfpm)niOnM@-t2=Cj@L?W5LJ8{mUeD2B=;+XjeIt%7pwZMz~oBP18 z7B=9z#ItZg^G#ByroWVEsmVRokQ}On! zcG~mO?cz6!$6=8q+w9Yep2gfrq}81d0^IHDN~{arpx|ShvK&B?Oj*b_J4B|E=wt{CgbgZi6-K5WBs)| z898viJ$?)NZF-#(Vh#TlOny?56Q%7Abyu^!bJv?<+0B$9(pH$g)h&b#%>wQjzpdE@ z*aU{lHZWD&E~`yP8@P%AJr?P}F!NPo>A1y*UmxRnK#)p2lpbtY7xjv~f>15RSk;(d zC&EL$3W`-dMM6&8n~4+#STb^76fF*7Mz}W0Qhdo9GEe;_4I_NPNhu^rsjy4BfxL}3b$KZ{1o4PpHQQfn5+GG((hN_SNz+D`7g_!U@o0` zOM+<6dI>wO&M3A z$-L29DDuoM&-tXe*iB@SSX@uhi!BSNio?!U>5ypXE@WYC3imEU0Dj=Z*)cP=ECzxq zLRW8ox&Im-q=>2~X^D-4^bx}{Nx$1tO0CDUIQz&?Us^krJD;_ThW3^FJj)mzhd zv7kuD_A)fQrCqg**+YCdj%bxsZ2ZDVet5vTVzXAi?j_D*tNkSqY!n-xC_B)Z!WY54 zW?=m0O8uJ``5-0B7(h5FyF~MlMB@YM^o85o0QGl99u`uu86DLXGB1TD8hsNTuRShu z@RIkDSn&9es5nM~9fy3fVS9CKN3E>jZ~iFqx?72=MHIAbkJ*Y@7gu;|qhq3a?Q8h! z;X!*4_EYkd_GoRcSWnm&vnrWNyj6w+Y&#&+VSxAO8<*Oh2y9bN)ecszi~D0b+qQvt zI{qIO0j_I#!0TO3&Vt3{7S3VheaGX;1(^ICxM+C<b-VkaKi_tnD#&1F7^+qwPcG-#JWqCEc+X*Sv_2MfJMTn=^P8C~jM zFgfML?f49U&MX^yQ)`#Lym(#V<>c4K)JbuI?RgVu$r8C*?7lv^!*TKzl2IYu5hU^J z0{J;gkY}(QG1I$sX0Pma&D*6-a4EngiP!z5BX_ZfCf_JFK*}o`--{{4Io@^24%UJ|Z$;Yt;sQ{uCTZ3%4CwPoKJH*8srZGY`WeNrDxFfOrc zyV?RUn^appK<-BM8##X--&$-DI##$5@4pn7`Bk*IsbvnPkkey0f+kJL9v;8c$ID`V zN;9x0&?EJk;uginnl2K{Hgx;QJEbH9p&?CFI_;#9!DJ`DjdhXQ?76_jN+b9}1K*6U zyeVdBPqI)g%#TLZrYQ#j6&lzFkbl8HPi6#E{?M4sp%E50_NWyFzD^XCN0GtlITi2W z$W`fC*=fg8vu8igPavsL=QP8t-2-Emi+)Ro+<5t^nrC>PKGvJ>Z z*%UKBa#y?L|!_j15j?9K2i_qL+WBj=_Lp@r<3fE>Hs!NCS5pf|5?^g0O)EF6CZ%Qe0U*4rHlCVJ zWNj>&6~}}c$hZD6e^dnF?|+<%mGlK9afigDb60uEqjgcfuM@BGp#h&6HVZ*Bi+jzo z&Bmu_gKsH+u=>7tD<8;Fh#L*V=emR1u`1bvW#$piH0${gl{gc?e%XjnO}?eLZ?t~~ zMYG-v)yj~QTCpzsxY=?004gL|bE)VGUppFzHvsV214m=Qb;8t?hiF`#r1xv=Th6wiR7>2h~~@C)bdv4IQ5M zu0)kEq!0a4{(nAeO~)^y*3&+X4bC9W6$#-ny;}8=i7oj_=AJ1918B7ag@I8`*>KT~ z3Z)*9&2%nMcd(so>KDIDp-9Q$UqvO`H@OLQO;P!nj>2nt7x_7fw=~)w@Oty2#6OB` zxZ30PQkOV4RdC}hkNam3ZW`D1?a6Hc;P;pcKCD?a@0a4SM~iMq%l{8}PtZV`e%H$> zLnP<>_GS4PxW5Ot3%_{WwtxMLuS#JK`&_1Q0s|)yjVDXN5#OhX8lu!#qGfir(Q6rw zbO+_IgV;Y%1x(qpbo60vrgW$U>NR^QAutAe&5?wt4MQYlpGYQ?1xSR@WZzAt;Tn01 zj_K7ft9ts_x_m_V+03la4pJHr!S~sT7mBLDPh<55Mo)1N-FtUDjJ@0+hJRuRXu((s zKkrrHAMv?2vJP*Dx5vyFc)JQlWinsTB|i$D&fN-JbCnnD90!_SZ-_H~QP%0Z|5&UH%ZY zMnN(F+!6>@5=c5}6 z+mCkHC3KnJ#Z`9>_hbLdG7g)Ueu&*mRJ!EcCe2L# zy1=p2xj*hJL{8&2kL=IIWO~{QkFkrt!u@eM{MGbbNP`46-gR>;A^b4gFDgG5Txaps zYURbM|Ed?bX}P)@(?3FIY#xd8nA0Qz&X1%1cg1u>MC<=FaYF&!-XB$)ivM%0T`7z9uU2?eyDb+pw-g-RZ4y`?X_I zvGvp&$1rI34=4F89~0l45CkPi)Gy{2mfZ3D3fubQFB~E$zD^LzDakCHW5DC2sMzpn zJfU$eF}q(=5S4JLlxKIU=)iiz%wZS9Vo;WhTv#Xe2t;nn4ZMWZG@PHqCFcXMFFK{Yk2w?>5{as02EBScE~J6;fM%6q-&ctk3i4g~fha+J|y zgEu6!5j6j{Nk>O^ZI%WWi<2Z}niE~;TE^G0fygODXNg=!_NI1VLY8eRQD~a09cNse zfrc%di}^2!CMPNGOdTE-zguN&Uqa&+1%G&mOijp!@liAXWD%SrM$DZ3Yh&12yquDboD zM9g_CcZ|0D=}rT2+BAYoO2tTKdv#hZI%UlI8{UmQ^Frd{d=K#3nHsG^9RdMHNN0t@ zMGn@#i`NWYw4R7R%RLvqaY;^-lglU&D)0XN`$Oqtl8y_2w9J{x_*=gL*zP^<*7_dw zaUg{Ovq{Epx$0>2_ImFBgtX08GzWqIh>Nlp(FcC7!ovD5Jq7#SGZsrd0vP@oJB&TY z$*+uqRo_x61yR4>F``Dx08)Q_>A^%g(Py$(m95;}f0F@35M9Q>tWr#;Dqny?=y`4G{=>QNd8@Fh15 z=e$SyUG1WXr)fBapYe>m!wPCOb{O+thhm!bhKgBe66I(X6+&B-!dWA0U+`CNMjRY` zfO<(^En3l6JphRtm^KW}@r6x2hi(ckb~XY-l$T4DkS4i0|3!sWN3SMjo8uDH@{CZObNjqI@s@Vf<5#)9Id~efeDI5R~|wi2D+urdqQ=xObw7v$Ua5nhQCA9xHD7Zv_cAak_T9^%!JsF8;`RRS?{B?G>d1?M*Fd&c-lHGQZ2n7)6GpPP_zw>t9R1kGVAJdhCiuK|M;dHGSS6`TFkv z&m6?~2`yTkZ>W#PQRU-&baspR{=G^Z@UjGc1VmE}5ctv5a8d5Q44LTUz-V%L4%LW@v&*_7%}Xje4be!X1NttE-=_QbGJfGF zogBa5cvQgyI@NpX@f7XTY0}YTPNMr7w~Y*>r4Yu9v?ashCbI*D92zVer(ChP%(l|0 zx*xgZKQ71mGX#-s{)S}nHXIBWEU87;eCvx9KerNzBgEG9|E^a|4otLO;nyd6v;FCF z=>ZgdIOWfX9;o_k;>`$7IK2AQCEn9ojv6HP_@9SN(>>2sZEob2FfJnx(*JgvWCI*>Zz^9AEXfz z^=M~*9i2XYVpU?&7!LVKvF#MQj4oU`-OtACH7huhbP2ci)&*eb!XKYK+iBZREWzvE zQD{|&qT|WSw!s_3&DN}#|1_VseY3seOEWmGeBv0-Xjo#hdaZn^ z`qM=Krz%A*?Z*djZs54YMTbjvAj?iH{(|PEf$Q$2iVljIV#7l~BO=@eYLvbjgxbQ! zi7t3rtV0^(_c~$>3^i~ z7X7*^kFE3vdk#kbhp7;Cds0O71iQ4;`1e}57+H+9@-#ennTYcoqHbQi1ncaZS14SO z?M1v?pX|qe$9RiQi0ho2vI`9$l_JmcZVpV;WfqU};CTg*&Nu1cmE8NbYE_uBXEy#+ zLX;c^c(hb<>3Zl}kDHSy?dx`qb~I2qAwOJ&+8m@Cp^q-O)(|7rt3JK*OY@_aFeVBo zHfh>@=k0d)d3AwW6m5a87;~t!WP}hsYbXj0eP|CeI$Er@2i?FVnI0!KaiCO_;%5n^ z0Wza9SnwN!hds4S{b7w&n;4V4u^C!FIRjRpa+d9#H8!_ojiT*=bw-!;+^22Y@+wDy za@Fz+mBl%JaM0;Yj;3BAM!9XQ&j7o7WjIC%!w~#0fECjjKC%O6^j`90sxG-d$W3JB z_rP>9@sZ0GVuh$hwcBW0>-+ja<^$q-ReAVgD6N+S*-ylVevSi})Q^X zMU>J-IsWXZHQI}aRHtyCw9i9PFXbRK6?Ak zc(>d|Qpze)f|VQpx1HX*+1p1-MfDyx+GnCc{T&LML!_MI__Dj`Cbd;_=HH?{)<(+~ zjd*02;>hkdo7jBz{~rLcKu*6faHCE~{NIm%|CPt*-)xnrU-c#zunTxQm7av|`}#W9 zdja5oi(OshW$|fXZ11|N>9@eVEaZOfap#XdKK%(-js!Z8itweA}Q5Ht8K2N?S(~+iHQ*t841u7mAnRr zQ83JVk{OtsRvNA>KcTzSc|?5=4;^)a$KB(9)>WGzi{sUo#Ze`C$Tu&Z`|oj=B(1kh zu8XHGXnTi4RESmgvGkTQYf_2MbUAU7>@O9ECDTrPRkX-LQqpKytB5Wec$Jm5>|`wR z9qc`8mlt*q7LTn?7GK#WUz|=Uzbjb+#3poq5Lm!V70%5LwUaJ6r1__Ah*Q;6!Lni@3;CW< zQroI7)gSOC{j2=s(ovoaQQNeiq<>EvrzgLy?`5ixQ%=#YQxgq4kx{~?%!LEcM3S5> zYSkH7DD}y1Ey&A)JA?|wP@AJ|6UnSwGOn7W`b$u+>5tGU!%pyqIimEg7+-pS60d@h z09E<*!?Lqur36X8Z`_OCtsW~XvesiTPSQC~jx!Eb-e#qA4;mFp`HWbFXPe)7IG38R zxLeI<@ZZFc2_uxaBdVS9~2$t@Um$Y|Ka0*pI^9qWnpK+O=4nVQ7#SxO={@uXVi_0KVAO z-!IRAN+{@JQ~>3_nk%XD=i2D(Vp6E3Wbc{1QCgkgg=R~3vh0W90Dn2-XY z7t-o}#dI;fb|`(}hcav2l>d?^%9e%9u`pR!M4!rMkcT_q6As=}KV3AHnBJ;B6nmIV zRso(kwCq&J@e}vpp8fR#VnZ*`ashd}O6RlOcG%->A{^}>1O2Ff?jl|7ns0dqo(e11 zhlctD^Qm}+s}^MzPsH!y3ENNggL$@Cz#q#L0SfO-2zANbFAF;x3p#gXyqUelFpR}( zfR11FCs8DnJ)leSD-1`7uP6OJvORlj=9wCIF+fh&=RrV30vc;Um>tbnTK;F6&?NTMJ2u1)dOX zh;K~bZ=#&zT-|C`4Vk$k^|R|NncgP;C~y+%Yb?ZP`Dcya^;8Y9`EFvH*_xQ7?A3y4 z4k-0d@|1mE+1W42yM5ZA!^?KZqnHuE5Pnv?xF1%XS%Nixo4p9&f+b(OTshbb>l4NB z|M=kR-zuh<*MV1!xvE#8TK=;z?^dDj>$|$%3jkm38opZIz}zT|BE>4P0@&`F!2Iiv zH^1)z7Jr1_&%2sk!QUX$G$(+khM6mkvp854M}G$z;2xbUwqv)8>Q=aJ%fUI!z<9;l zdd!L>lf=M(#&H&vjb{8Vc#j2;USuc9TVk*8{iQCW0Z+jhsjw#;#Gvx**_eS^;L-=^BDGz|UmVJ|Nqeu1> zn=yWWwCoa_P(4hr^gR~N*n-GhS{Tt7250Pr0NAtPtR^AiGufQ>7E|gjTIoBw?F7-$ zH%oXzZSxwz6CHAp0=yLU>}QL)qE{%Z7W{x6vg-zyXx-{Xb0>irP0w+qiGsc;9Dqbf z;{>z%fiyLN5bepJ?SeY}W~O{p!lEJzi@vabN%u8!qlai+jpP*VebE?%9HUKUS-=b( z*HV_o(?q+|km+w_tFV*+s+YzrNNNH4^4F-`rSr(6t{8!Af` z<_L_9#1`1qOG4Hl^_7*m%T#iL=jXp>4`G_|XSCc#JqS0~mY<~`Lypr1--f|~_waRp zkG;e_I-Fpq#p`8@=gr^y`1gOmbTh>#OE<_FGS{FEg8G>r4)5!WT<-;dFL?E2e|Cgb zMBQcnt|DqhvMY+!X8zH~KmW`F6o1!@(Ef&I9_alb$)Z3&Wmc>am?pm`)(M7RE0APV z%*|l=ECA_L8mma>#1Iur(rLtR*`S9j z!6b}FPb{dTMYn!W0EAe~1d5xBH%?TnimA7k4)ll`27&5l$#+fqhG&@)BBB>DW|Pdy zWDU-GQ^Z~EF5ND@PvsrTE5E@;U^l3p3Eg>39%MHatA)x0LJJN=phRf|BVch*h&Vu# zrlS@T2NDGt_<~_TAPqK3ET&2gYFM7J>S7S$?tdXJ!ikH*Uwse?S1dp z2r_r}C)|NH{^9$+d+mSeLiHqn^G#2VD8m`y@oe#Z@Z@?a`2@!24s-8aqMg)mevYB< zSZ1Otx$t((pMK`q%Hqe|mA%Dx;((odA}wB!%dSNYTKuWjK5LODN`_`NZLV z*4J<~H)?z)rkGtp&y<^gI|FtUj5PgdBj!z|O8(~VBJGHKK?lYqhUIC>7{kWA<-8eO zWHIGn??Z2()#T~waC#hvLsagg4k#G6ay&iLX%x2;CwHDOm~su+V4Eydzdl=0TMZWr z2h*lPkejgdZ^N#MHIPtqn#UqS{6(hud|u%*Df^&jNd_}dezm)QKmTXfzduGUC)9&@+EK zyX?yV)&ejjrgHyMo@DI-7j%1i;p6)@UX?mgsD~ zka+H#RN7Opuif|ahpAlP6{;dxu&D+uO29xz1VcNGaA<+{rpaO~JHmF~YIb&0%#5Lo zI3yV|`pgeInpfq*B62mlev`RepjvWt*v)MlXO@_s$)hJ1%iF^CfAG;TXRq>D+$kG> z&x<->;6tR2>P9nICSI6XjpWV8YCGKlgL%qO_C)hAKoqKivi$l_oQ?^CE9Htu?eDj5 z+FZnw$(D^rSgVKz-PzEjDy9-o@NCQW9mKx9*CskUfg)TrzPBGi zc3Fhl7Li-T#3xyde|*~)7p@!ErEp*-<(;zY?CuMLbT^En^o+pL~1Iuu1Ii0d4%ySeC90N9P=~RFo2HTVF&gV1S5|`Yj>XdmL zbXe!OZV!19OLIad)SGRJ5u0r+%CsXADy=eqZw&%d2rEs*qJetcK2(wC24 zk`l z0T+POhsmrp)?B1&QD_m33$FaGJLkqOrRhSERQ;8Nf6B)0ru%q(+rWDqUnegJwk_Is zmH&v?n%NC)`kwH9(fBhlb3H#U;FrtSSYFnBM_Z~KI(5E4t9Pd#$X0yk?I5wH-_7W4 zJPuh_OP|~gHx({xAIHCa7lgLg;WL~4kdOC?dw5{H9`0@9JjHclNS%I}M;>L85=f4Z z7bJV8f7;Md!qW=dbKM>=RA~=hjJZi)VZ$+JrHuS~V~*5agUW#^^)Q~>8*~(OccN{{WyVK?32@Jn`&CMvC ze@Gp))X>MW@g$L?!#+L5&7eQ@xt`^*8&jrBeT}5U_d{%J&bQ}q-A+4pTFuUbJ}S4q z=lcJD#z#-3r(Zk0eCGDF^+v1^6Lq_;l?v&=36a1`8ckG6pHUtIrw z_;S+kalne?t~C&=prbVY*0Co__M|I2e+PisG=47;9dwhNN7XwrS{t*(-}1Rz%LxS({P5Z$55BV#$;~4=-%%oe zlns$Dk3VNr)2#@!%j9w#*B(3HGq_>ug%b>EOblR01RaCe>*J2G>o{!RY_rs#f4l6< zWCXc_p-O$mv_oVPiwZI`ukd7+-@hx^mqqL`(Xn`R5t+{1lw(K9bz{?%EsWo}S`6m$ zG#GJtIE~Ye!fuWBhbhRn4f6qJp0`EKdC5an|@Pm&&p_}11CAcpibyIh}4(u&! z6NC=?LpTcieREofBxBwsPYwOABqiqG?`;G4*~TCAGxc^t-Faje9b-W`FmB4iWirPL z7w_@R@nOvSgnxMNDw^s%cXG|x$2f6OKV{6>7zB_5G|ypt93yTnwkFNcNmqBud;0a0 zPetDcx?C5%Z@_=Xo{o)=uQ;ZDg%KMehVGXQ1bmtc!BB}}^9&p_^X+lp^w;-d{-+2A~>)UIB7&H6M0>Z=+{_+f6 z^I4al>uX(~0>D?iUI3j7OzudPfp7sB{Cn~VLI4QuXb~=c`}OXZUH5-UBuUGh)pjE9 zpwOHn9Ga6lV(4vDwbxC21V{swae^}t#1lbJKAa4_=>vK0>h~Hzt^rto{8;wgFtQ`U zZa&(AriOAo#PKJe3gBQ0Og@2yn7(6e1#{7X3#^0LqtrYoxw3QPVPvHbzo&Egw z;bTORDVU$<{ZxwG$B2iltnH-tiGF-QOmv7_zXum_3)q2MV-0=UyaUg z(=%2MBA<3gQ@JbRFKIM6gl`$YXT4qvY`ZmPJMn*Bfq~}i9?vz-mbm-rnD6Pdz?02+ z$?E}{A5W#YFVTm8A8a_Wc?sJnALV7rHFFR7SR7CM?40cW`p*hlotDQ~_t3)aF!-?h zXy|ESv}ba;=^ZvZ$0g)o%pAmmS9_kRJM+5z2? zWIqx=6R6C5O2DycVe+;k@bLpMJ$Nb&uLT>Bi>lL!XAvhT7TK{09IpSc@>xJ_t}1rZxR0;uy4!qCYCPr%;oOg)gg>CLg- z#{6>xxi#*8`Pe_t&fFVj;+6-~xjSClR#nl4)d&;|Q zXWRO^ogca#3B(@e^c%=yCK~qsN$%&p2}pwn8}Dhi{K>Ws+1Zd!N!dHGMl$x)(0q6D z|CCfcPVi>DDTBi|2WEoIH0kk;|AgC}sL2`~d#7H1V}8d4w;{KU!RAxp@L4Z65oi0A zw&%|+SWOHMoAlUFe(eSFqzkc&cv>0Hh|M@bm1A=DHRuIeJoyh!Q`N?gr?$kLq{l^} zF>R;q=fUAeI2^PisfT@OQSr!mjDrWVn?PB!F8i2fKDm&tK9BQ<^fq@BZBN`fIM&pHV}9w+0j%lg8;au20Z^6g`{&eXcKbeF^|y z@M3=C0msk6Jp{eleIi*HUDoJ(efV##kH77@|9b(%H&`1C(zC~p2X!4_!~4vWb{MuJ z>y85ejx$gRY@a^+3BcosYY(6@3C;5PjP06 zf7+4}%3wFZ^t1{a8_=6rl)!>{TJ~=Mfwc99YoIAa9;p8V;kAlsxk?Ajwx^!8T zB|#X=ctg;qeV2GxbjC9oGVf9!Ih|Ld7%oW6v+v{}$NjBIhN2jaf*l0&%MbsEa<2d*Z71?EmaFdv+~ zSG-r^9Q}<;$F^BenY`;OA8^=p=%I~o?Now}75sQl?9ffkMGZ>g;f+Y2m)+Zc&wDH! z+;5!}e~vd(Px7;sc;I8$Kq13{EvGidLO!1Aw`QQ%Sn4?r)bllc-pR_{_%-B{i^{~h z^ZUzB@rBO@u0Hx$&4-w4lubsT)AsMXexf2g;iX8&F>vdsk<%o-!pvn2PJej7znHTg zKdFHKT-;elpKsW(!K_0cDU(TmUE0Z%V?fYBiP~r|#fc|fMSsK3Th}WH5|wAna$Sgj z*P~lU`jXr1@TK2+{rj_i|C@?fcRN4af9k!H+Jmak^|h`~0pJT>2m}tU*!{!BMDI<& z2vBTy&g^@={LuB^KXKjs<+bN2Bsr@CoF6X$3u2GAZ{I&PdMsd0pq#sZTCZn@%E0|d zVt}I$Sx?C0AyCI;WB$i>E1yq!&-v$KI1-liJYT4^%NF1k43}gvc{q4Sv(bhHqRxJW zwv^WnCazzb^9%qb8*&mm10?%)K6ks0glq6LUwgdX^XQ1=Q*f89np}oG=s_KRxyIvq z^BI9LY(1yV0?78Kuq~H=r_(s;8Tx!@qmuFagjc?%MMwPb5Ns2>ye8xrv18P?=|Ipq z?D}zm{h%Mv3nzg*r~e22lW&|>dfENvyEQD58YDx@5<&7eY^s5$*bREeH^(r&bhPAC z&b9x4iXGug)SZLbc}U$)6RgcC#c%reLWvP$0>6dKU*HZ7#udkZTE}pEuJoW&R&(3~ z^U%VWk=?F{FH=7ho5^R=xJTT$-4d9M=e`=UaIAIyZH!~V7-ODa4X|@-DYYK=51Gq8 zuv0w?V&vE3LaiZ>#Shcxarz((%XxZJsbJ{+g70mArx{V6dGb+aEIK|9`3Ij5v1amhTIW;iw8Tdr7@y|?-TMfWgbPP3 z98{g95VWwiBWykSEqlHz#C?Md=96+#=D$KC@h z>#IOF6CM%q1cb*JJwWXZ&v~N>NJlj~^SRu$pR`yq!ePsg3cjZqjM>}g%6LD>#-58t z14^4X3K?zVrOw3jG@2n?-_ed>+eu$MCmm-ZaPYX&o?>h}=H}PCVDKbUr|p^E5n_U0 zlds7Pf9W89Z1$lI=jt=HnS}4Sd=wB!_k$1ldrt%+@p|m1cXAQ`>kYc%D=M`$8oNaQ zKT;Ok;a#(FJ>$weI+#T5S$f=STjpivQ@+zO{akjlwf+q|htz-h?&Hvg+o0(M^XLxv zHYu9#xHYY(g)&$x{I-Mi_f7Ki9cc)}&E>$c!3)}dFYB9FIc%#=d2k$$D+N8woh19; z?0J5vr$;d&`LK5TW1f;rA9~XN?W1mYIF)wyaH{?P8t=RO@U~0C=iG-+7JII1v@g<@<+5e1#9@}xyg%l- zf2Yc?xpTdu|Kd0vi=MFxqj_n1${fE#qaS=;M<17|bCupOifV(9v6nt*yzlz&1*I=N zy*n@crjAN@qIou6!L2lwHYdCg&->Y5x!!+&Z`v|{_LZ`^)9v?G{De^pMO=*5cX3=} zf3B}|eF^|y>H-k1^nVysoMo1*VbEsnLH{q*(vFJ7Pj)b;vzS0t}z5PzaC z-pB63em|0y89bj8CG|nDiCv_wy(u_%czfE-S0iX2n?ug`L(!=-GBKmup zvy#UbKOF*N3epw3Fxyy4=oXH2@+0#k;v@!0;+vLkD$gL5wfB`xViQJUR z&nGv3pV<6dxm)RCYe!y#07Y`!MGD69YD`u|_L-v2b_nEv%#kes;ZClO4dk?5d*IJ~BiKGzqyJ_Ud; zb{%*W_cEBjoV+W3H8qljK6~E4_>`#Ee|x?CP1oyxbl(?1df1o=Y!J?uOm?1mc^Gg{ z%UvLQ{*AlpyIlm%Rko=1g`s`#utySM^Q?z)Z~7MLBQKb1xBcd?5u6K;1nTvCuSXgP z+B(OWyY`KnjWHyD=jsams{a)5pe|zR3YpFD{O(ZZ(=Pv+?6|Bf`FQ9L+s=Tyd2|}w z*2;dL0&@4Pm90))!M~mt5QEn`{b>5?K{wy+C!O~)JvbBCNkJcdJ^e`E8ZLSG|5J)U z`c{n}DNKISyi((7vlY5~Cm+!`6QcLl7dT-peWW?Zswet?!Tr1Wv;aA%A4!_)!pChk z^+nG+O`rFs+{g=8=Szv2wGFviqKBCe3?B9=%z9|cCQtfF?virMe_E!`GZ%hNR~}BC zWBZt=olMD}*p;^9Df6_U6_h+gc*OMw2_7~ujOqzzWN$8+a~JO&k7uz$oUBc3{5H>| zdd;`fI9AAir(*u zV%HHg+u?lWPB8olNYfP0t`qK{9$-|Qmg>byxO4%-a+P|6OeHB@M z+@{a{>&IiX9Jg%Y<+MvnJ$g=wti333oOGPHcLS|Vw|z}ASev)unfBvy((5zwB5vgZ z=$UVF&)>wD@q9(G0>{HA=PBDo`g+H`S(E^cl=sd9?yioCsaM+Il14x`DcHYHwD4W( zRjF9YSH$0At|8V<;LGHCkGIY>pPF%hiX-y&rf2MQqW~cu?{FUcoPW{aLn54)Qtrb4}^l8Glgo(|+Q9T9y>t8;lgsYzZ{K@a}^RxvPOL~sAB zDZl5Imzfc5#!N-_R}}7&jqEYLc^*uo~6ev=JTj3chNH0pL4tK z(t^$ZpQsA@?4(waKFG}$9F*M}IuV<;uHFk78P-~-WjN+$kq&;LeM#ason`U`d3h8_ zPvQJ8U822g5=|W!xLa3Civ*+1FSjkPWn#?%Uzhd71tWhSyN3R^YU%z;76VmYKGv}7HbPvsi#AI6 zSJSti@`KOywXRPA;0s>vGM-e;`*+*(7;_D`OHinXHnEKSo7bCPeZBta>-8VLpPp&H z0#eR%?DTj*0jRa^2%0?zjG35dP1?_d^xc(-z*BDp+7+J^(x1TWn`ia;oz6T5;5&bW zPOGH0PMOq9wnXhnJ0cl5W&A9|r$f=88YTZ(Lduc-$<+6-&O?Bs!X2+kB@+>&l*3uV zlNJ3g9a(*2+4e?BvU}Y#Z>qSDJ#dTf%fu+p^W%yd5fg>)TN0BwxbJlN{qs682Jff; z8iiwrBNp5{>w!!?amhJziJiKf>AQcVm`YLdL>&g%E|iBd=lCw{^bg&WMxG>j;Odhp zn++o2y2<~so{VNPc*+W&cmHbbsM-9! zd&G5*FVb9XJZ9`Ncl;7Dtv7p^^h?YaJJp>u-HX%PkCts?ieK%tYQeJSR`Y-I6A=2& zD}>(UmG=hb&?iE@6Z7{RuZi!;8@sy{qUq9{2s`s!OoKpe*^wqKw1%#AR6zFnX5|oA zYY#IjY)n~;>l5rA5bqawn1ML$Jz)44G=c?fS0n! z_fYL+Oj{^YY(F%=qz)_lQja!lZ~LX$;;4J4K3QOmMe^-4=EbHL*u8=?=b;=VK)361 z+Aym5p2DBeXL4#=JU4~mMV?(OKr#T?2H~4u`hb+R{rL z{+X-CpSoWEp_9T9Aol&I-QpXI7eOcc=cQ4dw^bI~4XlgFK)fH9_{Rkwe|(Om>^) zNyAL)kZ5M&Nq)xnKs}k5J0TsBTDwUS8fZ&vba67_LPF$0_%(-i%(M%Y$xxA=iu@Ed za%Vl2+HlkNW|eSCcXU52M#49>U<6&h zn^^TGxsxP}D@7-pR6W3x=_`Jj-i5g|PWZkp=3KBUC^<&2*wHq%e`vf_+R-wA=xu*~ zy!|G5akp<-00;4q==`!^MBG>7{p z{|k0{(?^qAYVSV5f5qwa({VK1eVNC%EB)_vZ!e4&`N*<%?_z{>KMmY$g14aq;C$vw zO>EOCf{KDzFtX)w55^+*wmp6CJxHSeSBZvDf)!5Ot{qFDAJ@6;;(q3vDWJ)T?=7I! z6S>VE(He0HF|jp@^h5H?ck&e@6d{rAnYq&zOfa&AAjhnZf4Sfa5z-GFi*>r=FJGrvssOB%W z)3H5UEX8;Nqj^WbKJ$V8>FdLAw09BUOwk<#q05GY~ITow|#-v(s?Z7?h@TAo%>cCUQOas?a zAj{n&8#h&6{=;7>6}&&oO=2l6%KwkRJ%Tj2&2tH&lu5x#3JyDcVwCrl*iH>YZnHdO z*12_!T})3r_5x|8_xSNfU!cU?mK@)U9?>82R*uFIe_roMhIa3A8*8^*rU|q+8<~a? z{#YuiIM%=iiWPrPnQZPSD`Mc6ZK{1~r*AV!zg~`B7;za-CEf=FF&T9b8@q5=$idGa z_E@XcbEKWP^?phjeYk+Pg=>s1uEqn0h?9=}YjU zR&nImf7FazmHn!i6q0994gFFEX7kG}ylBVN#VC0CsTu7;V?m`IFYG{h0grwcnzqEW zcRP0yLXUiiJ8O`$i*(PX-F0QX{%6wYJ7F(|iZC9JFMFbl%N8r~%xHG>M56ADX)&t# zw^X+77spCm(XnSNcvy^Dwo~gli?5u=u3+=tf1(bu2rIimTk=DjwE|XcV{vXBX9AxR zH)SpG37z&R;}!PlzZsxY7*S@}EXy}oL=NpnMkC}iAAxsB7DYN}gAqSUcnDuz!qL0E z6`|P&xyG%(umd&&UxaDGr|^qU<7_sj)h(TR;XNq5g_K13_p(y=@VdU2Ol0dLqx ze+2O2?sk{Y)n=bQyWuYFY4fpZc3+?uqK)}r6xuK@i^Y(QEM*`>>fZ0)cmKxq|94$C z{&Ep3AWvYLcv8VLXNvsC7x|>9i3`AQ_kE5wiesPaJAZu&0AK7Pgf6T2S}6GT<+-Ql z4{>a|mj%bAco(6^0}FgrpmUA$UtM&3NB4E-N0oG9{!BJrq}Xnm?w`Re_W9UB;8+Y? zRS2$_ECDcgd?dH3{8ilSnd!eJ9 zSC@Uw1v7upTS-1e%-hnpiH~-L0Q`KC#g{w~nC(7P5f_TV7&}YNf#i;}NVG?8`Epfp z(6bsG_7zLNx>2NroDgUe$xIsW;~we6y3Y%o71C(@l`XGMJ3 z&-ZR2e>9Cl7;xfdD#-lO?a!KU*G(S2{22*LxyfLCLbL_`yAf&uR)dZz#RO=37GB)n zVR?TtWGxWx!Hh1d0YxV(2ulb_5+4c4Gm0*rHc%hKlWl`i3l?OMi<_+chNnEr7I(BQ z4kn*%$)>7}?y?vlEFr@36v)<=kFyl7AWE1OPy0FF)t6$NItN1`06rW(g`172Tp(1EEHV)#0ynqx(Z(RSeApR#=gf5{{SAM zkhPyIvx!Y#pvzWalirPaWKDT6^+-@PeC;ZI&BWc?Y;OT2UbghFTrWQ{GgbPn$%`1mAmi;Sa41YHt<=+$;D(>)kY1{9I=0u zr!t@+X3xaG{@BhSD>zpz*fpt-;l4Uwt`FZje`M$F(;N%W)xm`AEC>34B8$C%3_ z#ln#FNcb$BQ9tmz9AMGg)8~=o**Hq%cTYxz-Oo=gtQCDVx8~sc-k^*eW8sMwt^C#B z-PQw=|DX*)z8(bS2^vGR^j`>C<-30b_dO<1&aW?yDG=>$-8NZg;K0cUj)Adnx;-I< z@?fv94bbVwGJCi67#>G97h>L~Q_(mVC;4CHZ*wdqBerAMh~yUKSzxn(nWqrU_L#V| z&E4W(*=BL^)kspBwunVv{;-#DChb&q;WxG!lrpWAd{C+Gz2$db4Mi+8m#oqSAQ@{Z zaf2;($XW!!TC(KQrl%sEvn1s4)c>ZJ<B-)}P67MR}P%e9T^`x0SNDyd)jA@4`y0|TJ z^$8nJe_Ozp_Bo~=05bBCWkm4D49#wQ5$NA%rTNh}R^TKZ2|5^(qm1B$?&581?E)roQxRMOz3AK)jCzQ9I6#xj@S(*+oRYXx@3 z54ZU#AP(;qV7_EA)C({g*suV$2AiynJ{&?aVILV5WenM1&MwCyGq`e*jK$)zPqw?P zLeJe%C#_5$CTjSUauN7#oBjY6cU%8!6r!&Q7|?Rc#tQ#dP$!cB8y1U*w)=m{&)4N% zgvg=~^q_lK)bTW`*{{9=j^bHl0Bax5?JO#jzdzBi@tfA`(GOhj zf0#Joaj!}RFS@_tyRtCMy?u1c)@lT_1KJ%KoCa6i*!o;w>-rP`zS?DfLEZAU(yxnK z(vIi8IEr0L2cXh>BvnjwJvlP~CBDAe|KK(1-*wIPo8K;KtCUQvfVEm4d@JIgEfViZ z8%c>JJIniR0@cL<2V({+N`Y9e|d}4nT5|86^};as)tPu|q8^6M}Z5 z%e29CjeJ?~g^f_uIz178!EEONu#a-uOo&X-kaTzgNZJrQ!Gp<)0d6Nc2u`4h^08!T zXIY+vu?=jA*_o0luj1cw?MR+_VdwPLMI`Q9AUE%eathtpuGKvqI5Wo0Pg!U};cZp< zE+&s0n+_nv27%>c7&F>%)ddQt7b zS|_+Wru6n6k_CmXC-2q4M-` z30hfR*)yFo-FoYif54Z!KGzq#J_Ud;cL7CP&f}F;Buf*(4ScloU|@X@x`Q@gcx_*9 z0!kdyQv5&={r;=(FTC!5Hz?KOs0d)nlLU^QJVtdHojW6#Xpe`O43I9-RW`oYux&rG zume!I)0Yd_1s#7|CTkBC2xw)BuwaMgHe%bnTqy6rYT~ARlz3&qrDB?<%_#^LBpB+Y zFi?~l_N)+GwqP*YnUvk_{l|c~D`=ductHByHi|(x#D+MF@hsVRecWO2%vr9m5E1} zc zE-U#1Y!!cPw&9^sm($r zS%i!d^#iHALg|ZC=07N^S`MRc07PEhJHC1 z;BF~rXu}Cef{W1I2J)p;gpJkqUIul_T`VLvvVceLro3gerFao$0)44)PKkC&PMDOK zD%yV`V8}j30X}a(CLR*YB^P|}ANh|g%oXs$^*?yM`+jZ=0FKeeOc10t^epjmSpFck zoIrdMefFB9?&95y>$IH`J)i6AT%Q8K7rTf-z6fI&ahSZ@L}k9bTDU`8+hX4wzrv{v zq)&?0`By=s0)&97B8Y!06k9wys`Sb+ma~5Y$)H&U5HE5Z%gOs4 zPApjD0!xv6gp8K%-GfN(5(mMspa;gcHXDFk*3ziZ1;yiu+@5DFm__LtdP4#L zJGBMiYKlG5Evjzm`Ep(ytEhou0kE*3k(`v*sXcgvCEm2P=B4jjV!GAu{XJP!@xaT6 z;Fsd&m~OIdnCOWZ{j&=$W;8=id;WiAyaUS`e$wTqG9sy3NxJ}W7bII43OZEv0_R#V z`w1`M%stL6QaD-fdrLcDl?$GuBHSXw6KBPyO%&|j3L-mQ+$xa0YYgjZ_a$-I)25d= zpv4cHV^NK$FTpscWjHq|f);R^~gULbOw$Oi0& zZVHO%t1R@hsX#7^XNLRSWp01r+Yz;7I*5H`a(qdQa!13vt$e&0*NC09ZH3ry_k~=u zFeh5*Ux>+GKw%g7jPO(VT)d(5P78n8p+$tv`}Do1sSqq=S7Jcv6;Y0O6Q4jsXcmFKYNElmH&UG4#mw@y!u>U z>iQG_zT^b}UksuM!w8fJSoduMU^;PD;{o7|-HH~m7Q2VBq~A+}3O4`R_3m%K{(Tpn zpGl->46N{qs#VjA{RM)-{_d_#t_)CE=n8~DYA&RhSc}vQs2<>VdnNA(N|>}+co3VO zI4KF|;w2(#F(FVTx2b=N`o@>qD{BaN-NfbihY1+3|4 z)8=20(k`&)BB2Si-!T(gKTimH*Qq$15mdo=y?MQzzcm$j3L_)F?7|;Yf zpikz!;zx^i(%K}vkZdlO9qujjCGxo2ZsQZ*MLP9kVT{|WGJXs$!V5h1rpoo zx$;L$(k2@dkkNmVi>G@^xAF87Xn>f@M@n)@*Re?}D**1A{xj~@|acdX+s2@2hW1*=>+G$eEiCVn6 z)?TB#iE$t=s6Y*dKb+}CZ|LXtOW`>beH3Bk(ZUPr6?T7Xd{7oPcMEB0_$CO_Z%zDi zwiyjxQ*{N0ZK_+|(Q_8q2gIoNkb{RVX-QbhU#3Tnr6-CtEn4*zPT(FUgzWb?YX!zM zv1zMf^Xo-Na2GaEWdOLTc-cvZyGfpVl%;NN-)_fRSYrU8pqDf{TZ!e}hjMs{+#gy| z0RGjM$2NbYWBSEHyhX=roaJ)fW{>8OG#t=RCi8Joht5Z?rkvt>de}_ z>jZ@13E2nFZs(ibWn-7HpL|uzr|WZlwd+#=_+pnQef)tU;+X=V7Ox%2j{o^T{bF!W z++ZL^wGtttuvqZ8$be-P{aU~N`tSd~X#5rzBO-spctGN`=_A;$h`E}f#Pc2iLEblx zRcYKZ^27`Px9;bWR1^Z(Vqb(z1Wu=)Ntwk1EJ_&ayG%9;9vsUStxN>ExOks`GKhr? z3-iU`v=r1Cz;$`Bi!dxPDOO>Q*6bR=M7!H9?h;n%R0S6QvN=SWsK`V4RZMcd^3Ly( zK?Z+Tk*<<_mBwLyOF))1$v!Y(EKF+8)#hmkUi{xv5G9l5h@?@f8jE%FThPqimk|oN zLtIt*`{rAJ^k?Y>NrIDf>sSVs31yX%^0{c14OAf!FzZ2a#C*SSfBUuWdF_nMu#C6kgLzfkJ2zsCmNt?<80JT6$zn0F) zQq1SuNMSx^JAcF!aYbA3qs=UqK$cOttdOTH)-L!I+X=)Ha<&~a0WI#bu~@R@%I3fT z8%tleksXNN;%?GClu2*GUHeP!Jw=Qt=~qzWg+Sp75>op5#;--Y6pq|UtF%dIsTQv$ zWBHkX6rmr1HDuXwM}K{#SoqSesl}L*4MS-yZe?r0Vlv(2V?m=<<)_V90aAr)6*3%= zExM^#g1OueU>_orBPHfwuE=;Ecq;niveBBd1C4Dss$2!w3_F^B;)P$2GUTZ17%vK_ zhV$Bp5&d3@^`hS}YHLNb0$SgBkJ}9j!-0=~E(1!u^rO(SD}aY*J8mLbG?fk1a$R9= zVaM%HvK+}8c}^MDN^Behdfzr!;05txGr_-v;3I7REb@*=n=uxUhn-uvksu7?N!Q&F zxTOM_!LsSWb9Gt|z!MSynXSUW#5ZEtZX=w75B49p-hC_eDEuqqk#TR}n;L@&$&1i` z0RO?J2z6^g4sFZ^q@{?ApX-ZUp8~*_yq5iczw?Fiw=eEgydG=m5#Px#0JsMifo4?w z+Ch4Q7;=UxEtmj=ceCGc<9UB~v7hnK0!oJjfxCc%p@Mmez`_@doS9k3=3^;v>&WL` z=x_&-vol%nIIIb?2qKmwFVAHNipGk6Njb(v;-KUV>?{To2wuT-CqTZVx1=lXW>_(V zDGY-XqKy_bTu5vQEKQw2LO#iXy7> zT*sE1#{3g{K66Ek0`9@*fWznSG}waJ#LeOM^R?p}hI8kZ3ECpn_<#?D54Xu1bT=ia z+wd(u+p_Zo@$OH}8}9fC6%~y(tqVSgds|zEslYd3>n52oqG1;1m3;8#S7xHcNYm3W8 zyp^Si8`zX&?!_k2=)WVd1@s3mJ%7t3>VMTl7-DmyptEk71NQ7Gdm2*|CkqCL>iCkny!Yc2-1KJXKH&+<5l!#_Sp26> z{nwQ#<1G)^0r|Cmg)tW$G2oq%P%V*I&J1fON4?@XkH=eu+ihFBdA`WXU`kE<0@`hY z9Zf#LMqA?5^d~Py(Uy0iiMDGA5me&ee`UagPrz27hY~@aOKEq`Y_rNnfNWuRmi-uR zV6jJYSyrf`YP3_vKasa1wtU!lWPYJ!pXLDS%oaQ)xfjKMSUkvf3AYF&% z|Flv1yOO+++jzdrFXnd6as^uI6S8Iz64Pxv>9kPj1-Qk+W+@p2jY>wv8+P~rz^+C= z2>_ZT8w1i7&x{kWB_#ibVV)40$&?aW$KuV$wsn7$#X#XRd_fDz6%gXb0ciw1r(*JH!r&(d+=c+|1J7Sjbas$N{sE%_68_ zpLBW#02Bbl3*sJZv!ojzHnMCWuREJ&LWgeq9xBTG!2iGg{ho`i@27N`@MWCx z;((BU6Fi9?k+{l>4x|mXfr8QN;nqmtlD{j`)YZ=V=lUYorvUKPuC^CL2H#~tFl17* z0ga0$#W@Sq=9ZQL#5)4KLtRC%%-S&NxqxW>?Dg(qUD7heQSO_SJN4~)TYJnfg zqIlR~+crjRumTqduB*7PL~zFRrwrc7fwhfWhCGb`2%uWdyj*S?PkdPH%-@*^aF2 z(q+6Qjv`vidtQB(;|K6$_a2286&=lgE==cM3MkIm+C@fjxfN@;IK)iqyy@HhC@I!Iy`=@+om!&D&H|?y_vQwOQaO7(1itqth7zmvOWDkC5k;w z{`@a-$j?odh(*3Cu{alNZ|<_m4jqdqPqTlB+@!Q+h560TUc7HygzQ#_{c`SqDSHrY zMI6`bGAbxZTWI=s=2_Hi=_3n}(3-_C*pV4Kf0L%m;>9SK)$&;x-+XM{2R`>{YtVof zSzkk;uq_P9lK_w>pPIEv7Vu}NFc!X6Omuy__L(a{0w|6c^&-bdke>mUxuec_nDK~m zTSeQXJrlDmhXa9j(Ow3QyFU1TV~=hGrnjkQ(TVt*67%9D@oC!wi;bc{bD`mp_W`Gj zBKolO=Uls;DqjZX%X;_X{I_2peuud5qF$gHW#L5$Kb4Yl%6Jcbui2lf+dRQXQaUz1 zWGWQ=Twmk*6ac>5H3BAph>6D;T(zqVfLS9UFu;3x^-R>f`e}ioD?o#PJE*ZzXJG%G z*IfVSb@zu@)wNxWI4Wd`qkq3X0@waOejLn#qzCtbWC2zTsjWa}IfjCvjiK+&bzvt4 zBiXP5T1y-p0F7hi!wfpoCxXLGHv$xNWT7YMDvlMYW9m>f~asHme82WE21 z1+?wN#Z1((WD1g)JX1J-%>s>f!A%wnJZf(SL7M&d2M~w)tSx8m>lIE5EXYW1W&X?3!aZynr{ugSZTCH5d2*%v$aN_U1Do)ehlO4FVgWnFVF;lh+4%l{jK#yoh?`_9{B@VR zx_h`6ODZ)~^n6Qv(9{?5tBF3+0qCkGJ<%5sSx78_7X_#w+mP?v&G8sfTe|QMs8%+@ z7W=-p5th=gv7Okf(lNB?g1wu9av`_GuTtBzH%L8CD%s+@Rp1CQ^a|Z67EBol0zkOL z59dA;>4_PlM@MW`S^uS(Zn=E96z5_XKYG4DjPs4}W zpbnWj@}S?gEiaDwaty^e=?ZT)XI=y#kebM#2UW8o#<^o0@{{I_7c0p1l&kISE?dCU zAX5g2ZN@?Pl(!V}>GK-Y<`3+x;D<#ZV6`oTSuk)h#g4vz6)G7ove@QK9=qmMhLwtU zz6lXA#JFUhDvK)Z&L7sOwkSN<7|1caumr6|vB|Jc63?P2`r3MX(9;o5#L*th0Kxs2 zvU0iG{IXws&bTOF7A^K$4&QgZ`F+M|P`q;Tdw$cI_B71Ls>A2CVPo@C&iAL5F_`_s z4n}OCmHWMa&-E3qPXXYIUEy$8yxAgI!0Q#`W^B6~^;kbFbtV`np+&&<1qvM=#e~;5 zSx``XX>2tAzU#)%TyOut_5Sbl?|nMLE-|6xLtHC}Fz_#a_Qe(gt>X$4=T+Ll@Fb1% z?&1V@ZUt{XWGv5?0zQFOQBZ+_q92uE4?Lcec<4fZal`@(7Allf2w+3(UEhYkfGK7VIy%YKzEG((DodGVSTXxbWw>zGXeV9>XiBxTYqB4FZ(fAc!Y6yM+ zoAttq7g&sjLkG>ic+SM>ot?f|R;rf2dfS$$W6WhDfUJyH+bK;vK=O0XaVC6{J2VAd zniGeA@vW_g9{k*Xa!-mj1Q}m&J8o=c$7!WDdL`A{GPgfrp)72YMpYcc^pM@AcDlJ{hr;7LkB$+?7w#srg_@nI%Yw;9TI($7~ z&~Qt|2=t0%cPt<>iC^?9Evjt}%ERp$Jfzouc>;Q~N5>O=tID)3ahpGr2ct#1SLTDR zvntwrpeAgkqakt2V@L6+kjVMI$1y!Lmuu3o$(`~LN|0O?{>QGH*_C)QL5LE@1Ltei zyDQ5i-NG)$A6k_0NMCZ_K2R%ZU%-NTP|~1jX+Fk3h<&n5odxRw+f~Sa zm(9lf#uKRy05VC)#LpOc6sN=(?Qh^E=oEJ;h^O87Bu#k;+5}F8_cc4Ff0z`yvdD^_ zj$w|+MrT;=viNDa6ak~tl93N)cGYB7mYVXF9qO6J)O)mhscGaT`ml3L+FQr}LYgLi z`M6Gxc+q>x3jcTiU)O)%x~BUP@oc((D8$eXUR;kxpy8=>@_I!sX4o1zFZ&Op_qj}; zE}NtI=lYIcp8~*_yi{SkcZ!faDH!@OEDwIXJh(OhX~{=fT~*N2?xnz#fw7g&;OJR? z=Ns+UAHClE)Ybk!xnBQ1f|EsV9woCyjOUUb+w@lqu-MxT9OQOzWqkA_hP8u#({edg z@W`NU6@Tt{#R3B``!3k%*)rMImLC!t9{U>$vGbR=yA(_;a4e-O8F;|s4EZH_EhIsi zJZQn0DZ$!y;iA5Eql6opP-3^ouc8g>>Y7I~myLnv*=Gi91eC3heJp_^S~16$AwCWh zGEed%Bswdi%||UJl2iI-dytENRm|fUXQvKjpRR#=Odv4rtrN3(%dlL&EP%)=C08>C zmV|8g$n7$G-kSL$Gb&t^ouws9@+5UOwx@5N{`oS)Gue>4C5>nXPg25$_vX`fKYVK| z1;49eK;v*l-Q9h(vno}&ZP?PUQ%)S7eq}aDQ=4=n&(u!e#7Dj*-EA0uq_H)!FZ^mG zcCu&Lw$mq!^}=5kG6oK|`>_)w-N<(#A`}C0Z>9YchczA~kw@kYNAp++7&kjI9ayud zD=y%iHz>)SGIg7j{wyk()(p>_JnLr!n0-r{6IWRTUP&XK`*Ji;sr`=RdM;ihb@_N= zarQC`2z%6+Sv)uVD5u?j&tKI5RvSN5S;Mp~kfuSH~zbN3}pEU-E5O}RPGCw-Jvm$i6$ueP(G zm9a`K9kIm(aC76qs)JX_Sh-vx%KUWl#ObR3>h=1oueU!zm>fNS=|^z?bBuv0qi~LK zyoh-`$NxdVD8{Ya&@f4y^8H-j>FZMf_+l5Tc&bXHYCK$;0oVhH67{Ap+d!p~EB8^qr^?7~z$!oq}cG3K!*S&w#Ln;%WLejB;MYsfvEhVx`*nvb0 z$!>Q5tO;@l<~_cDEjoSAyFdXJH$?IQ$P{5yv|N}Uiyd~kNAE8Ge)3bS0nf^CGC@3Q z*|F1+p;7%5oL;FQPCne97`WX$?&*=Ns~}{OGCCS6;W+*`u9+0=PW)b^?RrC&o*v9a z(kj#K%AFne1?S~8%2+7)&a{a(cp(p^ogk=JzW}~vVmn`dl8h7!yVgcXAM=8-IBLn0 z6n7v0lVTEnCJo$04{VU1$KQT8%;30jg!f6_YeNf^c_uNo%p*~>w*^0;kj1ab!R-cg z0vOcW6)S0<{QDD6T(&Pjx8sUGV>fW6qn#428>fo~f1V&vArlF&_J~6x!9Q7Q6#jt1 zZHZ^fLt|xs(F|j+WTNQ4^xKDc;qs&Ue4%C-6d1HRjPA4-r~8jHw!sVtw#`-8a5z&1Rr*K)#No_(=XH3WK$D?&OFI!?2{YXWO97! z+w5e`A*xOB_VrmSP{B5TbUZ2bWeGle9$)k-1YQVT~GcZ zu&)MxUCGCk_C&12)ps11HzWQx zn|EGSNb*QA6BhBK9gzg-2|SV5E^v`ME0U#uc17@aRU^qL(e4WgpKtE|L=sEtyK*I( zy8`jc$ryj`+$;AI$f6&`Y<$`Y1BlI&f=D2s8`E)F;?zt&APyA{T-;@J>+1nCOlA_| zL5z9|-e-yfX7^YyqH5!@Ib{!CCBKxfM)Auv=-N^8hNP&L+g5KmWyL*{xE1a2o_w}{ z`J3?~s(kUfHD|{%S&TSzt0IvynUQ=_rb|VYtxIdRE$Y~ zd_5lDX`L}SE{SQKU-6axbHVV2 zPi5=~U2c#}{zpMH*^H4U$HZ@cmvwShuAz7Qf3ENR^(g>+u?q{A305Amv}1vts*yPO zccblyVcRp`X;IC)ZA?(3xfQ(b!F(6jIk1ZTU%%e}itGLFx^8_R7GHi04x_(D@&d<3 zm;^TLVrUTj&*b#@J~?(Emt|2F>G8Zrfabk3>7!&;S-+jOaAnav`ijbbJLT0$ou9_2 zeHRP02#1tOF39;e;Ux{~L44>=W@(m8urL5y+jJYRZWT`nakMag+Gz9S56x!azdJTn z#Xz*m>|~FLW2~S%aynlSNv5-Gr4C9@Vu9aI7n*1CNq=o|s)V$2nvmO&V^7-x?@s@g z%Pbg~KZ2@dGl2}|5#hgo&0Vp1%y1?=TJ$7eo*#wY$_tt9ewvF`YX!e}AGBujMqeAW z1|4DB*oi0AM6S1{?~Zd@JFM|+i0OD$quf~B1Q0XvS_r2 zkC!mj=81?jzDDGig{H@e`lnGfN{m zjiPkt0xy}KHg?2;h#P6M*XJL)UVqE=_Wu>$N`sUCw4q_!Yhr~ck9PjN?+NL_jronA zA>Y*SjB&Hv{kguv^(g>+vFi+w%M$;wTgLAhj$I!Fd(Vh}JV+MqZ@8J?SHu4u=~f}* zTAh$JLvaQ5eF0egrfaDG?t1#e7a09Q0nhHu1&`4d-&rji89j|!TSOd3i}5-VRUh-X zA86X~G^A;}NEBeJ9c9sakJA+bT||{zH<@5nDeY;^#|5wJQXO9w5yzONMNh)em+wa5 zC-mM=!Ka^pvx1oKIkf7|+~v`I-+l4py)${Za|hYX5z%_s!U#ovjPp5&c>%5BYXeUK zb;`Qc1m-#d?wKg`@N4qP)^nkeYM54=;(%|P49H)HytKo1hIr9B5)y+GN07&aBNo{G z$dfPTR6v*>A|K2|N6*vW-}$wrQ2Ywaxm)70j1vNX_`mPgPab``3+9}OlS>(&bD{U- zVR+a4Ke-;RAv%wOh-5P*r}%QtTMsnNyD?Kc-?we1{-(_OnE&*Ne0|5mGddMzm)bwu zPtAJNN%BZ?Vx5vsl<$&7J_Gl;knNNSFsx3QPx%I~4|DjTjwh`> z$$jd7B%;j9cFFg&dC|i04anv=e&zT+R*ica>B(b7dq;->#8O#8e}^=Wg@{_#{~$=Kuiavq#B*=__WVZ72 zJKMYc-6iyT`g7OIZ@BLNNWGEcbCKu0PpeIT#xXOQ!w%Nw0T9LF@FIJDuq^yUU-_Jx z{9Iq{`V;`Z*fl}hcMzxR;(PKhh=PL}(A`1N7TJW46@a9iBf~7H2%zklBD8jbSdbWC zeedx6$o1d92o#~W&;FEpL^23>bT)MPV^5<^cAvg0VPhd{k&cq{W8F)1Pf#XXz zdc~ef7Ktj_JR)PcDbmrc7qSldEYp-?Hf7R zEryS}jD38}58T1#P1_XS)@9Cr`8f7-w7}y1$ycD^#Quj5#;%Wp+$ows_oem=zXs5==CW8e6@>zNA`C>w%~qW zzF$^Me!A-sCKxDm=RPuBtNf^Zl|u8fI}=tWu$GuQwB)YbOiyL$Xe zFBRnXFwwhe{u*MrE(K$m<9&=<$?uUyOovg{t8&l3w1 zFgu?qbW>m>SfBerF0P<|OEGjD!*)8;{$`x_xu(^u{a!XJ4IF%w^YLy6%lPUXOJh8Z zSCy3NsV{z?+N9^4HT0P%xqLOv*)A!bd)V`ubcmM8=k40LtA37Tv-fSYkIDX<pZ4@o$&XqHLh9{gsVR4;4&Bm>Fv+#&HNHJ)jIa4%9!q?s5#t#Y2B za(Yf5@I~<2LZpN|sjG*}+YXC!IGj6tX}9SKzGFS@;py}IK)#WLB6*DOBHZ&5F_uT7 zl+!u?>8G?83lN7bPkQ$iHXFW{v4fIY8JAw~!DCk}wh-@LJ?$ip3Io&nF%FC&t?AK6 zi$f24z+8$V@qOxlH!_k?T8oW0xYYaEB99NW?br7HOV4hR51np3@Q7H`EdzVY$60(# z*@1q(;*norH}7%KjZuY*>`SuE6Zx&0X*Ziu90P~ULuL-MOZVVkDMybf9eDEYxVH2w zUK$JLmG&`DiX8C^vH+d1p&?t0HFd$?P%xgVvyIOkGTAbJayt-)w&`U*dEn#N)Oq9Q zuAA{QH6(KD;*VeL|BY+h{{?$Q>JClYxF!vnZY2J zpg#XR;8x@!xl@v#i{__Yy$*T2w*}m{RHN!|wG%V=JMC{(S0uNU-IdT9RXb^k-7HIl zW}!v#W~L!is*r6*pP3Y$^7T31Ey|`()X{D(O!3Hn7t&2av;(6c-uZt7S}bZ;e19+b z^8RMGMg#OP`S)4yClu2RthnU~LP^f4nR7=kWedKAJs5BnGgE&k%oP_VNoHH3{^YGE zzrd74xQ-TXpO3pLkoV4b0z=~a5b1Rs2NZX&(Fg;k3$5S@Z&v0Bfet@galeFy$)mwdG;)$0gqO|kgt>H>04;zjrkz%3jm}T+}Kah@p?t1ov*W2Iy`WRTdk<{dW zwfh7;z=y{ZEWm|*!*vjJ@IUi^dv@f|ra$OYrqwYv$2b)IxxUlarvUKfE_un^mx{fj z*5_sYX5e;Acud9!6M6sXGiD<-JUac(vlZr%XzU8>w}I~8y&nJB>-O)j*H;2Ox}_Yz zOPO(}f4xb@r?j*K7@pnG9?|eOfCRX(%+xwjsg*~{+d*5{4LbJ|Y=%+;Kv;`lJ z3z#FYzAGa6G2yYm^=qA4^nj^X*W1(S0^d>91MgE<97o`L7>h@=w_N^80-}n>MWk$9Fj7y|GJGCexjN0L}0F zy)WD(ov!opac!)aknf*&?t<@?d_E4ZlNh1h2lXWZrkK0Do^xY%rb2%)R!ybMaR@ieT%f7%E$VUBc3OUyU!c94M z+JwtcN%;JliewZ!envDz+RJ!<_iWkZ*eT$ra7jHg3aCg*t_3&hEnrpoc1N0Uq7&VEK3t$+A}iNX~* z#ogXHZ0{uK@FAx=^qQCui{J;lr-iRjEgKvs73j}1I+z_A{z`@#q)k45UQlsyIF0}d z0#ldSz%Vks6)v!_b;!2p=RQCL2141H$ipm04*E&rtv4Q8~^0>@poOk z{#u}7;)E}tQw9h&dF0#^jq!az>py{iN+%ck9W6ZEIj&JR@%=PqEVJ;iI8z?z!pN`z zCHz&H*!rxn2Tyw@k3jD{{wEu1AFi;>%Z1{3Mk8e?%{&I!sv~)SOBzqkZnIc%p9`Fo z^7nC&h;Uv@2AG$?aVm=+5#UA=aX-f~)@OOB>mGMma)f!8j332^%l-3D}h>V;OC+TkH3XXV@2I zT=xVnJI+7v8SU-^;;?g~{l@i2Oc-N?|CHH_kALXSu+RK|?$HNnH)h{sT=%{BPW%|x zO=9|a_}cJ0Ul=)$jx7O+rh^)?j-70qf9`x@y8MpxvwX?Zup!83+I!g;AqUK7w9+M3 z-oM9BKR)cjY$fa;I2HhGeMVcCHBXadS29df@wrNU<#R&`MkBwn@?aO?TZUSI2{Y+wYddF!-SECkr6kd@+OUu$`fQHoKqy$9@0G|6c=^&Egrx47=Pyiqj5D zJ~w@W?Uv>^zEaUU(hZw%o=o)XvOz}wmn8tsgKp*7A0fUh4u`SB}g{NC%{FTO!) zZLE8Sjl}Hpxc)5$RL`vt@BpwLs0E;sH{NBnxeq!N%$xGo-&F6c=)Y*mgSvUt+BEPG zY}W#R=edI3)VdaZA?la6VxVxDnIa#^2pjMWIhZzVR{FMBoZkaImGLX*+9w(!Rq_n3S@7Msy! z_Wb_pcpJg{0Xr~W4?d>eoF~T*@`3CSpP!rx^OCNKP>B`O?tCGOH?d3N{divsVEV|a zV<8peTXJ|LO2bpbcS`bBpYs$aG!C1Um5uJWYe;Tw4FA6FwPG=vJm}X)OSbm(ba1T z+8YqzMlQ^9*DZ(J^F@hOeQFVkVa;SnNUyQby+bP3Wk!kP7+6d@`LeB zCzebX=qi)3jrVkk9|af|8!B}iOO4iC>X)=0!3VNJP`2Rji4=8eGSf_BOy|K`tRcAb znEu_{X$%=}g<)6kIF4y{&hJ?c3Xe)PlCu@V@cGkjKqg>%=rYImyHEa7Ht&3mK^tbZ z@-xL@1J3Vf;seHiv^Up<&*Sue&IH5lcgx39p3$aXdoH@QcBMQ&w4+zE6E%kxgv3X*=kWqSutqRJhA>&^Y-IjPuo& z0Zw4A>9AKl#y9d#e{F3ttQ_9ub}aZG?ESzEqse{O4Td4Y>9_Y`vr~~<0M64vW9xm; zWb?9pik5TUGG5`+y+=!b)l3IX`zC+GhSJ`*1)`(VZ}CAfP5rz=GIzN{u9y?D?Sakg zFNL0XJN$O&CW?H}!@ha_|0gaEzyJF9SK0zZoR$JT!_FSeEL=l$7=cw0Gr39eZQG%K z(;lW796;wEsYe+{+no-Bej5C9eW$Na0pP1$=B%o$3e^}K%ie5%B+?PYyY0*&9PFNs ziE{e2UAS{s`VFb`G}q%1NCeZlYZ-}JUBFoNE3VgHcis4HSBHP#o5scrCw+Z@Wh{zH z01Fz820ovBJ^^s_@q}zgi|9K8uf2)Hb`5$gnFuU?sd?K40^GoAzdX?S<$)$}9>HPd z7*jCIK2QE)A>>AX)}m$RQSXuw&L0MGPr|rISJ}s>5rp?#%Vb3x9SIO*OJD1H)cY&~ zI1_&C|M7UMH5VV!U&y&d6BzV*pC@BXA}kM>;u^WMi^4^kGMaQ8erU}tvAXa1ms1Qk z28}+nWFbkoybj+h>16T~WV)VPV??67#E1Lh>ZBoe?237Rs4&lxbbEfkH$~%R0uB6R zU>Dz-51||RS``VN_YYaO$#Q>~ygMkkeneY`FrI9TW8wqbrX1!RVZ)GJyuas8`RRx+ zFmBK=Tr{avHxuYE7!Mu?D6rW+MV$sqwYj@&m zQ${P4JjS$1XQ7fG*WiKpru({t9T8(pV$^@}t#`kNp7MY#RN4zpwb8~*4pW!jKTayP zz81GivLP*n%`Gx7y7oQpMz1>bxVG;mzf1BN0l|HLY1#b@LM9`cF${L^WS5wU0$6SP z=yl{2`F8!~>%ZT5ef}dopE`aR&vV`Em?u)@482dv#8G}?gZ$HTncn|*i&EKy6JT2i zJ+*cEkqf?YYQqYPpX=*fp8~*Fy$qOM80x$AiYSVBOHpW96pRF_1TgO32tmC8k3a8a z{`w7n@#jd4LB79wj^X1S3)cJdAGzB8#P#;KUjM!;#$M{f<|e0i1q)9Go_1dyzx|$y zD#?uR0wVU93i#kSKKdZT*u}M^B7(ao7(PzyZf6p-2HnT8QQ`TsEIbI00OfpSLX*7C zF~Qd{?}*kx-^wwL$Uc*ts={}tJ$OFJ@Th=)lTYl3l>%olZFG)gqsG`S|2enC*pN@? z40Cibz_VFfKbKu4U%_95?jc*!3{*&_BDqJ0K963e!LP@HgD;%MPZ4IZaA1w^s$v(M zyGJJEW4F#;xqHp|T}a=62Tyix4Mg)jxJ!`q)2T6W3G3~4;F;k;yB^Gs(!td&4_&6qP7)ZV#GU$xOiWT?>*@oWsAZrg0 zxM+@j%l}STapX95Q%kaHl4?iPsVjHjVLvYS<7WB?r)2a@({V1vJ{;#ImII zme(SN`{HwX+a6=s9C6&*92@tSpE#+Ti8dL))IA1CRju9J$)e-*k}Ms1AVVoc{1s@g zqTV6Xj01-4h`Fu@%4Tcv0ZYjH7AC)+A3l9cg#Pdbt2wsoaRwEWrRPe1^%k6ecv<$p z`G2pR-+0=({zKRQ|916jbBhG6_Jz6wV9DN$uAr0HZ_Wfcne6rZLUufV&FRvwh+i{7 z^Et@hws6DLCBChDp920|U*h@{0KVE~LHBj7@M&*W{C@F5fHr_y@#VH8Oa zf7+q#GJNRs{o3PAfb!&t3+D)bwlUFPx&Ht4SGzx1clGoinTz|VL|ZoTjqRLogNg1LkPs$(hYO5sQ_2|Vi zA6&TQHl4+yLGHja8Gr1yb#Zal9`Kw;(+~9uKQp;|{3#R>YAhIyVH^Rbjn}r5tsh_D z_~LtPNbY-foW0e4ZF}+E^pvj^6X^h^4|{cs=sD0TE@;3Hco3F2T}6W$D`NE{2m^4$gg4qIKqub9RPf>8xV!{+>$kB`TA zGqATS&}B&_+;_Zxn2v@$KJ%>?R9hroxBmP!-fz3!{n%YdG=Fzmm)S5R1YH6S9AsBX zk^4Rho3Sxa+i#$AV>s|}$q&3JK)f@aJO?PF?~tisW^W%wk^Xait?N?&_-YrNa0Zn! zXDopS-oIX-9CBHMvN4x~v)T~gN1`#4d$xH1mlueQ)z%DubWZ17um?=6`mw9Ye|f$8 z*7fh-yn^!I%fw-f7p!&;7QtcC611D_YzX{;){!HKOa$tTmkJiRKLevp68*}aKiLGp zbvYmV1jiw4BYMygVp=+47rO-(@Q$EpJhnb&aiAp|hL}+izWWR%l5R`1J@7EFSK;qa z-?!8@l7X3jESPOJWL@I>QQ6>i+KkBum2kRIRS3E zcw=X9=#_bdb7C~DO+)PTpi!+zR#Z5nvekMdAK1yiXU^lUn7mC^Tud({6#Kr(P*j;L z_*Tm1q7?GzvPCbB?vEmg``KzPOf*aygD>D}$j%dg(ZJq`vAk#YY@iQ0R?soz03KZS zcAx$dc%(VP???5;G2(Qwb>M;*A!Y%Lywud8?MiM3#dp_h;fGCS585dft-Z6^9yCRv zz1Bf1`631actDyN#U`9Zo$z(LD5(357q8q>RZz)e*(efl*fzYQ+bznG1qFWIe7Vhm zW)m}i+govgV?q^vZ{2>+;&WHnhuh7~pDlF#3T!vr&nAWi(#y;FD`&rV2pgwHc3hYY2STOrWH_+@Vh_S zxXHpxnDc>ITL;!EG0c3I{(^i(5r`*w+A!6Bs?crz7i!wzgQM_%>^*`5saVYEme04_ z%>rPO;y7e-ynFn$tM3n85C4Pf{m-H(g;O$75VZo6Sb6yBhk;Rh8;}d}Ox!WdV*B6? zR@J-z#-i7}DgsDfioplHE7ZW^L9u;+?dSR;*QWsR1uq90R!(Q)Qts&6tJfF=7uvah z;|}2V&)fu z;%8Fn5hwI`%ExU9baMwGI#+q(s=i8pV3rXilhF71mnR}VPR2|!yDXqnmdYLS-cv=| z?XikJ5$TNkUYRbaAQ37*UMZd`CUWk_mR2AnD+#JnQseFM-fYd)6$wmlevaf9blCUS zoz~tv8086}7I9*o2b05we!c~fiw?LGZfZLx?6b!cMvda!EJD0=bhls;$!t%5d~Z9d zbtF>`z)i=l`+Yd7+15}97j|THne9jru~=Q>_XKP(w;$q5!6wJoSa#QdM8h5Dwa0VH z*km#7O!jVF7g^fFY#o?hh(pshI5$pgNT!Q8vaGo;jQ4_uvFIj5>#a5)$Ihj^&e$dm z5Mr3sz(|}5@Zu4KqtiBqYnxVo%4VhS2zOu;Ql6RP%~7+d^t0}9+Z5+JbS5tP1XLOJWTm5;SqFti+JaiwBUzD-z4mb zw}HL*HxTq=={GNsx$!Qs%8!=CsXad8OP)d)4!#YCi~4oT3%_A?let1J&@=UiJOVle zpKj-6{UGa256pS1s8D2KaR&AV8{I_+w~L);{y*2efBbs=f$Q;KGUK#jpOmZ z3IJd1A|NdUIY4?TAvM5yU30;`K_wOi!zZ_&^Cq3&9NuYJ_MQnMZhDp80p9_&m|2!st=X`J%(B!AZ{yk`% zg0R3##+z{cU>{JI=B46cTJqXl>t4IbM3akT6^%op*!z$Ngg|XcC;2_b_UZu%h=_U zP?w8}w&}b5^Z2fR1$!5RJe7UjuZ7uUzI8SCex!Z+LdEZFqeiS-1CI!Rgi&XMc}{rBKFe!IS4slds=;x;+K7S{^Q(FqQJqtz#(-SYuy1Ez-~hfRy{ zhyi{RPBYkYzut=(ufg6|mI(7~%Ol9AuP%ukZJ4Mq{uEaz^EMH@P32YeBv z!rEe2o$$(kCbr|gKttP%l9tN?i{lW9`NE>pR$h>aEojf(SGO+13e3MnJvU3~L+$DS zW_B?KS%>yPEkN8Ry@*W>=lA)iExGLBNB|4R2RXLlz|bXVT040{>)xM1-?C9iU*%W5 z{2Am)FWwG!leY}R%^$d^2Y<$+0S9Tvtmy(je!c#G-s{~@^lm%(;>eCSLrNxGHj+Gd zYx7?5}?DLZwCTJw*(BRi##C3s2dP7yDX%Gj-+FN6OsFb0#Z~1HIHWYW~f~ zm_DoL={m|dVQzUGW2;L&#d-8LZ1D6b3=Go9_ zKCnjQ$#F_cq2)){kH4@E{F8O~mog`GeMr(4zxN!ga2E2}b;GahZ#LcKdN0xVFXbQo zkczM^r?WL=Gb_W_nvpyuF$JJ3B3(L5Up{QU(R?esEhqrIF>*oL&9lgVV4a-Hs4CNs zU(!jBmXP_z?B+yvqkh-KpF9}m2;7n8b@^0++>nx5eYVz;3&rYwS3bR=1;KJeb{l-V z)OT0@;}ukXV4e7`5b*8m_uty2mVW9805xWHC;v1RL@RJTQPR}a?rZIiY7TakQ?AFZ zEg8Aay^i~1gZ|i8>FmjW9pJDwrpdV_F)8GI{<(3u?UPJySHc+)&AFQ$4M`#k4O#fm z^+y6?No31&O1Ptvhzfcsrwo}T<9j=8;}U62vR}j>`YQ;CZ zgLgG0(U9xe?qw$#%6KnmyY((9;|^9TRxjdY-%GRLA_pT*K}!X6xH+dv0G; z9UlHmU%=OOQDdIH^=zP9$d#<(TT6?ZNpEV~1^IR>aWQwx1Z|wZpJ!2QA-+w+NwL~^Eul!t1`&1bz z($x5|B*gS*89!m-kMcfAWB#j$=0rfNu|Qp?v7uXI+L(lFW^k8wOjEksUW$Cf>e5We zOvvoZo%P@y1nHG(H6N0yw0>gypiP_uf1e|LU_~MChaV|S_U?tk!$Wz-?XO@PV2pkH zkHjYuIx8}+>WQ!QYrEnRJEZlZ6RfTuH)CUcy4@bv=A_(~{Tf60dy1Ff_C~MvxG-QE z-g)_Yf%$jdOy06{(4(BrJ5FU<1NR8Sa@hmgigMhM2m{(un(k=RjOD=#1HML^3>`g8 z3iu5*HC>28iML;Stv&oH7SGRZJU<6|mF~}(lQU<=>Wg8%4$+M9B^ElPp4t(Uw`=R9 zwlID{@!nz}rK}@^PSVqt^3;2L!vRE+zF$|j2@cM_spb4Sat)OBG{3jQ5p3L&aB94F z<_?eAf!$l{rBG7tqUiyq`S!)FMNl@Z_t&5+(+k#=OOYoATcpV^Hqr#zCENY7O(Kfh z=Qg+MLGY^Sq7!YU&oyc_AgI$JN1VAg+GXH>hr-Zl4LDp}^pZnG+pka=pcPUk!V){B zpYTY}Za`tx6Jvv-t1BsNSOOmF`dNYWbUdoFl!U-2r=(z| zg>$2Wvt(osX)BL%9vPO@QwN`xz-6;dD$zs3n;A1&zN0qF%bk46ov$C`oO{Gt# zgtlP2n^uSDA@ePu>dx+939H#?OjXk$ya?WHgxNpdz_-PMF9IN}V{kDX1eJ_cw~hA> zNCq(yS&uW8deHk*%4{9f&_V2`^LWmY>WwciO?1MsNvlsjb^rMJ`U_z8WN+aepZG=&g9*Yd2GFJ2I)k2#@%N)Ey)ZP)j1Y9e8~i&bQPSx}k5Y`c zpNz1aGaA4hFeJ>~6|N+@sry}qZ4+tAGYjw9#8b4Z^Q{&Jn~wzJFSCVjIhPDun6~?_W8rLNxSzricDIXt{q3fs zzX@43B=fxEjh(1lBmNm0*#1X`?q+>eiN>LDHXxYxg8F=YC@uk`=t)b`bTNDw+UaQS zAdvHVRb~Ek1gA7{_uv%=s5VZ)hdho6m^o`|CN^yUCcaTVTb`=zemA9?X!`|oGWLSp zs(@*hvx9r+i?^`zrVp4GI~7PS=Ub4x==h$Y7O9&fGwZi_!!^2?yU~>wgT_OG?ESnb z`hbM(SzZ27$bg=Eq=QzNN%-RD))Wxpr;)qV60TFaAAd&wMDkw zNY3Djq~m{<*LaF_y;0N=-KUamHOo-0R}M7uv54rKY>-Bi0k_K><=yfSwgvzf2%Zga zRI`6hxHM*Xly&cIr?|%tt`d;`dj&6AF1-tdcCC2Of^P>N!3tc;nXSkMX^n*PwKb=bwEyB- zeA4B88L7)K!JVpD(w=xseG&8scpUHrN7Ju%LquV&xt+u(DG&B#g&Cks(bpP9av@i6 z5hf%lulov(mRafV}wC_7jrD znNx|I#B09Y&Xa`aB?_}pRVBrO{uT8f{-q&Ag36L>o{}Y7m1FG3pT^;7w`j*FlS;ai=E=}dywD<{x z$Dh|Rj!GTpXK+qCrvV+_P=rX>k`n~^g^~g-3AN(y1MsW zcP6B9;ro{9z;4-d*6-MBtyf{viRLfMi!!p8mJeb^>lfk9+ctMuac$e9(lyelOE!Xb z5kPFKb#WP^Ka3+aZ&2Y%s9fAs5@%t)b`&IsclqbdtjQDa0HS&c#QSI3oi=0|mAwpc zJ|Dm@2`eXmii<#mTOUbkR30(~f@<81ZoegMO-5B!ul+Qw;FszokvF92pBdI=+e1op z=Inw-FU>%hBd1O6LBMs-XAC*`NO1J25rj@1wh~U7oU&gPB<;ny)Z_g$L7(5?$LT{@!hVEp+=dyPv zBix4LLRK8Fk3oKGWga$}yrg&X8ps|sU0ATY^cn)D!tBp3OV4hfqS#kVO$T=#P?CQD z5voggh75f2)mPZJlxVl+c-_f@4?%ha3ST-hmBlqXTo~?uNJ{>U%RG^>-&)6F%q`nl z2A_?Sfic35-bVN(JpreGJkl-4w_8Z(FERP0AvV}Y@cqpo?O$?)^MSq}Z^;JgeiTml zc)DpBxI5n+b=~Jgo*c0<+zp+jCM~`Q6-ly&R>Y5hjF3gs$?hYX9pIxwAr&?90sX4Q zOXWe;KWdNauR^B1d{hPyy-KAbLA>Mb&K8!47-Hac@d4)joxZhf!Sc><{R=puaP*MJ z3)0tRLElnVzIOl9kqUx1h4;Sm;nJ-6cI^~ku~k@Lo}PTIRG4;3mus5x;S{NCekI=g zXlR)e;4h3sr8!lD8(ky(+{-u)}g;TN~F;fyP%$p<+i*(3)5bud1dw8<=y57c749IZF@MnC3MS^@!UwnS9$Knx9#WZ`Jq4(Jk!#`Y7 zV51jrTar#w-92r+pB`N{A45`)=((yE@M~4db#NG(mHfn7=0*6jN`WKj7pJAV=}m-f z|HUN`>@ama19$$c*tu(v-@st$&(mv1*U#%O#ALRZ=T@EANE6boR^~5%Ldwrr$H7J* z8U0Qt!?L36Hj4^&Df*J-*xw1Aozy2+O0bS)WpY(23#aJwN^^oItCtt=L|zbpm}SE! zr`TY8pVc7KFldeD4 zk|d+;9f+TErqvTh#(lAKO(8JNn`OqzDIUdL0_P9|P7qXX!$LBKf7Ieaeb25t z@+N9s?MU0OMA@xMMvbU8ZSQN6~a5_`B zpP1@yJ7gs0WIH^sqkB+P&(B&&5lG9paTRjd`9Rjxkm=D83z!`Gu!Ep(kF444w#lP_ z9lJ{8R#Ch1GZtpvZP{RG7*%XFNx6~yx2bRuwQuciKgqz8ztBcrUb*<~@7wzqYx&Tv zCD7PkAYSh+?dG&009d=*b*K6O6vU9b|1hCEuLOTR9vhzulW+sgW)5hv{V$Y^>G7gI zmJQzLb-5|^Z4Q9F8p3Y85bwo3vJ$_6dg&k!$jXst=)kN z+(xa+ghgNN^2dq~7VBDh6~T5gp_{|;9rMEq>C#>FST)ZUPMg9w(ZQN~ zp+?W13@Pnv0c*UJ<7+SW>Y_#FV+I=QenL+Wm3o}A$*g@uczYt_>(li)-ut}*I^!7D z@2F167>P}fu6xA4J|E$10~Z3XZv_jiU4%rJKL6uE@9uc+?cM=y?9Pt2A3i?4f2Qxl z)M-c-#BwJTyDd%r&am;~Z8+##TvUiOxgYNNAsJPdw9zuodw7q(-7auSf$U(Y0qqcp z4x!gai-5UYxM>}+0Nk4jWzB$B9-i?Oaj9BRQ_?!XP~F`*UYh>|V92a|6}WuE(9hDpi>chl>|%<%E5H1XGh@LVd(^n; zj#4;wqM714ukCp_<|Y69ny|~(MlkCFxug--y~(4`3frjeOvRJSjDP=jL$RpKb)7{E zJ@?W+-ug4wtzFjy(0z<9sJB}kJj60p%b1Bb@TxtsJQ0eUsJbC-?KM5e-f>b#_=}wB zf${Ul`aC6h8hH$2ta{+KJ-75N>~RUa6STeQr@y)%P}zn)bivk+l!0BDs`;eT=yzl6 z6_2h+zVl}hu4B+^tY!Z@qF>i%XTi!^cN57cu|td35)PaJ9951E_oq@Xmx|;_z#fZU zsoY#V@(3dB^v!{4Ag5G5`|8s{FZC>LCfXM4lIM-)|l-+#p>dwrThK zg^`0HcIGKB&r2eR_Tb~xUD2L(m32oIv6 zbNM&BQxPkGPgR=dh*i^OX^2crZBiF4wo6?Ki_43Q|HQq=M2)1WtX>&O*D%AcLdZK5 zvsUDose^a`Og1K1eiKdxfMvxSxZ5g?N{Gq*)VFuTEnRp<7?I$xu?4(0zE}^Guvi1?E)3FmJd!< z9-mM$&7g-4AhL&I?qMp{6}q8v)`aI(a(p+qjU)g7F7I5RR|D1Hkg}HN@|M^0F=fC^ zQx`cC$01QNL%kNS=Y3h0qm~xM?9ntFbSRcr_TJ#=G6_+g1NH?I$yo%|()@ zkw0C#k+5%&m%DEBRK4EH23kmF(B{-hiwCvqhB*6U5&j7@QCf z*6QWiFCG>M^P#E-7(&(b@%^7P|UL8ME%wJBB5&r-uXb%635SbH5j~i6%Iqi1=@R>(c=X^`~ zep6Z~$2|W|&^cH|fqF}`)9@SQQwgi8&MB2@AFRLo^?~HL3r5x-lCOQa++y*vF{Pco zW{`V>|8zXG%KeCG183l`?KEE9*oDC9TP~+=kXz@?Z(}QzrF1=G)C$g(tm03HNHs5c zwH*R=S1Y$E*4T_}Ykj?)h~9{U*LrQj+OLuBmcgrjI&0(OYAMnjIoC%^P&CuD}g)5=&X}y^6t+$-aGi(K*Me-LuVWHk+N7*(HNCh zsS6`->FQDVh zSinD`Ef3CG^kxzYWz*7fATLCW?v;IvQ9eV--3QpB(94=ln_eo{cd7@@72f_f93F&t z{X#ycYBV89HdBz)GC`TCeESqOb6lvgHtc!Ek8kvpmb5(35USAK7E4aLf0pApBGIy3U}Ro!~Y9h_6IgjyKEMfhWi zLXGqV=KCU!p%EGfdTOtCdYKHZ2fxrQl)PD>P>O~I_Pclze3}tPMxSY~j?)X~zeJl* zze5KWeQF>s<5KK>kuCfdpH`;qB-emsw%4q4AzEA%o`vZs8NoHnW#+%TeNP3;!!x3S z=I-;p`5E915x)aVZz;FJu0`Hu6TuOKLgLbT6i>T;-^rC)JYeRHJLlg_otMgc07X^4 zE67b6ae6XK9k}uin|2+BE^ee;%gVwEb%9v$+$YoGr+`ChGJcw|s-kM^Wp*LSYvnJdC_aefy zOx(lFAj1o=YStea_NpUrj#i9}EdO#rm|=A%qObB&b+Ht8pxcZ8*DNX42t!t_3Ej?R zF&aCc52=%1m%YSe$1LBM>63Xe%yZ=+5j^+rYA@oT)*zYP@Uqv^)W&7A^TvKA_oU{$ zaYc6t*P2#r-9+15$iyAc@8+#Y2kzf>VI2l(`&8GL8~Y;naRAK{Pj0R~^F?XSL7U6i zUVci*bY^2^+mr6ex^3(3X};Cd$M$VnCxvD6@Ty}=s3ec__=riv)ydh(Q3rf-z=Z#E zQsZUY$yI}AF+lYnsV5<=n>=OGtMPiMc zJIftEf+;Q#K=pnkQwq$lxiIH9yBv=A@Oi_p%|-KInJ;1#i}s$`ckB?Xn_AB8#@i;?$Pf^#wCU(!saSsl^m#i` z$u0Nn{(&S&NwD&2t~5p_J6bJN_qV>T%UscEPEsGxQy%v~dGaYY=Y)qeHZ`g_fuHB! zxHBoCsnz4B6A>-lBt9pIAmW3-?L6b$}1nc(V*t%HiI9+M&6iHX=47ndbU@6=%KUs z#W~=21=5PVB@kbSMgOc9UUyt!@Hu*Lbj}6hRL70V8Bvk(OGrR>jwVD&0ms@axf{c) z3glb=7M8y6Y;@(CY=eJ@^3dhP%}KB2j0aBw$kT~}C0e4AHQo9;9gIO>Hf6xbz%&+b7GJd71I_kr2<=f-9C&*{U09wktlRb}ztZ=N4E$uUU&xOFQjgKn zGj1PzN|2m3UKP5X18)KtQu8A-g=-3G5yMp^Nkz-oG!vN!J-Xvz3h36T84x+8r?c-b$ks9$$`^-7RYKiUKUQ8MJyIdx)#6v~PGlixgliu0{a41-dho$$6vxUqM@* z@r?Nd=RebamJO;wN`*JH>RNV$Nrpz<`g|k^`4iip9VXS;DbF!y%W)AZf3*)ox_s%E z^%5)KUMse#N-%tDSP4-==K&1OJs&B8X83Bb){%LfNcX@>!mmFWLE{@!hYe4x!9V5F zAnSKqI7--6z(b;d0Iv1D(KW`cJpBlar)IPJ^o}dLsl>CuBL0@;J-?Tw87fyNt;MEi zKhR`u^n|=U$nIjB^N)3Ri8 zz0ts^Btjq^j#186Bs{7z2P3nSr@*q_jB#P~iEJQ$@ljA1jH#*9M&ZMoBF_4yuVy8w z+th`I#IDNlajLBxIuzSlOg-4HNq5uN;b)2_F`WWNGYVKf>w!~J`_WQ%Y$Y=lUhs;r z<)msk9}vRZ6!|L50M_o@Lz$`>_b>ZD_3a87Si*g{zm1OpZ4S-y5ru1eh*>njnZT@R z;4nwYF>=;{3puGcb{jVY4&4ed8Fdvt^6^#l-S?RemqQy^v${IKuf}x83D~2(zlbuM zJ4>eqMJ~79uir`0yNLT$_hx?RC(;8j92uzRFL0s2pxK42)*N+|0*FzKdRiM-dPuJt>-csyryn#19h_CIp=>0> z$FwXu?UEW61f$-`LqO{%{1&doNWbk*>WQb6APshX~MBEL_TwbV=K4^Mwa`k0=gqo2BG7;3Zeh-@sqVBj*p3!}luRvTf1PvR3eo+R` z5K-;*CM3!>O!dtil9+GJqrsMzFb{=|yATW0LX%d*DzR|JCpwpo$eG)80-Fq@OE0{> zo+7K^!{KzK``=4HU|8?$Iieh2ZF-l8orY-8qp8!p^g zmZ(8w$&M|49@$1ahKQHP6lHn>St0LOD}guQ%H2M_qArb43XIl3%qa^7!jB%N-7*v& zWYn>1tA6YA`S|si_EQ4nO2}6^<32BOk9voVxCkN1du*3&%t#xsoQGcSn@-g@oI)#& z{1RH{QPPZO936lJCAiJ@Bu*?NY*Az26bE_R+2}gYV3}X*srH)-g<7@3OR-XDH`Jgp zuVzSZQz|sJz-cdWXboHR{3CrtTH!fWA=k@eoJzK^>%;kAQdAqa0k-Q-D~Yk=eB$>z za!dpxY7!p*k*fdV6jz zCoV}Zpms#XVbqKOTaEwwe#;9~8?NQ{e6mt5U3$r=wc(~XaVTKwX^xdZkNd48~y7@u9#&yBZd%6Lj2x%%l?B%0ezNQ%giY$P(_1A-{HI?7%bG0pzb`)?Qm*Y6#kY z0?_9P-VM9C4H;w%l<@m-iM@SeXK$z*s_G+O4;t6vs8e*maIkaQpC{KeTRKj&wLT=N z-2)WH@*P*k7qmIQf|ENj95)+Ec)p(okmzuZRncknH0)y0h7`;g7ElI6rSA>sOymIXDL0jQp*~vSZCi} zL8<2s3M2``@frTt4-t&>M)4goc3YJ%AcoR1My4o z$d25>P`iV=W<&vBsduVR5V>QjybNc4Uc=R(ci7tdXIaKoG9o*xj~c}b9?dudfy>@q zf7m9@%;D5j;X={O$j&X}HE%gl(gWC3?MQ?_cu>rZ{*}<#Dqq+t)-V5ZHXT26e!}iA z=l;rlueLtyZa=qH6ad&9F2+&Swp{z5{|-ON1f?@CcFoTHgcFadY&VtDHh z`W%s9yg+Wh@#V+i#AJUy{2U=Rsh`@CC8t;SmoHw`!48Y zb*gt$7a`IN$$?&DDXZq*!S|gc{Tg70jCtMtQF^C$@GMesh6%a2wh%W)&C~_jn{G=q5H)k z!{Db(tU?Qr{FfoMm%o6xW?t|#?MU!n0Y7I4UTdD2Gz2uaDs#BL=-gmpjG47g#9%S; z8>J=x1T@+~TLd zhVCN3K2bp}aI`~JD?$1Rj?b87S~flBs$D7)d|)4mwhP@x9rqH%1sUav4;=l@c64=c zgOd^~0M*&sn^T&V%WFoc1fWlYDW7xW+5$M`k?nIOCDrhcieGrP96y!Jcxb1-nqaKT z*rw@M$@Y6320U+{X)q$2>?W?be#x#QSF56xAy%+uJp1618b3aa$-jNDT;w_;B@Qw8 z0MojmHS%UHQRBLsmGC(wN7d1Rc7iooMl&G-*cvHaiP^2Sgvw-HxA(uN#n!>%)LxY= z`qSx`GNVUTd|r%1>1aPUlB}}+ksI-|yUq+XbE}D?sIJlP4oi0tD7X{=w6^};FPMZ* zwedLRUYWgKDGxD!)(u^l6h8m%T9dpryYO#V2(p}izhm`CeRR1{YK@}<-J#Hk?PT>7 zSO^Q0NOwe>Qf-`KC(vgLS|>YGTVv5BDz%|IeM1{A?tBIZ5n~1}MP?lT@i|h!?Gp_o ztzS4p=H!c_Mle-w&f*^FlP3Dj+v;P~M>WTktKv zXif4Qv^jox=(337V5>GRpzYyj<*2^R%SORUnQlT%B2CdjwenzDh83uyL<0Rsz}8`z zeXG7;TQ_D<&Vj#I?y*ZGg~FXmGtvk?ly%t;q&^N zYe~a$c`B{*^uBt1q85L~b*tQRjRA+3-6&pW)x-zyhD`85bfC9*ZA-j!Vr5lE4gtu? z`WW|?Oy9v9@`_l$ed*}|sIBa$F56Q|)4ueL0&)$YQYpn-6mn+g4#k8r2ntE6da4yG zYhJe=cqEzU%981W_lL|kNo&X4TBl2EeA}gF zGXkT8|D5WSOns99! z2N)u>R|MKgYOKAznrX%YXL;ksd67??*L?dQ5#>mDE>m{2;N~ashz@e`6~?#v%e7i> z{W8*u&GE^lG^c=+u<>SkE{;sRy8d^fjtPMQIhH_lA$w)pGy?TM5Tb{Kt#^1Gtg%D8 zJsncoo`A1gmdPM@3p-B0DP^_{z!iY+cm}DdWPlTN0O)_&aKZ;(cmnVFmAcf6o8{@;z;Eq%Js^;nv2@ zRw2o+Y)4*)3A%S)I|qE2+L3)Qh^_Rh!`k*sQ#N&|?Zj}eo8c|jV^7%#iTdc=%+~D9 zt*C%V&d(=|_@vfV25e}s7jj$91Pe_3Q3!Ip7vY=`Uvz=xx0GxzHt0*QUZjL%L90X5 zI$op${P(+Ol!{->6JVrKs6m=SdS*cs(wh$ms%GD$4Zp%Y1e|_ii#iHm9v<-(CqMwR zASkBb>Gf3~gWDr3-PHdU}?2QEdw8zBI59)8e8;q+*CRF0N9CCWjB`yu__8 z3eu6EKZI|$tS@7wYGf8(l4WGrIb=+W^x*$Efh2+MmV0wTOdI)m>CaiuKPpTW(0<%g zRdpPB9lP=ez-pFo`<8oBt;4Ug~%2?);0dr3;d_E;(w0&uflro+4Dc2#Q(Xv-*)!rs?~_x=C^D3hl%TG7(T|R IJ$wDX0Cu(xO#lD@ delta 327773 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⪼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

>Ze%cgR)Q`!Z_5oJ+p2S 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≶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 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png index d033f2d678a3c7f50ff690d1fd883ecfcb980454..f4e70fc113f153d9ea520aeb1287115aca976f7c 100644 GIT binary patch literal 5762 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 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png index 6eb2156ae33306b8f22e059a48234cecb9f36355..61adda5e7d951314a48cd924cc352e5a683e0e4a 100644 GIT binary patch literal 18240 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 literal 14960 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 V0QC9Cr;-%#LsCJaTFfZ$e*iSv>xKXT diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png index cc4f25caf52a17be52676661f4cbb263a0bfd55f..fdd4d1a73322e7fb17652afa2364f8c1e08934e7 100644 GIT binary patch delta 983 zcmV;|11S8e2ki%tB!9F?L_t(|0qs{?Yz$Et{$_T!H?`fOH@AvvvqA`=u?ZT@CbIED zgeYlT5+x;ddk~igK@e~15|nx%RQj+kX(Uq8)V-BR@KB2qnz}cuU29!-j&sg-H#4&{ zv!)0S{^ZY``OlgE`_6a%nRCX9ziih31mrgZc9p?0D4jKDQ-80ZUPN8&Q)UutNz{GR zk5WGu{t!Ud<}=y^ECbUi0sB7Mtm+e}z7Zy( z7=|tZ2L2NYWPe&yadLVECS{N0_qnMVSaR(cK88by38tpG>@0>e@qs4K0+C`WEA z=E^O^dG{KWT|I=(FWtrjBm)8@fdXUgc{uG}g`BjExISm*U^L9!fCY^Q@hI>{H;1~& z;}nQVq!>pqExQo4r7K`hO4Ut1I6V^=JnOKy@i1yNa z>y;0$f_@&$OLM@LSA><5J(w_b6jH1<)Rb0W%gs8}`kLtoK{-i10vudMpuE6^?XLNX z2kP2xz<>Mh0gxm@ptEHbvRQe|(Prlam{~*-d!{Z#Pbi4`=XYZq)J1Oa8WLQ8`Vi~8 zk6^+05)|hE=zZ-jJlz*cu7{JEnQ&bTP?~B@tp7%KUvV}Pd?g|s%Mk(s$@EZfH0HjBo|jzkqz#Z7$&dKv4T5j26-VCn;%u>#sP;Qt&j z2GTHput$4eG2DzKDwuk<^mgl&Q`pi_Yl?u7Y=fAV90y3%R4j^G0Uv#!K%GoXu>s7@ zn%2@u#HUX{A~lquM?0B$e4RWs`UD8^Qcx1r`2EN7s8w?eJpz*d6C=US?M>9#>9y}a zCbG1M{Ftzrd!>&-MW=#5_t7iSrWdlK^PjYT>)-Hi*be|pn~U0~#BBfo002ovPDHLk FV1jw&)M5Yt delta 916 zcmV;F18e;42dW24R@c zA&HblC759L5J*wcLm~81MhF^Nfr^r-MD)_fT1%QQ_0Wf3Jy`e=sHv=)uFmbw-F2DS zof+N5u!jyD_RhWcob#J=&dlEN!Ul`ie*ocy?q(r0`XGLIn15;s)p)9Ek318{h@;w1 zwU%o8@`MGGmztyjG@F7bK*$|BEcYm=ycntGQLUz6=YeZ z2|x%rOVxe1ZkX^fWC7@EJk5gp0PYAMLmDcEL+zG zz{ijU;DfIr1AjW-Ks?SYL9%`;yN>V+MX~ulrWfZ{2XHE}a|S?G0f-LNq3K{LwucxT zbE)A*bYz#K&{TtwxhZ7;P62?dl7St%C^XXG2LDi(wM1pU_r3>~=@C^pri`{#i4CV!<2*m{6-vB{53Ms@lL_-Mr2 zmuLerCu)sjPU{u-G;F}F~NFR zXkb22PV`PR_L*&KcKI~%1CPFRqGxnaT-Mb}Al&@z*BH}1n`0dS`y&(Co_Xs6ZlxDt za>0U1b0f25Yj*iQGtK~9#H06sz-X5~8X5G7cz-+Gi>jV>nuU2-mzIzjmB`jaW>UVK zn%u4T052-qjJLB+BCquZ`X+|iTzEhTn^V~v)d4NxOSuPx?*X=3049*=5IvseSK`$3 zd+fSCuZ+#Ph{PkUTmr($7`aYu(;D!i;3^w?Ya~u~M6LuL{TE1=MKZ96K)Ih>0c7en zHGe;=5J*~>jk_7372u?(ub3K`iecSmvY8Pgsbl4P diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png index cde1401e1262960fced044fc48a3c1eae026e2a9..365e9eb15201d97c485f9132edcfed7611017cae 100644 GIT binary patch literal 84277 zcmeEsRaabHux&T)kl;=N1PBC&;2J!^-QC^Y0|aRtfD-UqoCy0_j%H>w%{5qFuQl{Ae$C{znJSV?&ZP*Lj3F}q z@A%r4D1Qo#R4DJ56}*#A%X2VwC{VDJA1BmMv2|EJj4=LYsJi`-4( zsiD~j|KQjue6kXZ6Q@s^RtFE}LmdbtVVZBDJY~kv40%-yI2|;_HCNxVCmJ^Y-mlx$ z;C9D|scS+n{cj6fkCRbNz?17SCG=dYDu|;b$j9WI?UP5h#U{L8p&-aaE+{#vqmg{s zq-AVGYv<_AHGf+3;WXi4y{n1M@|v2|;}>L)jE^7mnIp4B^U_7;r5gXn5MW-?1>jZt zC;bf4K`n4>5zP9)A3$7~m`&58QnOd|uE8%#VCeXKppiDrZ*_Cn)6Mi(*C~CPfwp$xU{%^gyywMG)Kymq607%h{yrE zDHWUq%7l0$I@d;?+#PRQP8g2Hq=M5kKES_&&e3gwgQu!h|jGXGs|$ z1oX!$XU7FOqjAkt!_{%d2!&X1%@*^3P+|E%qMkG6iAJjd+8CG_V&H~M(DzXVLGzk0 zjglga%vKCaOS&SaFkIrIuPY{GttCxP$n>J$5yAAHM&q=JGLLTd~Y zV_1cM->VG&;))XEVE@!cyp7r8$A7zV@$e10?w77_v^9!t3thS!4Ezq3^P`k0GdGo? zQ_Si6!Wy#)lA52DTOMo3q==L5Ztk1n8w1z(P_PjM`Rv1`aAHmrd4lfKU5!E7_Cj@PG}Asq4S<(*k(IbnmF z>1q|HctOv+W9_?4GCBO7_Jh57@=!v4_=X$5?uYlAUdKWE@s?CC;}Cu6K!?)AW z^B1D)RHTns+bKzkjUPrdFCRYdd7GW;z*PK>yVF?bLNaD-NAEoxx}0}>m#)qg zhz!>|Yajl>ZpS|by*ympxIx!nYKvatfngz=0>}Q%U6kpR==5V)&&)Y2fQcCmRODd) z&OAHi8Ry~P;TeNk1gjQj-|?i~bwiLy{bL~PopRgFZLPFIlQ`(#)|)Thec_vpAI4` zJVeBC-%1~w&ja8rWGu5`nvvd8b(+e3S*>8X-u4(UesR+sLy?}`9GTOWnT zpEZwrwyP7@Oj=j^8*$0dUwAz7i>-1_q6cxlJZ)Xv%%}Cdd^j3^E2MP*ml!Sd~Ryd!uiAg#WvWng!g@~}>!xYMo@lm~2Q zv&lUax(T>D6~*zRIWsfyYuH#+JC}n74HRmBXT>(6#?N5~kmQtK6aQhUx8#zfpKgAH z*VVEG1q?^IU-zHusIa}jG5ncQ7ABUA^tq5&TV_* zbtBrMOefFj`{q=FMXe77mYQ}tQg(PYI6KRRo5&_hVv48Pyp=CFyZyYYq>)hE=lXo5l<@7_1`4CC|{S;v$~9Hcge zhN4QgI9QuM*#!M}gx?EZgw)?&#IzkFq}7>k`GW2Xv%T)8Fu7x|+c!w^9Y&zGVf;kp z)$0ZSe3W+b($G~gUe;V6SD}mXY=c38cTdE+m-145 zJ(wQM6qc_41>Z>|TC_;_q>Jp`X^wlMAf66>*+mCP|JpLlQ1qRjY!Z5&xVRzy)2yRJ zmi)a}YX7)*qz_wuIDgcCr!!O7Tv`my*n@nq=HZ0$TQP319W|R4l1%V9r6$*-0PF(kR$d~3T-+y3=A^9d(bm5 zN{3c#3=J2WH($lW8g~45+;agmWP?~ZvPZRH9L-za@s`wr;FeE4K_>k7pn-DEUJme^ z!H^Am(rDzr=0&4lf0wNzzu;)|JPNTl2LE*vqV>?O#}2^-R%zjmhl7^Z+#)ndg&3Zi z&g$e6dRdXX!l7_Iz=U1PEGYNcjYmez9uVszwKWw}x7T?*4c)t-^IeVJES402D zI!Nu#Ql-!}y_-2nb zhXHWb`^^BAfG2pt6$es~xFzO%b_`uN(tX=~@o^VSf>P~H#OD?mvm3xvwHsc2n5MtR zf^q5UJC1&RKj)So@ioqk$_0;>)5kUT!j#PUq~GVVNns%5QvW@!(E%`Xu#zEb9;Gt3 zFyF-79&{lN@IX(~pWS_}YF2y+J^iSCUBu>e+by)qwQJO89Ec!;l2dI^j|KnzG<1Dk zh{byUk6hm)nSc_Y7fHH3F?>h3)FH*IMPpqlNN>SN@2;kXB^?1`%@2)Yy^uwnm!`NH zioH<{CU@c1BxU9&?FS=^GJ{hC%fs5{-o*)Q=Q_rr7=FFW%z(X>@sq1{m#aNQwwRxT z?d=%U6nAIA!#S|ILY1hG}TJq znHy|_j#!*>QpU&uRpxPEWW#r@ihpNUNxDt$UYuA_9u?Wdtatbln(B5#Tu1GD?Tq}E zatLGjUQ|fIC|~}Bv?lA8;-vcT-*Uwv32IFgW1rF+E&#;?y z-RHn^jIdO%1D^B1cf7I|Ka56N_%IyQlHA^%i%8aFJj#I0K89 z`NmzlAUQk4XlBI@&qn!QrTGvuAA0O5=Ns%uOU^x#TP}%xD~xBHro5~Em=&$i>j*XX zbO2T<|BSNwo@TQPz#MjyeShwP+gr)5Exp@3{{CspV@oCU(@@sW@#0?d;Uxvkl(G6N z%gMPWS_Z3g?wl3DKi9~=J;IvKwsjR*oPd64fiF71A1^tvgYvIvCmdO&I}s7(^@6&{ znzbHL77YX*4pQB$s)$PXn=I$9#MUL}wfF)K1xBA@@=VJ?&}F z?yP@&3i6~eqx73UdR6`1nYf9HL;(E*inc<@rMYY-ae+2|ot$9<6sY-#N1Q1CA=3nV1=5F!uPfY=1Ush8Xc~ z6>jH-Vf3XXUQ!P`@*fx%`E3u?`+3OS_+A_~mq;ttD9o!!Qjn+MQ#{NdwiG_LcbhRd z%}%2Bm_tNN&3+ER8(6x;?66vIAA+0hwVl90po0#SpMD#|cQQ*Zaw1AN|6s5>z~V)D z+E-c+y}%F;cx}-0P}1|w?`CR+P$vxbJu{y<(sj-Fs*AeGVFZBFzg}~gOU~4(b~a?) zaBQsrO3spHm&huJ;j}h>IVL{#!MW^FFLLzwDt3bTkE^ycS*#Hoq$OLh1df$>BnW=Wu*sQ%eSM(+XdUfD7PC5_RA*7jTn6D{^wxvv6v4?Z2aTrOxszmsez3m z%8_Zb$9q%eH@1g8Sz?19?KXW=pS3HCQ`-Y@e-ps~8cU7pkPsqYm$>ZkGD6 zJl}hLk`wKrr~+d?)8-KS@Le+=+jRFiU$G2r7vduWj(*-Q$P04c!-2_pdSl(1yDhz-jgJ~t4ix!uy}+DO2$PQa3BX3ZAPjgR23-SvWMc*# zxZEMa*tve{H+Zo=&K4A8Jp96}i(T83|1=7ILqPIN#8N;7Kx59|lH1TU)x1vl_;Pab zFk6k^(1>i~9?^RzGwilkpE8>~T8W$U&58HVQ?PlCV7`gK3e`ft{Ys91u>cT(AZuFs ze#Ny{c#)Pr8tEdRf`~eS!D4XeHRXtV>4RaO3J8MEo+Y<4_9@hzG4``2dt`=c0ULlC zE20ndgZh#a4ZKPGeLmc`+BA4#C%>s{nCjjRr$}&(eam_`>1&z+EHxi|{KcG5P1$!1FE#%={xL9M7WP^{I>FZl5{-^J>S(`-k&j9Ec<*N|MOKq zqJ@}9%_R`%#$h;T2mVLIckD;WTArVk^%OJ$U!BodopnKLkWz7uvZ~xmXeTXnYe;!X z{LvSbx7g-UKr4PnnVTyKdscqM47^F+C6VIABw>mCI8rNwN^96PrIZ#aDFYFUd$Oxw zOv5Lon6L>})6%%->Z^k!NHj1>h5A;BsNtki@EgXYjQOai7dNxL&&gM8XYEaZlDVN^ zDFh~i6Nh}QXB#X^AEi(iEYY%ESh50wg`+crl0SPWr7B)6nWr9Wz<@5$m&){>7aRWj z5~;zL#Cj<;r3FK_l=H;NABe#dq46UTGqEOJc$0F0$F7eph^!BK7$Z1%m)t6xX%?jH zMv(V%IofRe*0==1VrudZ$T&kJ5H9B*i7DM4**KTV1CBuYIq}}cr;-UW#w+?CQve5m zh&Edo7PfFZ(A85Wj=M zV?FHADs9_~vE)dd{Lj0IL#bvKN!yr8gfy<^wAQS^v!MxdoLKd)zOum~y`^nFN=181 zX7QUJ?PwM=3$6yj-8)}ou$EGo4xwjMe-PnqV_jn#kbTclmjoHEiVrlNJACf$?9Ua7 zw15k5-`zO3!Tf&c;X>JaME@0z{RPc*ihNIxnqEP`b)lZS_($EvNH`L9O97es(xVqKg6((vx+MU};w!q5}W zUhvn{;XXJm=~Df0=R$dd*Zx8IyxT7;)%9MQSUz{9Q{S1YZV#>-wn|@AlC=UhaBcWQ zaYyjsWqu?bbaj8-==r(tbw)RAq+!b(!v`?7%j)&G48Npz;wUCCZx(P?fqtjp6F(GaOnBE|n(*LxKvV_ye#X?nuYt zfc>jc`{R=rbUh3F&$)V+1bN}Zy1~YF!LNUW?gT?<+|G$_-g&T=h3wgpVEpN{jrjPz{OE4n+axcGJ#Y<(b5I=$(E&KzJ74O z^z}SLP~h)3H33Bbw&o?NSznzU5|oOTR|BY@i(u#3+Vr$2a>xDTBc{mw?|hSUp3A0S z<1|bekCkGMwj(K5qp`IkHk9svWQgz2&=5cc$jx|50`0E5F1-l)T0`3@SRXXWGkGH* zlHn`49LKW?FnSuso)CA&Puh4dYe~=Fr@R=0_8Ttwx08_pf3AMOPMHlG@y4?axt;aZ zUQ{v$ILL55X$#>{@XiO=h=7k6#k}`v@6a%(Ki3jz7jMfy%v zcOb?|my8ROWvq;pKM~w+omh9@t31==Y)NWWVS}!;@kMV7s9GaBHt87$1(bIf?g)N{ zb-L!Ft-MeB(~d-wC_0pV7JOAfK^F0*+`zl~>fQO(z=yi8Mbj)n`-Np5|KXm-jf6X} z6N>diRvKDl6nAj|6LJo_CX|0gJ0D*t(=RawL3eL^1xM^i4NLLJqoR#*D-tN#kl z-tZ_mMojk$kUf`|6i7CjZ*arP5Mw{XjSz))^kCwd~98@LxyRHi=9 zOGbr%R5b@g_UjqVY(CQjsi0f;EHTC{>4*OM8vq|ndzp(w2+~AlElb~x0gMp?w9V88 zg90utW&X4WnlJ9=mI@%|^1Q<Aj>5qQhM0fZ+2Y*HBN(X<83e=`wE!qt$nE(D19tDJ5veG$p5pye z`jVb^|{YA{?GAlAyY+NCJ0 z=F#W=)T*iMj8jp0(o_Zr#J5-0Fvv?1MT{~n-uc=GL`)G^V$&u6$e0<#HvXPJ&=SjV zZ9wP4R93eX@1J$<>0TZc>uVnuH$P@C_>Xr_pE#bHtI^(P`=JKbLrD9KuZE)6D)a5t zI?_}%DuYJXQaXk`5JLNyj6H#A*ba^7PduO7l93LaiFtmu8b5N=TCw0cH>dn{PeZ zPv&n@IUe=^QDpe+?&@{I?TUBi`U)F#^{)M>{#_fAnCtrjvg!t=ap}A9Qd+*xnbV+w zx68`beNksxX+7)K;EX$Jo*ZVtnWfOfc%B|kV3z!PbiOIfj>_5n2|>`!-5JN2yAQbm z-`Uc+Pk@mPs*Hf{{w1Q1*WuCL4w~D*@MT-Ew&+p$;DvhLnS4ZEGDK)lw$55 zmy>f*46=oN$`EWsdQ_v4b!JrfCS+*Sb0VTa4Jh?*d2hFm?=vKjfZb>2a9oAv25S>y z+{;ygvbT7Gz3e#P9L|{Ml~ufp>-?D6J7-h)@o@1bal}vuS_2w_E}vt+t0Jj0?r%1z z{j;q~8PNK=kjOtwSg(70MptViD~6HM|KqSEUpuN;nZ5~DgIHNrrOCXh+R)u*{4^-p zyD#AFh}lxUExS6NrSm9M+dWe!L6+`RPZ=zhyfcc>*0YEnH$vsdHEn39w1CJEd-rt} zTO7QQzvkgxKCKWu*I~IgjFw?+Qw+a_ABY^x)2`8OSnZ!!*Sa`7Q{}P9Zn@j(D|`8J z#$NTvu#vfcuF@7Ixr)y-D`pEKv3kV(&Q{WGf*gfD%2I-8Y0fjN^8RhSt)j$$^Vwb$%~Ce_eEZSOI+>_{^wKHOgbs zE~)po?FM==$xbl;vTnNJ@vUY^`&@;_S#hAGpOFIh>?~TFR{|Da-n?Kl6OEv~jB!;R ziBJ4M0E{z5fOTpDtg-?_&OeJS4li4LMoTgqp&-kU@|~BqQl|BwnqAKl_5)2qf;Ktt z111c*d#$-fdJtU=4d7+nMi^h_S(4X33(qfZ3eR}$yLy7htgxeTf8=@y621^}Jr}}G zwennw*-~CVn>}@LG|%Aqff(Kdde3w19x~;lP{Rs-GeKV5Aq^`8?Mwmw6i({gsN~!r zi?A&vt~EUq(?7(Z}|EN>rmN%O!OTa(R1EA}J?fz8! zIedTx?j7iF%;nP;RpWLi$!<@btGBu1&^wWM0VD1N;eQ+362Cfdz1+&Y63F|I%r|n( z*tS!hNY|P~=NI>H z%Lhy64LdD||Con(v^6t)JfkyU)!?hikFq~!zb$t|F|*d|;Xz0W)j~X zE!3F~1=Wy@05*VXJRtZBrpTqYjB*q05cF;X{$|{ZdSi(%7ldyX>E*sseu}5wMGAy& zr3zLoC)Ir}tlPn}`ar{s!!54aHit+bUnL|1#DK*a=6xT-Gr#j%yi~`;NO8>(sXM?V ziDfr7=HDRy)Gc1>adVaU$1JkPNYU53Jz(TQyTqm`2C_}`q0YoOn`%*92?t4G(txov znA8UVNGE&?W|g(xNps=Z;Ta^GqPyjI7@Cadyj}>bG*aoe%N4Dod!!G$WZLrwiWT2{ z3R>45^OYW7s-9Zz>=*kfVC>nN%?OEv9G@Si-1Pp8)8$9zl${mv8XEJueKB6Xb@59U z;SPK6DldPkEIQN{p?+w#CWZY|2}9`7L2RorQ5^qJnL0iB86HevK_>>ge8}hIUBDT` zf2`vM>;rU>)Yzi(KA@|ccEjs^$CUb|=bb)V0rse4c(P>h={`Xi-C_aD4| zj%=eH-(o&e0aTp+W?vL1M&{@tY7OQwK`}Bi4s!R4W&Lh7Nt6L&{js?2e$NI;_EQb7 zUTUz}*#1o z+^TbPN|5_1lH5PD;jK5rTXA&=A~K#R7bW`aOaIWEkeNp!`#^ad_Dk>Pu{(H|<#eh8 z&8Z`1F20I;YQTImx1`o@vg1V2?kgP}M4QNt;}A=v<)f98W#4*WzfL6nFRqVz9NI=n zex0xD89<}=-CbHgT6et)!k~4=xXBl5zRzCG3JbZ?eJ? z?3~GzKi~1XV-l29eR+mg78!tv#`Ok`X34^H>8(eI-0XHfOM)t_3vv&%eMFnZBSwAXC|*n0oD;4zI;U^O8BZ_?c8Z9`rCxmz+ZRa zg!bI3i=P^nqV`9CP!}WbkldlpU3xJtvFO3bW!u>SMIuTk)wX(qxMy`H+93<^Z=4Dw z0Q{x8ii8kHA=Ng5s=)Y=0)0dYOwFd;=4$Ux5`ym3^#Rt~4aXlyKGmpdo_HKdszvj^ zbCR21pN#q_nkN19r}=m^Ay{0&8lH*+bjM}?Yqqfc-K%aUr%YWip16C`I%CfL_*6Bp>b$&2KpYZ4WoZ zT;iIChpC)N8n8T8nt#Q$2=kM)ABhzR?;^KB)=?3*Qk5ARne@~LQQLG+%00|y4UAdC z6>~uPe^U!2!E^z^JQrW9J;Jo>f2*w!d=qp|te;h#L(7FVJ2oPRA@NtA4+Pq+He(2< zTn=X1f%lUHqWaQg<85gs0mVE@@dR_FdXQsQ&Qxfs*)sDn3Hzfitp=>6N&WYCQ&bx; z<)D&ZlDU`}Mpdb%9y~J&ho-Tlw72^2xg?W&PfGzUNaawnG5ek(OpF2-3+b&a#q)-1 zw<%P#O6~+&t);Mx z88VDwfw;dn+0d8yL~!;#A?si8u`MM>yBU*1YGW@QV_@Gc!dV4vqNKP zNhkZXj=E2EJ9C(M4<6VLWdA~IXz7yjn`nn;Stez@G0bPy6zl|q4ZfxYwpy)075e=@#NB?4WIQ_kZ9EKq z)S(~q?u;cSv(1PzpfB0VW{VXPHk7KfS||aNc-Wg7pRc@8ttA;PmNRWTY)L=NSgo$J zFogwlfNCGR1LR&J=+~_>qp3J@J^%n-&*Gq74$wSKB#^kRU-}&arJYyvqD3`as`8gZyb|8`%O+qwS?cxvc=%Pvkv;*ogo`yBc^4JAQDO zAyHM5wJdCwkSc~#;;LT|+NHgz>Pqimr9^g%*r>|($5yLqIRwu>&Z^R_Gr}184Izp9 z?ZS14V`R%ueT%8L=R#ynHO;YbV3QPx-@E+222S-PhS^wMJ$q4of-*!d{`Ts#T$AR_ zU)CNRay{eU>Lgjm+^UW^q{_^ESby?qsf(XPjq=oNWbJUPJeuI2ewG}!Vbx&%c!~ya zH&@%LbtlcS$`yZNYUb6|6i?wi%w^hbyHDaN#$|4vtIkB!R>pygVm%SFq=)q)6V$9M8YdNBjbkji%%1z8pr3=6CP zQ%C(8&^IIPA`?|q;L`U-lZdo@gXc<~OVyGH_7jb}Zy!HL%6qaWXLgH;O~H6*xblu) zu--b*m?0xiog94ampj?z(8e8ej?x9CL%dM!!M)Z26AlYhOEJC{;nm-Yq@9<>@P{bA zgQXe@}v2YuiPF!R3 zrB;4La)41v+Sw!_u78Dmn|}CZXfr!?D?2t0uUH{AVX0f=B7~-CHFc#aB}9=UOZi)W zR9=-rwQGsc4ubwEc}rI`7na(E;`+kk^MXB3D6IO*SOU+cLfXq(>95wUH1BH_0~2KW zvC1~g^S5-r%NVjeCFT(9$k!wC-!WDkYCcpOe<0=5^j1hnBA^aG;7v)IA$gzLL=@hn zo_MS93%`5s(2|5c)z`9>q!qfxsDV?ka|;?0*! ztf|kcOnWlGUWk70Cp6ZgDUAv}+I$_Liz*+<0oG6UDARGYpXdmjP?ui5Qz!b~Y-)gx zImW`c4qu{Qx{fq2m}aQDJ0<0)>0W*2uYVT9v6-d?@fTbTC#YDnXN^6|#hyS>*Ho@@ zq#-Km82)`$_j%n{=<8*EnWr z+b=!D7xOoHXi9yoa?TG%c^wheSe}^_*RzjeADey@V$WJ{Re zp%#x6Z#eK;5q}@`PVSiO?_ZZAPrV#=NVvp7Dx$rl2T1Pj>Z6;DB9=u-sbn6JUd6gx zFm{uJ1}ldnrKP=QU3>3SoIRA+N8?gk)?TKQBwgP z*0OIB21C7NnK;*A085k2yBQAr7`cg_V%&Fl8>2}ijbBm^Sp3r8z@=9MMPJknKkpy#H(;j>s#ey3PR^Dp}0t_u?f9+|9YamX+ z54u}*r8KmbQy=kBB8z$ zjcXvst7?oohayCoBY#F<=Rk3TAcrj{{iQ%e%~64fKVE8m_W5LsPd@nF`+{wWBWA_+ zF-O{=tceRwSp~u-NeL!^lZ?in{_bzH!^Rz-)6vo@7wu5#zt5hSy!988RI_PCLKf#5 zpC@b;TQ3tyc1Fn2n{xP?@WF#|(7+w#WK8C5%-^eQ%1{f~8#__c0FE;5lkN5cWw1GG^4;$mhULjSy)pQdF#|}I3SCRDo>axRI$2% zD~I|zQR{x5F_x}$$M#XlD^O05fxk1~4rGU8B5>CQoOo3cdE{j-&Jn85b8|AtTe~AW zKx$Xtt6_Z0Gb4AV(8%oy3LJO6_0nacW_axl+BT%w>phf3VtG+j2SZ%hZzolEegH#V z*Q}#}y=*gIgas$X3dFH)oz2Kf6YW04Fv%+bTA1yoAXFir(8|-~Klv;uGZyORDli&W zaAlVS@JJzlf{WQxqkG0E zjCudQlC!@Js06D*;G~(5x%(@w8=?X@L(Nd`MemsS?cBdej--MbSHtrW}Oek&T2ql+;&-_GTj`1B;JD=36aF@-4U&W8PDWgvMs(t z&hzxMJX$iCP&{*X%q165(2 zNsBc{&?zM6nqhT^)l)=pR?&Izf&TScr);yw8lk>R(Atqhal#~FP9nbh885E|+n663 zR2))J^O)Aw4p?u_dQ+Q(%Idf-*lry19t6B-ynjObk}@K#Jeg8(z8~;I3B&IqqrGXk z4$~CapBwK!U_)M0_A}r9?95wdXZCnMd%lIFRY%;3Mnpd^Ww+V6*X9mU;UsB(f};vt zj(EWi0IV0d_PX?$X0Gsc{;&8h zm%a1f_cg{g55D{qzd1xIRHYSv&@`dH-Od-rkgR3?7pTjXMC&6&%VC8lcY`P>kxIPt zW%ut!^j)ivk=wGkg^`X)Qsk@0G4;pR-S=>bn9(x6DG?X48o%=TeV&UAk#W zr3aLze2wjg?c*{CjeY$6Md>mZC!#r=aJc~9+5|4wM$`JRej(X3QwmZSrE}kWD^e?3 zWK(qrcEEL4d;*@o;w1~BRjE$2Jxv_!CuPc+tD zxRp-sw6JS11<93p&F*z&#vFJySH$UMr4sYb4;DWFNuIA9oPJXi13wtTh1YPZ>J*5M<^85l@igh6*JsyM`=@AP;&i_?ntg(*yb;F%S zwJlm1Sco9iO=##E+wKiSj~gMa%U8ns;rAh`(n(>jiTc``$dxSgs{?9ua~6K-CG%mf zrJj*=L|i1B6GWv_wnXqeZdz=b$aV1glyH?O*3RJ~wAg{lrjmZQn0GRHTegIDgBm-< z&!gWszM%N9izXNxf8QT5EFM4w55;xjG*;PWOT+h%ORWKGUzP*Usf7Nkd3%&Xt+~nd z?@y?Ly`%R+nlxnMr6~sz%^I<+32MU`3{RV^8uKOw;w{PNuc@IY!=E9S*3$p@iEv4( z+$wQFp~~?s41bC@W)IVIL7*YwB+Ki#kTVJjda6fdNsytgy%k>Yjj*tXI@@TKQYYcn=0sX3FDr z#>?S8EaYah7foFnflxmAyioo7rhmrDzLBZ-B>P{1z3DNEu>xGUGdr!HX-y2f%qkrZ zvw^>p7v*nuum?Qo*huOjdOINr>5d`lPE`x&zV+J2m-iJiMAVAQW5fK~Afa-EZZ`s% zqqq=Q6bVTR;x{-${YC*~D%iT>L2zTP=4VTz0TOlrp9%6;{_SofgvLsjt=RWIG6FV6 z69LnmMz}EXY}a48@jq5t?!=A8oinciN^sw(lbrwt{>1f(GENac)X%e}t{%IDHw^~Y zXVhn69ih5Mq{$ExH&Nsv9}R)D0PX7vy5uXLZ(v-Rl1vKk zyfJ<1-a+cb5tG)P-wrkfdⅅ`SP#{u5b_6nAI*d^>EslD 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�MV<%l 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 literal 76128 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í?a}nFKOMpde#Zkn|F`jt{#lZ)Qp73} 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 JPDHLkV1kpoSd{<( delta 1943 zcmV;I2Wa@l5u^{0BYy{LNklc>tuhG(+Pyj~^9=B4EDMqMH zG!0?@X!v`_jFqG>yCE=)RxlMn+DPR%tqfk`aC{|Bu3XCI~(?&YI z!66xn6#&j4vvKoqv%iWGK&-Hx!0wCG2=J3V0yx2yNq-;{LVGK0#!ZAyiUr3G*krgt zF)m`>KpA@acEy_5>3Cpj!je;8;^u<}5#CaADPS-0Af>#3T}5F7t_|gWLE+dnG8<9; zA^h+DK|PUnbUm&#*1FWL8aRmqw4bwaq0!iu^eRGp{B3!LpfD6B=U~>+4LDbKRdb%| zLt%~kpMM%T1bGRW@bmO;RTl0Wj6Gu(BJ21T9IGnTma)1iVEYocNp_hw2f($qPgd5m z4I{9c%y|!YcP7gqZ(rn-sj=wSd=!+QV$x{|NgH6VI8hynl#AJ?B||4-F-daZ?cs^M z5gBAe1Y!Mo`z5T{V_^DT0h#K>kZW_m!_6HZ#DC93njt|^JvTQuEFV4v5yVq0JH5xQ zdtA%K7JE2*N)q{y3WaT}Vfz+@+GcCt*TWkdljb6Y%zL%S9yEp@2@6l`fU&trAfVtX z0Z!F&*uf17xw3wn(Y;FmwvWz6Y>&RqrE`Lp`^2ETPXOi?Z$!QEzPd)#c>$=J0=)ye z~i(jh$#Xq%IajmhA7&a4M=H>2z zr~JF&*=~_Y=-CewdJn_XfuW-9Q2X+AY7Vl0+Ju7@f60>1l`S!+m_H;L%j2f;u1gFx z_v-O_@m3tWeu4QQj3yH<*WcjNzVZ^h^V?Vah{_u^2R(=v5Q0XMpO2l7#V2+lzkl?& zb0H<5&0R2vFQ z1X=-P-a6~NnXZd$TQVkcFyC<#u@APoPOxrB)K}pSJ?7eiF&zsRd z0jb3BW&W_v#?#QX7hhKlt51H1-K8g(oe~q71@&=&eJE;O3NnyHlv7$;X@6;!!^K-w z_$+xIUfKUKLdhInOos9Jf)(JJTeM5-NHSLvq_y>8$Z_4!8q*B%*mUkko`&jb*M;M} zo7p>`rZ{2BaSRc51F^~bm9O_Xr< zMmbJaUvy|9zL&vfTUfGbrGEjJ;{X{v_<8?c!gRb?u*zoP=?ZPpk*#R51VdJMSZG;s zg&clLXti4mIiVdM9*x|XNqC<;c`J;jrdD*hu`lto(!6Y6j(M!rdV4K~oFO-MGRo^~ zu=|2|^fqJQ3p|Z;Fs6Wt&1>y;g=NrE-~Q3qIS3{TrVVEfJCwcl+bU}qDcAl z)NDgU6%Pl{ZL$?fX^0_4acS{Rew3~nm5!wY6jsub)8QnZH~tZBTBVHI`sS!{F^VwVF{GjA5qM+QeXF$KKuiG_v3`ML0DI<7* z1RM0=v8uCzO4lXAtw;M8!7ieLXz~E7P|64z33qzxdWY*W=zj{@2hmfa6wdYo=o#A- zG7d8w-^oKi|E~<&N!lr8%A|LN&B(HJHbcof`3?Zu`7HCTs!dT_96+~iGGRV--O>Lr zL7~kbCQOxe!iuy(dg}U-`^${!dL6SOQvr9s|5GfRHoVu89t(8-YfNte^hT!w^cFyG dJn;(nA8#w)R}jQpmzw|p002ovPDHLkV1h<CFBundleInfoDictionaryVersion 6.0 CFBundleName - My Server Status + AdGuard Home Manager CFBundlePackageType APPL CFBundleShortVersionString From de8a7818c390b6f8e6e51a9aa60f43ab915e49d5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 2 May 2023 13:42:01 +0200 Subject: [PATCH 062/676] Fixed split view --- lib/l10n/app_en.arb | 4 ++- lib/l10n/app_es.arb | 4 ++- lib/providers/app_config_provider.dart | 6 ++-- lib/screens/clients/clients.dart | 14 +++++++- lib/screens/settings/settings.dart | 39 +++++++++++++-------- lib/widgets/bottom_nav_bar.dart | 2 +- lib/widgets/custom_settings_tile.dart | 48 +++++++++----------------- lib/widgets/navigation_rail.dart | 2 +- 8 files changed, 66 insertions(+), 53 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 8017577..ea3738d 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -607,5 +607,7 @@ "safeSearchSettings": "Safe search settings", "loadingSafeSearchSettings": "Loading safe search settings...", "safeSearchSettingsNotLoaded": "Error when loading safe search settings.", - "loadingLogsSettings": "Loading logs settings..." + "loadingLogsSettings": "Loading logs settings...", + "selectOptionLeftColumn": "Select an option of the left column", + "selectClientLeftColumn": "Select a client of the left column" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 61aa7de..6bc3ded 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -607,5 +607,7 @@ "safeSearchSettings": "Configuración de búsqueda segura", "loadingSafeSearchSettings": "Cargando configuración de búsqueda segura...", "safeSearchSettingsNotLoaded": "Error al cargar la configuración de búsqueda segura.", - "loadingLogsSettings": "Cargando configuración de registros..." + "loadingLogsSettings": "Cargando configuración de registros...", + "selectOptionLeftColumn": "Selecciona una opción de la columna de la izquierda", + "selectClientLeftColumn": "Selecciona un cliente de la columna de la izquierda" } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 0dc8ac3..caa7dff 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -166,9 +166,11 @@ class AppConfigProvider with ChangeNotifier { notifyListeners(); } - void setSelectedSettingsScreen(int? screen) { + void setSelectedSettingsScreen({required int? screen, bool? notify}) { _selectedSettingsScreen = screen; - notifyListeners(); + if (notify == true) { + notifyListeners(); + } } Future setOverrideSslCheck(bool status) async { diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 91d7dd1..bdaf046 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -172,8 +172,20 @@ class _ClientsWidgetState extends State with TickerProviderStateM if (!(Platform.isAndroid || Platform.isIOS)) { if (width > 900) { return SplitView.material( - breakpoint: 900, hideDivider: true, + placeholder: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + AppLocalizations.of(context)!.selectClientLeftColumn, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), + ), child: ClientsDesktopView( serversProvider: serversProvider, appConfigProvider: appConfigProvider, diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 74f8a40..fe93473 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -29,6 +29,7 @@ import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; + class Settings extends StatelessWidget { const Settings({Key? key}) : super(key: key); @@ -36,11 +37,23 @@ class Settings extends StatelessWidget { Widget build(BuildContext context) { final width = MediaQuery.of(context).size.width; - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - return const SplitView.material( - breakpoint: 900, + if (width > 900) { + return SplitView.material( hideDivider: true, - child: SettingsWidget(), + placeholder: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + AppLocalizations.of(context)!.selectOptionLeftColumn, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), + ), + child: const SettingsWidget(), ); } else { @@ -58,6 +71,10 @@ class SettingsWidget extends StatelessWidget { final width = MediaQuery.of(context).size.width; + if (width <= 900 && appConfigProvider.selectedSettingsScreen != null) { + appConfigProvider.setSelectedSettingsScreen(screen: null); + } + Widget settingsTile({ required String title, required String subtitle, @@ -75,7 +92,7 @@ class SettingsWidget extends StatelessWidget { thisItem: thisItem, selectedItem: appConfigProvider.selectedSettingsScreen, onTap: () { - appConfigProvider.setSelectedSettingsScreen(thisItem); + appConfigProvider.setSelectedSettingsScreen(screen: thisItem, notify: true); SplitView.of(context).setSecondary(screenToNavigate); }, ); @@ -87,15 +104,9 @@ class SettingsWidget extends StatelessWidget { icon: icon, trailing: trailing, onTap: () { - appConfigProvider.setSelectedSettingsScreen(thisItem); - if (!(Platform.isIOS || Platform.isAndroid)) { - SplitView.of(context).setSecondary(screenToNavigate); - } - else { - Navigator.of(context).push( - MaterialPageRoute(builder: (context) => screenToNavigate) - ); - } + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => screenToNavigate) + ); }, ); } diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index b5511c1..36abbbe 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -91,7 +91,7 @@ class BottomNavBar extends StatelessWidget { } // Reset settings selected screen if (value != screens.length-1) { - appConfigProvider.setSelectedSettingsScreen(null); + appConfigProvider.setSelectedSettingsScreen(screen: null); } appConfigProvider.setSelectedScreen(value); }, diff --git a/lib/widgets/custom_settings_tile.dart b/lib/widgets/custom_settings_tile.dart index 276d517..554f13b 100644 --- a/lib/widgets/custom_settings_tile.dart +++ b/lib/widgets/custom_settings_tile.dart @@ -26,8 +26,6 @@ class CustomSettingsTile extends StatelessWidget { @override Widget build(BuildContext context) { - final width = MediaQuery.of(context).size.width; - Widget tileBody = Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -80,41 +78,27 @@ class CustomSettingsTile extends StatelessWidget { ], ); - if (width < 700) { - return Material( + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Material( color: Colors.transparent, + borderRadius: BorderRadius.circular(28), child: InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: tileBody, - ) - ), - ); - } - else { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 12), - child: Material( - color: Colors.transparent, borderRadius: BorderRadius.circular(28), - child: InkWell( - borderRadius: BorderRadius.circular(28), - onTap: onTap, - child: Container( - width: double.maxFinite, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(28), - color: thisItem == selectedItem - ? Theme.of(context).colorScheme.primaryContainer - : null - ), - child: tileBody + onTap: onTap, + child: Container( + width: double.maxFinite, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: thisItem == selectedItem + ? Theme.of(context).colorScheme.primaryContainer + : null ), + child: tileBody ), ), - ); - } + ), + ); } } \ No newline at end of file diff --git a/lib/widgets/navigation_rail.dart b/lib/widgets/navigation_rail.dart index 4837e0f..6dc028f 100644 --- a/lib/widgets/navigation_rail.dart +++ b/lib/widgets/navigation_rail.dart @@ -68,7 +68,7 @@ class SideNavigationRail extends StatelessWidget { } // Reset settings selected screen if (value != screens.length-1) { - appConfigProvider.setSelectedSettingsScreen(null); + appConfigProvider.setSelectedSettingsScreen(screen: null); } appConfigProvider.setSelectedScreen(value); }, From 2cb50611414cdec06841831bf4292846c32497e5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 2 May 2023 13:47:20 +0200 Subject: [PATCH 063/676] Fix split view logs --- lib/screens/logs/logs.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index a900964..430b6da 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -341,7 +341,7 @@ class _LogsWidgetState extends State { length: logsProvider.logsData!.data.length, isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index], onLogTap: (log) { - if (width <= 700) { + if (width <= 1100) { Navigator.push(context, MaterialPageRoute( builder: (context) => LogDetailsScreen(log: log) )); From 9b2f5f7aba0f894a17dbdd8b4aee3419a853fca5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 2 May 2023 14:01:49 +0200 Subject: [PATCH 064/676] Added log details modal clients --- lib/screens/clients/logs_list_client.dart | 12 ++- lib/screens/logs/log_details_screen.dart | 109 +++++++++++++++++----- lib/screens/logs/log_tile.dart | 6 +- lib/screens/logs/logs.dart | 10 +- 4 files changed, 108 insertions(+), 29 deletions(-) diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/logs_list_client.dart index ef910fd..91b8424 100644 --- a/lib/screens/clients/logs_list_client.dart +++ b/lib/screens/clients/logs_list_client.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; +import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -163,9 +164,14 @@ class _LogsListClientState extends State { log: logsData!.data[index], index: index, length: logsData!.data.length, - onLogTap: (log) { - - } + useAlwaysNormalTile: true, + onLogTap: (log) => showDialog( + context: context, + builder: (context) => LogDetailsScreen( + log: log, + dialog: true + ) + ) ); } } diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index a6960a1..5ee50b7 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -19,10 +19,12 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; class LogDetailsScreen extends StatelessWidget { final Log log; + final bool dialog; const LogDetailsScreen({ Key? key, - required this.log + required this.log, + required this.dialog }) : super(key: key); @override @@ -105,25 +107,8 @@ class LogDetailsScreen extends StatelessWidget { } } - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.logDetails), - actions: [ - IconButton( - onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), - icon: Icon( - getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? Icons.check_circle_rounded - : Icons.block - ), - tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? AppLocalizations.of(context)!.unblockDomain - : AppLocalizations.of(context)!.blockDomain, - ), - const SizedBox(width: 10) - ], - ), - body: ListView( + Widget content() { + return ListView( children: [ SectionLabel(label: AppLocalizations.of(context)!.status), LogListTile( @@ -247,7 +232,87 @@ class LogDetailsScreen extends StatelessWidget { )).toList() ] ], - ), - ); + ); + } + + if (dialog) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded) + ), + const SizedBox(width: 16), + Text( + AppLocalizations.of(context)!.logDetails, + style: const TextStyle( + fontSize: 22 + ), + ), + ], + ), + Row( + children: [ + IconButton( + onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), + icon: Icon( + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? Icons.check_circle_rounded + : Icons.block + ), + tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? AppLocalizations.of(context)!.unblockDomain + : AppLocalizations.of(context)!.blockDomain, + ), + ], + ) + ], + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: content(), + ), + ) + ], + ), + ), + ); + } + else { + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.logDetails), + actions: [ + IconButton( + onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), + icon: Icon( + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? Icons.check_circle_rounded + : Icons.block + ), + tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? AppLocalizations.of(context)!.unblockDomain + : AppLocalizations.of(context)!.blockDomain, + ), + const SizedBox(width: 10) + ], + ), + body: content() + ); + } } } \ No newline at end of file diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 776bd0c..a4c082f 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -20,6 +20,7 @@ class LogTile extends StatelessWidget { final int index; final bool? isLogSelected; final void Function(Log) onLogTap; + final bool? useAlwaysNormalTile; const LogTile({ Key? key, @@ -27,7 +28,8 @@ class LogTile extends StatelessWidget { required this.length, required this.index, this.isLogSelected, - required this.onLogTap + required this.onLogTap, + this.useAlwaysNormalTile }) : super(key: key); @override @@ -100,7 +102,7 @@ class LogTile extends StatelessWidget { ); } - if (width > 1100) { + if (width > 1100 && !(useAlwaysNormalTile == true)) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: Material( diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 430b6da..45494e6 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -343,7 +343,10 @@ class _LogsWidgetState extends State { onLogTap: (log) { if (width <= 1100) { Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen(log: log) + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + ) )); } setState(() => selectedLog = log); @@ -604,7 +607,10 @@ class _LogsWidgetState extends State { Expanded( flex: 2, child: selectedLog != null - ? LogDetailsScreen(log: selectedLog!) + ? LogDetailsScreen( + log: selectedLog!, + dialog: false, + ) : const SizedBox() ) ], From 2afbaf1f9373c9d4882e511fb13043cbe4fb6752 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 2 May 2023 18:03:16 +0200 Subject: [PATCH 065/676] Adapted modals filters --- lib/screens/filters/add_list_modal.dart | 208 ++++---- lib/screens/filters/check_host_modal.dart | 236 ++++---- lib/screens/filters/fab.dart | 35 +- lib/screens/filters/filters.dart | 91 +++- lib/screens/filters/list_details_screen.dart | 36 +- .../filters/update_interval_lists_modal.dart | 504 +++++++++--------- 6 files changed, 616 insertions(+), 494 deletions(-) diff --git a/lib/screens/filters/add_list_modal.dart b/lib/screens/filters/add_list_modal.dart index 196cda1..fceebf9 100644 --- a/lib/screens/filters/add_list_modal.dart +++ b/lib/screens/filters/add_list_modal.dart @@ -10,6 +10,7 @@ class AddListModal extends StatefulWidget { final Filter? list; final void Function({required String name, required String url, required String type})? onConfirm; final void Function({required Filter list, required String type})? onEdit; + final bool dialog; const AddListModal({ Key? key, @@ -17,6 +18,7 @@ class AddListModal extends StatefulWidget { this.list, this.onConfirm, this.onEdit, + required this.dialog }) : super(key: key); @override @@ -68,51 +70,49 @@ class _AddListModalState extends State { @override Widget build(BuildContext context) { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - height: Platform.isIOS ? 386 : 370, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor - ), - child: Column( - children: [ - Expanded( - child: ListView( - physics: (Platform.isIOS ? 426 : 410) < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - widget.type == 'whitelist' - ? Icons.verified_user_rounded - : Icons.gpp_bad_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + widget.type == 'whitelist' + ? Icons.verified_user_rounded + : Icons.gpp_bad_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + const SizedBox(height: 16), + Text( + widget.list != null + ? widget.type == 'whitelist' + ? AppLocalizations.of(context)!.editWhitelist + : AppLocalizations.of(context)!.editBlacklist + : widget.type == 'whitelist' + ? AppLocalizations.of(context)!.addWhitelist + : AppLocalizations.of(context)!.addBlacklist, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], ), - const SizedBox(height: 16), - Text( - widget.list != null - ? widget.type == 'whitelist' - ? AppLocalizations.of(context)!.editWhitelist - : AppLocalizations.of(context)!.editBlacklist - : widget.type == 'whitelist' - ? AppLocalizations.of(context)!.addWhitelist - : AppLocalizations.of(context)!.addBlacklist, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: TextFormField( @@ -129,7 +129,7 @@ class _AddListModalState extends State { ), ), ), - const SizedBox(height: 30), + Container(height: 30), Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: TextFormField( @@ -151,54 +151,80 @@ class _AddListModalState extends State { ], ), ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ), - const SizedBox(width: 20), - TextButton( - onPressed: () { - Navigator.pop(context); - if (widget.list != null) { - final Filter newList = Filter( - url: urlController.text, - name: nameController.text, - lastUpdated: widget.list!.lastUpdated, - id: widget.list!.id, - rulesCount: widget.list!.rulesCount, - enabled: widget.list!.enabled - ); - widget.onEdit!( - list: newList, - type: widget.type - ); - } - else { - widget.onConfirm!( - name: nameController.text, - url: urlController.text, - type: widget.type - ); - } - }, - child: Text( - widget.list != null - ? AppLocalizations.of(context)!.save - : AppLocalizations.of(context)!.confirm - ) - ), - ], - ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + const SizedBox(width: 20), + TextButton( + onPressed: () { + Navigator.pop(context); + if (widget.list != null) { + final Filter newList = Filter( + url: urlController.text, + name: nameController.text, + lastUpdated: widget.list!.lastUpdated, + id: widget.list!.id, + rulesCount: widget.list!.rulesCount, + enabled: widget.list!.enabled + ); + widget.onEdit!( + list: newList, + type: widget.type + ); + } + else { + widget.onConfirm!( + name: nameController.text, + url: urlController.text, + type: widget.type + ); + } + }, + child: Text( + widget.list != null + ? AppLocalizations.of(context)!.save + : AppLocalizations.of(context)!.confirm + ) + ), + ], ), - if (Platform.isIOS) const SizedBox(height: 16) - ], + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: content() ), - ), - ); + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: content() + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/filters/check_host_modal.dart b/lib/screens/filters/check_host_modal.dart index 18f1f0f..6678ddb 100644 --- a/lib/screens/filters/check_host_modal.dart +++ b/lib/screens/filters/check_host_modal.dart @@ -10,7 +10,12 @@ import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class CheckHostModal extends StatefulWidget { - const CheckHostModal({Key? key}) : super(key: key); + final bool dialog; + + const CheckHostModal({ + Key? key, + required this.dialog + }) : super(key: key); @override State createState() => _CheckHostModalState(); @@ -117,126 +122,141 @@ class _CheckHostModalState extends State { } } - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - height: 330, - width: double.maxFinite, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28), - ), - color: Theme.of(context).dialogBackgroundColor - ), - child: Center( - child: Column( - children: [ - Expanded( - child: ListView( - physics: 350 < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.checkHostFiltered, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: domainController, - onChanged: validateDomain, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), ), - errorText: domainError, - labelText: AppLocalizations.of(context)!.domain, + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.checkHostFiltered, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: domainController, + onChanged: validateDomain, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: domainError, + labelText: AppLocalizations.of(context)!.domain, + ), + ), + ), + if (resultWidget != null) Padding( + padding: const EdgeInsets.all(24), + child: resultWidget, + ), + if (resultWidget == null) Padding( + padding: const EdgeInsets.all(24), + child: Center( + child: Text( + AppLocalizations.of(context)!.insertDomain, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 16, ), ), ), - if (resultWidget != null) Padding( - padding: const EdgeInsets.only( - top: 20, - left: 20, - right: 20 - ), - child: resultWidget, + ), + ], + ), + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only( + bottom: 24, + right: 24 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close), ), - if (resultWidget == null) Padding( - padding: const EdgeInsets.only( - top: 20, - left: 20, - right: 20 - ), - child: Center( - child: Text( - AppLocalizations.of(context)!.insertDomain, - style: const TextStyle( - fontSize: 16, - ), + const SizedBox(width: 20), + TextButton( + onPressed: domainController.text != '' && domainError == null + ? () => checkHost() + : null, + child: Text( + AppLocalizations.of(context)!.check, + style: TextStyle( + color: domainController.text != '' && domainError == null + ? Theme.of(context).colorScheme.primary + : Colors.grey ), ), ), ], ), - ), - Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Padding( - padding: const EdgeInsets.only( - bottom: 24, - right: 24 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close), - ), - const SizedBox(width: 20), - TextButton( - onPressed: domainController.text != '' && domainError == null - ? () => checkHost() - : null, - child: Text( - AppLocalizations.of(context)!.check, - style: TextStyle( - color: domainController.text != '' && domainError == null - ? Theme.of(context).colorScheme.primary - : Colors.grey - ), - ), - ), - ], - ), - ) - ], ) ], + ) + ], + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 ), + child: content() ), - ), - ); + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + width: double.maxFinite, + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28), + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: content() + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/filters/fab.dart b/lib/screens/filters/fab.dart index 2a5d036..7a06e35 100644 --- a/lib/screens/filters/fab.dart +++ b/lib/screens/filters/fab.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -28,6 +30,8 @@ class FiltersFab extends StatelessWidget { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void confirmAddRule(String rule) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingRule); @@ -154,15 +158,28 @@ class FiltersFab extends StatelessWidget { } void openAddWhitelistBlacklist() { - showModalBottomSheet( - context: context, - builder: (ctx) => AddListModal( - type: type, - onConfirm: confirmAddList, - ), - isScrollControlled: true, - backgroundColor: Colors.transparent - ); + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (ctx) => AddListModal( + type: type, + onConfirm: confirmAddList, + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + builder: (ctx) => AddListModal( + type: type, + onConfirm: confirmAddList, + dialog: false, + ), + isScrollControlled: true, + backgroundColor: Colors.transparent + ); + } } return FloatingActionButton( diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index f985f48..81d4f96 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -89,6 +91,8 @@ class _FiltersWidgetState extends State with TickerProviderStateM final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void fetchUpdateLists() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingLists); @@ -139,12 +143,24 @@ class _FiltersWidgetState extends State with TickerProviderStateM void showCheckHostModal() { Future.delayed(const Duration(seconds: 0), () { - showModalBottomSheet( - context: context, - builder: (context) => const CheckHostModal(), - backgroundColor: Colors.transparent, - isScrollControlled: true, - ); + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => const CheckHostModal( + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => const CheckHostModal( + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + ); + } }); } @@ -279,15 +295,28 @@ class _FiltersWidgetState extends State with TickerProviderStateM ), IconButton( onPressed: () { - showModalBottomSheet( - context: context, - builder: (context) => UpdateIntervalListsModal( - interval: serversProvider.filtering.data!.interval, - onChange: setUpdateFrequency - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ); + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => UpdateIntervalListsModal( + interval: serversProvider.filtering.data!.interval, + onChange: setUpdateFrequency, + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => UpdateIntervalListsModal( + interval: serversProvider.filtering.data!.interval, + onChange: setUpdateFrequency, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ); + } }, icon: const Icon(Icons.update_rounded) ), @@ -329,20 +358,38 @@ class _FiltersWidgetState extends State with TickerProviderStateM ] : [], bottom: TabBar( controller: tabController, - isScrollable: false, + isScrollable: true, unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, tabs: [ Tab( - icon: const Icon(Icons.verified_user_rounded), - text: AppLocalizations.of(context)!.whitelists, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.verified_user_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.whitelists,) + ], + ), ), Tab( - icon: const Icon(Icons.gpp_bad_rounded), - text: AppLocalizations.of(context)!.blacklist, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.gpp_bad_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.blacklists) + ], + ), ), Tab( - icon: const Icon(Icons.shield_rounded), - text: AppLocalizations.of(context)!.customRules, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.shield_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.customRules) + ], + ), ), ] ) diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 7d8cf53..3001004 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -68,6 +68,8 @@ class _ListDetailsScreenState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void enableDisableList(Filter list, bool newStatus) async { ProcessModal processModal = ProcessModal(context: context); processModal.open( @@ -222,16 +224,30 @@ class _ListDetailsScreenState extends State { actions: [ IconButton( onPressed: () => { - showModalBottomSheet( - context: context, - builder: (ctx) => AddListModal( - list: widget.list, - type: widget.type, - onEdit: confirmEditList - ), - isScrollControlled: true, - backgroundColor: Colors.transparent - ) + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (ctx) => AddListModal( + list: widget.list, + type: widget.type, + onEdit: confirmEditList, + dialog: true, + ), + ) + } + else { + showModalBottomSheet( + context: context, + builder: (ctx) => AddListModal( + list: widget.list, + type: widget.type, + onEdit: confirmEditList, + dialog: false, + ), + isScrollControlled: true, + backgroundColor: Colors.transparent + ) + } }, icon: const Icon(Icons.edit), tooltip: AppLocalizations.of(context)!.edit, diff --git a/lib/screens/filters/update_interval_lists_modal.dart b/lib/screens/filters/update_interval_lists_modal.dart index 1779bf9..c168793 100644 --- a/lib/screens/filters/update_interval_lists_modal.dart +++ b/lib/screens/filters/update_interval_lists_modal.dart @@ -9,11 +9,13 @@ import 'package:adguard_home_manager/widgets/option_box.dart'; class UpdateIntervalListsModal extends StatefulWidget { final int interval; final void Function(int) onChange; + final bool dialog; const UpdateIntervalListsModal({ Key? key, required this.interval, required this.onChange, + required this.dialog }) : super(key: key); @override @@ -37,272 +39,266 @@ class _UpdateIntervalListsModalState extends State { @override Widget build(BuildContext context) { - final MediaQueryData mediaQueryData = MediaQuery.of(context); + final MediaQueryData mediaQueryData = MediaQuery.of(context); - return Padding( - padding: mediaQueryData.viewInsets, - child: Container( - height: Platform.isIOS ? 406 : 390, - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - child: ListView( - physics: (Platform.isIOS ? 426 : 410) < MediaQuery.of(context).size.height - ? const NeverScrollableScrollPhysics() - : null, + Widget content() { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.update_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 16 - ), - width: double.maxFinite, - child: Text( - AppLocalizations.of(context)!.updateFrequency, - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - SizedBox( - width: double.maxFinite, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Container( - width: (mediaQueryData.size.width-70)/2, - margin: const EdgeInsets.only( - top: 10, - right: 5, - bottom: 5 - ), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 0, - onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 0 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.never), - ), - ), - ), - ), - Container( - width: (mediaQueryData.size.width-70)/2, - margin: const EdgeInsets.only( - top: 10, - left: 5, - bottom: 5 - ), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 1, - onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 1 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.hour1), - ), - ), - ), - ), - ], + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.update_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Container( - width: (mediaQueryData.size.width-70)/2, - margin: const EdgeInsets.only( - top: 5, - right: 5, - bottom: 5 - ), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 12, - onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 12 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.hours12), - ), - ), - ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 16 + ), + child: Text( + AppLocalizations.of(context)!.updateFrequency, + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface ), - Container( - width: (mediaQueryData.size.width-70)/2, - margin: const EdgeInsets.only( - top: 5, - left: 5, - bottom: 5 - ), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 24, - onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 24 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.hours24), - ), - ), - ), - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Container( - width: (mediaQueryData.size.width-70)/2, - margin: const EdgeInsets.only( - top: 5, - right: 5, - bottom: 10 - ), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 72, - onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 72 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.days3), - ), - ), - ), - ), - Container( - width: (mediaQueryData.size.width-70)/2, - margin: const EdgeInsets.only( - top: 5, - left: 5, - bottom: 10 - ), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 168, - onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 168 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.days7), - ), - ), - ), - ), - ], + ), ), ], - ), + ) + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Wrap( + runSpacing: 16, + children: [ + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(right: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 0, + onTap: _updateRadioValue, + child: Center( + child: AnimatedDefaultTextStyle( + duration: const Duration(milliseconds: 250), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: selectedOption == 0 + ? Theme.of(context).colorScheme.onInverseSurface + : Theme.of(context).colorScheme.onSurface + ), + child: Text(AppLocalizations.of(context)!.never), + ), + ), + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(left: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 1, + onTap: _updateRadioValue, + child: Center( + child: AnimatedDefaultTextStyle( + duration: const Duration(milliseconds: 250), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: selectedOption == 1 + ? Theme.of(context).colorScheme.onInverseSurface + : Theme.of(context).colorScheme.onSurface + ), + child: Text(AppLocalizations.of(context)!.hour1), + ), + ), + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(right: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 12, + onTap: _updateRadioValue, + child: Center( + child: AnimatedDefaultTextStyle( + duration: const Duration(milliseconds: 250), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: selectedOption == 12 + ? Theme.of(context).colorScheme.onInverseSurface + : Theme.of(context).colorScheme.onSurface + ), + child: Text(AppLocalizations.of(context)!.hours12), + ), + ), + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(left: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 24, + onTap: _updateRadioValue, + child: Center( + child: AnimatedDefaultTextStyle( + duration: const Duration(milliseconds: 250), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: selectedOption == 24 + ? Theme.of(context).colorScheme.onInverseSurface + : Theme.of(context).colorScheme.onSurface + ), + child: Text(AppLocalizations.of(context)!.hours24), + ), + ), + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(right: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 72, + onTap: _updateRadioValue, + child: Center( + child: AnimatedDefaultTextStyle( + duration: const Duration(milliseconds: 250), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: selectedOption == 72 + ? Theme.of(context).colorScheme.onInverseSurface + : Theme.of(context).colorScheme.onSurface + ), + child: Text(AppLocalizations.of(context)!.days3), + ), + ), + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(left: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 168, + onTap: _updateRadioValue, + child: Center( + child: AnimatedDefaultTextStyle( + duration: const Duration(milliseconds: 250), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: selectedOption == 168 + ? Theme.of(context).colorScheme.onInverseSurface + : Theme.of(context).colorScheme.onSurface + ), + child: Text(AppLocalizations.of(context)!.days7), + ), + ), + ), + ), + ), + ], ), - ), + ) ], ), ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel), - ), - const SizedBox(width: 20), - TextButton( - onPressed: selectedOption != null - ? () { - Navigator.pop(context); - widget.onChange(selectedOption!); - } - : null, - style: ButtonStyle( - overlayColor: MaterialStateProperty.all( - Theme.of(context).colorScheme.primary.withOpacity(0.1) - ), - foregroundColor: MaterialStateProperty.all( - selectedOption != null - ? Theme.of(context).colorScheme.primary - : Colors.grey, - ), - ), - child: Text(AppLocalizations.of(context)!.confirm), - ), - ], - ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel), + ), + const SizedBox(width: 20), + TextButton( + onPressed: selectedOption != null + ? () { + Navigator.pop(context); + widget.onChange(selectedOption!); + } + : null, + style: ButtonStyle( + overlayColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.primary.withOpacity(0.1) + ), + foregroundColor: MaterialStateProperty.all( + selectedOption != null + ? Theme.of(context).colorScheme.primary + : Colors.grey, + ), + ), + child: Text(AppLocalizations.of(context)!.confirm), + ), + ], ), - if (Platform.isIOS) const SizedBox(height: 16) - ], + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: content() ), - ), - ); + ); + } + else { + return Padding( + padding: mediaQueryData.viewInsets, + child: Container( + height: Platform.isIOS ? 406 : 390, + decoration: BoxDecoration( + color: Theme.of(context).dialogBackgroundColor, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + ), + child: content() + ), + ); + } } } \ No newline at end of file From eb4462d4d01fefa10e86a19d2ef75e7396ecb4af Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 3 May 2023 16:30:20 +0200 Subject: [PATCH 066/676] Optimized filters screen --- lib/functions/open_url.dart | 45 +- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- .../filters/{fab.dart => add_button.dart} | 36 +- lib/screens/filters/add_custom_rule.dart | 571 ++++++++++-------- .../filters/blocked_services_screen.dart | 98 ++- lib/screens/filters/custom_rules_list.dart | 68 +-- lib/screens/filters/filter_list_tile.dart | 60 -- lib/screens/filters/filters.dart | 422 ++++++------- lib/screens/filters/filters_list.dart | 24 +- lib/screens/filters/filters_tabs_view.dart | 143 +++++ .../filters/filters_triple_column.dart | 311 ++++++++++ lib/screens/filters/list_details_screen.dart | 332 ++++++---- lib/screens/settings/settings.dart | 2 +- lib/widgets/custom_list_tile.dart | 2 +- linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile.lock | 6 + pubspec.lock | 64 ++ pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 23 files changed, 1445 insertions(+), 759 deletions(-) rename lib/screens/filters/{fab.dart => add_button.dart} (88%) delete mode 100644 lib/screens/filters/filter_list_tile.dart create mode 100644 lib/screens/filters/filters_tabs_view.dart create mode 100644 lib/screens/filters/filters_triple_column.dart diff --git a/lib/functions/open_url.dart b/lib/functions/open_url.dart index b4d52d5..b435e47 100644 --- a/lib/functions/open_url.dart +++ b/lib/functions/open_url.dart @@ -1,17 +1,30 @@ -import 'package:flutter_web_browser/flutter_web_browser.dart'; +import 'dart:io'; -void openUrl(String url) { - FlutterWebBrowser.openWebPage( - url: url, - customTabsOptions: const CustomTabsOptions( - instantAppsEnabled: true, - showTitle: true, - urlBarHidingEnabled: false, - ), - safariVCOptions: const SafariViewControllerOptions( - barCollapsingEnabled: true, - dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, - modalPresentationCapturesStatusBarAppearance: true, - ) - ); -} \ No newline at end of file +import 'package:flutter_web_browser/flutter_web_browser.dart'; +import 'package:url_launcher/url_launcher.dart'; + +void openUrl(String url) async { + if (Platform.isAndroid || Platform.isIOS) { + FlutterWebBrowser.openWebPage( + url: url, + customTabsOptions: const CustomTabsOptions( + instantAppsEnabled: true, + showTitle: true, + urlBarHidingEnabled: false, + ), + safariVCOptions: const SafariViewControllerOptions( + barCollapsingEnabled: true, + dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, + modalPresentationCapturesStatusBarAppearance: true, + ) + ); + } + else { + final uri = Uri.parse(url); + if (await canLaunchUrl(uri)) { + await launchUrl(uri); + } else { + throw 'Could not launch $url'; + } + } +} \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ea3738d..c08bb8e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -609,5 +609,7 @@ "safeSearchSettingsNotLoaded": "Error when loading safe search settings.", "loadingLogsSettings": "Loading logs settings...", "selectOptionLeftColumn": "Select an option of the left column", - "selectClientLeftColumn": "Select a client of the left column" + "selectClientLeftColumn": "Select a client of the left column", + "disableList": "Disable list", + "enableList": "Enable list" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 6bc3ded..e4bf4b6 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -609,5 +609,7 @@ "safeSearchSettingsNotLoaded": "Error al cargar la configuración de búsqueda segura.", "loadingLogsSettings": "Cargando configuración de registros...", "selectOptionLeftColumn": "Selecciona una opción de la columna de la izquierda", - "selectClientLeftColumn": "Selecciona un cliente de la columna de la izquierda" + "selectClientLeftColumn": "Selecciona un cliente de la columna de la izquierda", + "disableList": "Deshabilitar lista", + "enableList": "Habilitar lista" } \ No newline at end of file diff --git a/lib/screens/filters/fab.dart b/lib/screens/filters/add_button.dart similarity index 88% rename from lib/screens/filters/fab.dart rename to lib/screens/filters/add_button.dart index 7a06e35..f2ba43e 100644 --- a/lib/screens/filters/fab.dart +++ b/lib/screens/filters/add_button.dart @@ -17,12 +17,14 @@ import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class FiltersFab extends StatelessWidget { +class AddFiltersButton extends StatelessWidget { final String type; + final Widget Function(void Function()) widget; - const FiltersFab({ + const AddFiltersButton({ Key? key, required this.type, + required this.widget }) : super(key: key); @override @@ -68,14 +70,27 @@ class FiltersFab extends StatelessWidget { } void openAddCustomRule() { - Navigator.of(context).push( - MaterialPageRoute( - fullscreenDialog: true, + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, builder: (context) => AddCustomRule( - onConfirm: confirmAddRule + onConfirm: confirmAddRule, + dialog: true, ), - ) - ); + barrierDismissible: false + ); + } + else { + Navigator.of(context).push( + MaterialPageRoute( + fullscreenDialog: true, + builder: (context) => AddCustomRule( + onConfirm: confirmAddRule, + dialog: false, + ), + ) + ); + } } void confirmAddList({required String name, required String url, required String type}) async { @@ -182,11 +197,10 @@ class FiltersFab extends StatelessWidget { } } - return FloatingActionButton( - onPressed: type == 'blacklist' || type == 'whitelist' + return widget( + type == 'blacklist' || type == 'whitelist' ? () => openAddWhitelistBlacklist() : () => openAddCustomRule(), - child: const Icon(Icons.add), ); } } \ No newline at end of file diff --git a/lib/screens/filters/add_custom_rule.dart b/lib/screens/filters/add_custom_rule.dart index 3f1e1f2..dfb5753 100644 --- a/lib/screens/filters/add_custom_rule.dart +++ b/lib/screens/filters/add_custom_rule.dart @@ -1,17 +1,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_web_browser/flutter_web_browser.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/constants/urls.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; class AddCustomRule extends StatefulWidget { final void Function(String) onConfirm; + final bool dialog; const AddCustomRule({ Key? key, - required this.onConfirm + required this.onConfirm, + required this.dialog }) : super(key: key); @override @@ -72,293 +72,338 @@ class _AddCustomRuleState extends State { return rule; } - - void openDocsPage() { - FlutterWebBrowser.openWebPage( - url: Urls.customRuleDocs, - customTabsOptions: const CustomTabsOptions( - instantAppsEnabled: true, - showTitle: true, - urlBarHidingEnabled: false, - ), - safariVCOptions: const SafariViewControllerOptions( - barCollapsingEnabled: true, - dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, - modalPresentationCapturesStatusBarAppearance: true, - ) - ); - } @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.addCustomRule), - actions: [ - IconButton( - onPressed: checkValidValues() == true - ? () { - Navigator.pop(context); - widget.onConfirm(buildRule()); - } - : null, - icon: const Icon(Icons.check) - ), - const SizedBox(width: 10) - ], - ), - body: ListView( - children: [ - const SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5 - ), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(30), - border: Border.all( - color: Theme.of(context).colorScheme.primary - ) - ), - child: Text( - buildRule(), - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.w500 - ), + + List content() { + return [ + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5 + ), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(30), + border: Border.all( + color: Theme.of(context).colorScheme.primary ) ), - ], - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: domainController, - onChanged: (value) => setState(() => {}), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + child: Text( + buildRule(), + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w500 ), - errorText: domainError, - labelText: AppLocalizations.of(context)!.domain, + ) + ), + ], + ), + Container(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: domainController, + onChanged: (value) => setState(() => {}), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) ), + errorText: domainError, + labelText: AppLocalizations.of(context)!.domain, ), ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: SegmentedButton( - segments: [ - ButtonSegment( - value: BlockingPresets.block, - label: Text(AppLocalizations.of(context)!.block) - ), - ButtonSegment( - value: BlockingPresets.unblock, - label: Text(AppLocalizations.of(context)!.unblock) - ), - ButtonSegment( - value: BlockingPresets.custom, - label: Text(AppLocalizations.of(context)!.custom) - ), - ], - selected: {preset}, - onSelectionChanged: (value) => setState(() => preset = value.first), - ), + ), + Container(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: SegmentedButton( + segments: [ + ButtonSegment( + value: BlockingPresets.block, + label: Text(AppLocalizations.of(context)!.block) + ), + ButtonSegment( + value: BlockingPresets.unblock, + label: Text(AppLocalizations.of(context)!.unblock) + ), + ButtonSegment( + value: BlockingPresets.custom, + label: Text(AppLocalizations.of(context)!.custom) + ), + ], + selected: {preset}, + onSelectionChanged: (value) => setState(() => preset = value.first), ), - const SizedBox(height: 20), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => setState(() => addImportant = !addImportant), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 28), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only(left: 10), - child: Text( - AppLocalizations.of(context)!.addImportant, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), + ), + Container(height: 20), + Material( + color: Colors.transparent, + child: InkWell( + onTap: () => setState(() => addImportant = !addImportant), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 28), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 10), + child: Text( + AppLocalizations.of(context)!.addImportant, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface ), ), - Switch( - value: addImportant, - onChanged: (value) => setState(() => addImportant = value), - ) - ], - ), + ), + Switch( + value: addImportant, + onChanged: (value) => setState(() => addImportant = value), + ) + ], ), ), ), - const SizedBox(height: 20), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Card( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( + ), + Container(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Card( + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + Row( + children: [ + Icon( + Icons.info, + color: Theme.of(context).colorScheme.onSurface + ), + const SizedBox(width: 20), + Text( + AppLocalizations.of(context)!.examples, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + const SizedBox(height: 20), + SizedBox( + width: double.maxFinite, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "||example.org^", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 5), + Text( + AppLocalizations.of(context)!.example1, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 20), + Text( + "@@||example.org^", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 5), + Text( + AppLocalizations.of(context)!.example2, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 20), + Text( + "! Here goes a comment", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + Text( + "# Also a comment", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 5), + Text( + AppLocalizations.of(context)!.example3, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 20), + Text( + "/REGEX/", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 5), + Text( + AppLocalizations.of(context)!.example4, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.primary + ), + ), + ], + ), + ) + ], + ), + ), + ), + ), + Container(height: 20), + Material( + color: Colors.transparent, + child: InkWell( + onTap: () => openUrl(Urls.customRuleDocs), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 10), + child: Text( + AppLocalizations.of(context)!.moreInformation, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 15), + child: Icon( + Icons.open_in_new, + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + ), + ), + ), + Container(height: 20) + ]; + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ - Icon( - Icons.info, - color: Theme.of(context).colorScheme.onSurface + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, ), - const SizedBox(width: 20), + const SizedBox(width: 8), Text( - AppLocalizations.of(context)!.examples, - style: TextStyle( - fontSize: 18, - color: Theme.of(context).colorScheme.onSurface + AppLocalizations.of(context)!.addCustomRule, + style: const TextStyle( + fontSize: 22 ), - ) + ), ], ), - const SizedBox(height: 20), - SizedBox( - width: double.maxFinite, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "||example.org^", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 5), - Text( - AppLocalizations.of(context)!.example1, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 20), - Text( - "@@||example.org^", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 5), - Text( - AppLocalizations.of(context)!.example2, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 20), - Text( - "! Here goes a comment", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - Text( - "# Also a comment", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 5), - Text( - AppLocalizations.of(context)!.example3, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 20), - Text( - "/REGEX/", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 5), - Text( - AppLocalizations.of(context)!.example4, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.primary - ), - ), - ], - ), + IconButton( + onPressed: checkValidValues() == true + ? () { + Navigator.pop(context); + widget.onConfirm(buildRule()); + } + : null, + icon: const Icon(Icons.check) ) ], ), ), - ), - ), - const SizedBox(height: 20), - Material( - color: Colors.transparent, - child: InkWell( - onTap: openDocsPage, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 10), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only(left: 10), - child: Text( - AppLocalizations.of(context)!.moreInformation, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 15), - child: Icon( - Icons.open_in_new, - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], + Flexible( + child: SingleChildScrollView( + child: Wrap( + alignment: WrapAlignment.center, + children: content(), + ), ), - ), - ), + ) + ], ), - const SizedBox(height: 20) - ], - ), - ); + ), + ); + } + else { + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.addCustomRule), + actions: [ + IconButton( + onPressed: checkValidValues() == true + ? () { + Navigator.pop(context); + widget.onConfirm(buildRule()); + } + : null, + icon: const Icon(Icons.check) + ), + const SizedBox(width: 10) + ], + ), + body: ListView( + children: content(), + ) + ); + } } } \ No newline at end of file diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/blocked_services_screen.dart index fba09d2..2c0912e 100644 --- a/lib/screens/filters/blocked_services_screen.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -12,7 +12,12 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class BlockedServicesScreen extends StatelessWidget { - const BlockedServicesScreen({Key? key}) : super(key: key); + final bool dialog; + + const BlockedServicesScreen({ + Key? key, + required this.dialog + }) : super(key: key); @override Widget build(BuildContext context) { @@ -21,7 +26,8 @@ class BlockedServicesScreen extends StatelessWidget { return BlockedServicesScreenWidget( serversProvider: serversProvider, - appConfigProvider: appConfigProvider + appConfigProvider: appConfigProvider, + dialog: dialog, ); } } @@ -29,11 +35,13 @@ class BlockedServicesScreen extends StatelessWidget { class BlockedServicesScreenWidget extends StatefulWidget { final ServersProvider serversProvider; final AppConfigProvider appConfigProvider; + final bool dialog; const BlockedServicesScreenWidget({ Key? key, required this.serversProvider, required this.appConfigProvider, + required this.dialog }) : super(key: key); @override @@ -209,24 +217,74 @@ class _BlockedServicesScreenStateWidget extends State Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, + ), + const SizedBox(width: 8), + Text( + AppLocalizations.of(context)!.blockedServices, + style: const TextStyle( + fontSize: 22 + ), + ) + ], + ), + IconButton( + onPressed: updateBlockedServices, + icon: const Icon( + Icons.save_rounded + ), + tooltip: AppLocalizations.of(context)!.save, + ), + ], + ), + ), + Expanded( + child: body() + ), + ], + ) + ), + ); + } + else { + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.blockedServices), + actions: [ + IconButton( + onPressed: updateBlockedServices, + icon: const Icon( + Icons.save_rounded + ), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 10) + ], + ), + body: RefreshIndicator( + onRefresh: loadBlockedServices, + child: body() + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 41b1d0f..5a96716 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -2,33 +2,27 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/filters/fab.dart'; -import 'package:adguard_home_manager/screens/filters/remove_custom_rule_modal.dart'; +import 'package:adguard_home_manager/screens/filters/add_button.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/models/filtering.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; class CustomRulesList extends StatefulWidget { final LoadStatus loadStatus; final ScrollController scrollController; final List data; final Future Function() fetchData; + final void Function(String) onRemoveCustomRule; const CustomRulesList({ Key? key, required this.loadStatus, required this.scrollController, required this.data, - required this.fetchData + required this.fetchData, + required this.onRemoveCustomRule }) : super(key: key); @override @@ -61,52 +55,6 @@ class _CustomRulesListState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - void removeCustomRule(String rule) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.deletingRule); - - final List newRules = serversProvider.filtering.data!.userRules.where((r) => r != rule).toList(); - - final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules); - - processModal.close(); - - if (result['result'] == 'success') { - FilteringData filteringData = serversProvider.filtering.data!; - filteringData.userRules = newRules; - serversProvider.setFilteringData(filteringData); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.ruleRemovedSuccessfully, - color: Colors.green - ); - } - else { - appConfigProvider.addLog(result['log']); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.ruleNotRemoved, - color: Colors.red - ); - } - } - - void openRemoveCustomRuleModal(String rule) { - showDialog( - context: context, - builder: (context) => RemoveCustomRule( - onConfirm: () => removeCustomRule(rule), - ) - ); - } - bool checkIfComment(String value) { final regex = RegExp(r'^(!|#).*$'); if (regex.hasMatch(value)) { @@ -184,7 +132,7 @@ class _CustomRulesListState extends State { ), subtitle: generateSubtitle(widget.data[index]), trailing: IconButton( - onPressed: () => openRemoveCustomRuleModal(widget.data[index]), + onPressed: () => widget.onRemoveCustomRule(widget.data[index]), icon: const Icon(Icons.delete) ), ), @@ -239,8 +187,12 @@ class _CustomRulesListState extends State { ), loadStatus: widget.loadStatus, onRefresh: widget.fetchData, - fab: const FiltersFab( + fab: AddFiltersButton( type: 'custom_rule', + widget: (fn) => FloatingActionButton( + onPressed: fn, + child: const Icon(Icons.add), + ), ), fabVisible: isVisible, ); diff --git a/lib/screens/filters/filter_list_tile.dart b/lib/screens/filters/filter_list_tile.dart deleted file mode 100644 index 1782d62..0000000 --- a/lib/screens/filters/filter_list_tile.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:flutter/material.dart'; - -class FilterListTile extends StatelessWidget { - final IconData icon; - final String title; - final String subtitle; - final Color? color; - final bool? bold; - - const FilterListTile({ - Key? key, - required this.icon, - required this.title, - required this.subtitle, - this.color, - this.bold, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Icon( - icon, - size: 24, - color: Theme.of(context).listTileTheme.iconColor, - ), - const SizedBox(width: 16), - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 3), - Text( - subtitle, - style: TextStyle( - fontSize: 14, - color: color ?? Theme.of(context).listTileTheme.textColor, - fontWeight: bold == true ? FontWeight.bold : FontWeight.w400 - ), - ), - ], - ), - ) - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 81d4f96..607d791 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -6,15 +6,18 @@ 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/filters/filters_list.dart'; import 'package:adguard_home_manager/screens/filters/check_host_modal.dart'; -import 'package:adguard_home_manager/screens/filters/custom_rules_list.dart'; +import 'package:adguard_home_manager/screens/filters/filters_tabs_view.dart'; +import 'package:adguard_home_manager/screens/filters/filters_triple_column.dart'; +import 'package:adguard_home_manager/screens/filters/list_details_screen.dart'; +import 'package:adguard_home_manager/screens/filters/remove_custom_rule_modal.dart'; import 'package:adguard_home_manager/screens/filters/blocked_services_screen.dart'; import 'package:adguard_home_manager/screens/filters/update_interval_lists_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/clients.dart'; @@ -49,10 +52,7 @@ class FiltersWidget extends StatefulWidget { State createState() => _FiltersWidgetState(); } -class _FiltersWidgetState extends State with TickerProviderStateMixin { - late TabController tabController; - final ScrollController scrollController = ScrollController(); - +class _FiltersWidgetState extends State { Future fetchFilters() async { widget.serversProvider.setFilteringLoadStatus(LoadStatus.loading, false); @@ -70,20 +70,14 @@ class _FiltersWidgetState extends State with TickerProviderStateM } } + List generateClientsList(List clients, List ips) { + return clients.where((client) => ips.contains(client.ip)).toList(); + } + @override void initState() { fetchFilters(); super.initState(); - tabController = TabController( - initialIndex: 0, - length: 3, - vsync: this, - ); - tabController.addListener(() => widget.appConfigProvider.setSelectedFiltersTab(tabController.index)); - } - - List generateClientsList(List clients, List ips) { - return clients.where((client) => ips.contains(client.ip)).toList(); } @override @@ -232,200 +226,222 @@ class _FiltersWidgetState extends State with TickerProviderStateM void openBlockedServicesModal() { Future.delayed(const Duration(seconds: 0), () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const BlockedServicesScreen(), - ) - ); + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => const BlockedServicesScreen( + dialog: true, + ), + barrierDismissible: false + ); + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const BlockedServicesScreen( + dialog: false, + ), + ) + ); + } }); } - return DefaultTabController( - length: 3, - child: NestedScrollView( - controller: scrollController, - headerSliverBuilder: ((context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - title: Text(AppLocalizations.of(context)!.filters), - pinned: true, - floating: true, - forceElevated: innerBoxIsScrolled, - centerTitle: false, - actions: serversProvider.filtering.loadStatus == LoadStatus.loaded ? [ - IconButton( - onPressed: enableDisableFiltering, - tooltip: serversProvider.filtering.data!.enabled == true - ? AppLocalizations.of(context)!.disableFiltering - : AppLocalizations.of(context)!.enableFiltering, - icon: Stack( - children: [ - const Icon(Icons.power_settings_new_rounded), - Positioned( - bottom: 0, - right: 0, - child: Stack( - children: [ - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - color: Colors.white - ), - child: Icon( - serversProvider.filtering.data!.enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - size: 12, - color: serversProvider.filtering.data!.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ), - ), - ], - ), - ) - ], - ) + void removeCustomRule(String rule) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.deletingRule); + + final List newRules = serversProvider.filtering.data!.userRules.where((r) => r != rule).toList(); + + final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules); + + processModal.close(); + + if (result['result'] == 'success') { + FilteringData filteringData = serversProvider.filtering.data!; + filteringData.userRules = newRules; + serversProvider.setFilteringData(filteringData); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.ruleRemovedSuccessfully, + color: Colors.green + ); + } + else { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.ruleNotRemoved, + color: Colors.red + ); + } + } + + void openRemoveCustomRuleModal(String rule) { + showDialog( + context: context, + builder: (context) => RemoveCustomRule( + onConfirm: () => removeCustomRule(rule), + ) + ); + } + + void openListDetails(Filter filter, String type) { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => ListDetailsScreen( + list: filter, + type: type, + dialog: true, + ), + barrierDismissible: false + ); + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ListDetailsScreen( + list: filter, + type: type, + dialog: false, + ) + ) + ); + } + } + + List actions() { + if (serversProvider.filtering.loadStatus == LoadStatus.loaded) { + return [ + IconButton( + onPressed: enableDisableFiltering, + tooltip: serversProvider.filtering.data!.enabled == true + ? AppLocalizations.of(context)!.disableFiltering + : AppLocalizations.of(context)!.enableFiltering, + icon: Stack( + children: [ + const Icon(Icons.power_settings_new_rounded), + Positioned( + bottom: 0, + right: 0, + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Colors.white + ), + child: Icon( + serversProvider.filtering.data!.enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + size: 12, + color: serversProvider.filtering.data!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + ), + ], ), - IconButton( - onPressed: () { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => UpdateIntervalListsModal( - interval: serversProvider.filtering.data!.interval, - onChange: setUpdateFrequency, - dialog: true, - ), - ); - } - else { - showModalBottomSheet( - context: context, - builder: (context) => UpdateIntervalListsModal( - interval: serversProvider.filtering.data!.interval, - onChange: setUpdateFrequency, - dialog: false, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ); - } - }, - icon: const Icon(Icons.update_rounded) + ) + ], + ) + ), + IconButton( + onPressed: () { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => UpdateIntervalListsModal( + interval: serversProvider.filtering.data!.interval, + onChange: setUpdateFrequency, + dialog: true, ), - PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - onTap: fetchUpdateLists, - child: Row( - children: [ - const Icon(Icons.sync_rounded), - const SizedBox(width: 10), - Text(AppLocalizations.of(context)!.updateLists) - ], - ) - ), - PopupMenuItem( - onTap: openBlockedServicesModal, - child: Row( - children: [ - const Icon(Icons.block), - const SizedBox(width: 10), - Text(AppLocalizations.of(context)!.blockedServices) - ], - ) - ), - PopupMenuItem( - onTap: showCheckHostModal, - child: Row( - children: [ - const Icon(Icons.shield_rounded), - const SizedBox(width: 10), - Text(AppLocalizations.of(context)!.checkHostFiltered) - ], - ) - ), - ] + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => UpdateIntervalListsModal( + interval: serversProvider.filtering.data!.interval, + onChange: setUpdateFrequency, + dialog: false, ), - const SizedBox(width: 5), - ] : [], - bottom: TabBar( - controller: tabController, - isScrollable: true, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.verified_user_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.whitelists,) - ], - ), - ), - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.gpp_bad_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.blacklists) - ], - ), - ), - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.shield_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.customRules) - ], - ), - ), - ] + backgroundColor: Colors.transparent, + isScrollControlled: true + ); + } + }, + icon: const Icon(Icons.update_rounded), + tooltip: AppLocalizations.of(context)!.updateFrequency, + ), + PopupMenuButton( + itemBuilder: (context) => [ + PopupMenuItem( + onTap: fetchUpdateLists, + child: Row( + children: [ + const Icon(Icons.sync_rounded), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.updateLists) + ], ) ), - ) - ]; - }), - body: TabBarView( - controller: tabController, - children: [ - FiltersList( - loadStatus: serversProvider.filtering.loadStatus, - scrollController: scrollController, - type: 'whitelist', - data: serversProvider.filtering.loadStatus == LoadStatus.loaded - ? serversProvider.filtering.data!.whitelistFilters : [], - fetchData: fetchFilters, - ), - FiltersList( - loadStatus: serversProvider.filtering.loadStatus, - scrollController: scrollController, - type: 'blacklist', - data: serversProvider.filtering.loadStatus == LoadStatus.loaded - ? serversProvider.filtering.data!.filters : [], - fetchData: fetchFilters, - ), - CustomRulesList( - loadStatus: serversProvider.filtering.loadStatus, - scrollController: scrollController, - data: serversProvider.filtering.loadStatus == LoadStatus.loaded - ? serversProvider.filtering.data!.userRules : [], - fetchData: fetchFilters, - ), - ] - ) - ) - ); + PopupMenuItem( + onTap: openBlockedServicesModal, + child: Row( + children: [ + const Icon(Icons.block), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.blockedServices) + ], + ) + ), + PopupMenuItem( + onTap: showCheckHostModal, + child: Row( + children: [ + const Icon(Icons.shield_rounded), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.checkHostFiltered) + ], + ) + ), + ] + ), + const SizedBox(width: 5), + ]; + } + else { + return []; + } + } + + if (width > 1200) { + return FiltersTripleColumn( + onRemoveCustomRule: openRemoveCustomRuleModal, + onOpenDetailsModal: openListDetails, + actions: actions(), + refreshData: fetchFilters, + ); + } + else { + return FiltersTabsView( + appConfigProvider: appConfigProvider, + fetchFilters: fetchFilters, + actions: actions(), + onRemoveCustomRule: openRemoveCustomRuleModal, + onOpenDetailsModal: openListDetails, + ); + } } } \ No newline at end of file diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index effe42d..be4ff75 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -7,8 +7,7 @@ import 'package:provider/provider.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/filters/fab.dart'; -import 'package:adguard_home_manager/screens/filters/list_details_screen.dart'; +import 'package:adguard_home_manager/screens/filters/add_button.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; @@ -23,6 +22,7 @@ class FiltersList extends StatefulWidget { final List data; final Future Function() fetchData; final String type; + final void Function(Filter, String) onOpenDetailsScreen; const FiltersList({ Key? key, @@ -31,6 +31,7 @@ class FiltersList extends StatefulWidget { required this.data, required this.fetchData, required this.type, + required this.onOpenDetailsScreen }) : super(key: key); @override @@ -64,17 +65,6 @@ class _FiltersListState extends State { @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - - void openDetailsModal(Filter filter) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ListDetailsScreen( - list: filter, - type: widget.type, - ) - ) - ); - } return CustomTabContentList( loadingGenerator: () => SizedBox( @@ -112,7 +102,7 @@ class _FiltersListState extends State { ? Colors.grey : Colors.red ), - onTap: () => openDetailsModal(widget.data[index]), + onTap: () => widget.onOpenDetailsScreen(widget.data[index], widget.type), ), noData: Container( width: double.maxFinite, @@ -166,8 +156,12 @@ class _FiltersListState extends State { ), loadStatus: widget.loadStatus, onRefresh: widget.fetchData, - fab: FiltersFab( + fab: AddFiltersButton( type: widget.type, + widget: (fn) => FloatingActionButton( + onPressed: fn, + child: const Icon(Icons.add), + ), ), fabVisible: isVisible, ); diff --git a/lib/screens/filters/filters_tabs_view.dart b/lib/screens/filters/filters_tabs_view.dart new file mode 100644 index 0000000..17f74a9 --- /dev/null +++ b/lib/screens/filters/filters_tabs_view.dart @@ -0,0 +1,143 @@ +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/filters/custom_rules_list.dart'; +import 'package:adguard_home_manager/screens/filters/filters_list.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class FiltersTabsView extends StatefulWidget { + final AppConfigProvider appConfigProvider; + final Future Function() fetchFilters; + final List actions; + final void Function(String) onRemoveCustomRule; + final void Function(Filter, String) onOpenDetailsModal; + + const FiltersTabsView({ + Key? key, + required this.appConfigProvider, + required this.fetchFilters, + required this.actions, + required this.onOpenDetailsModal, + required this.onRemoveCustomRule + }) : super(key: key); + + @override + State createState() => _FiltersTabsViewState(); +} + +class _FiltersTabsViewState extends State with TickerProviderStateMixin { + late TabController tabController; + final ScrollController scrollController = ScrollController(); + + @override + void initState() { + widget.fetchFilters(); + super.initState(); + tabController = TabController( + initialIndex: 0, + length: 3, + vsync: this, + ); + tabController.addListener(() => widget.appConfigProvider.setSelectedFiltersTab(tabController.index)); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + + return DefaultTabController( + length: 3, + child: NestedScrollView( + controller: scrollController, + headerSliverBuilder: ((context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + title: Text(AppLocalizations.of(context)!.filters), + pinned: true, + floating: true, + forceElevated: innerBoxIsScrolled, + centerTitle: false, + actions: widget.actions, + bottom: TabBar( + controller: tabController, + isScrollable: true, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.verified_user_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.whitelists,) + ], + ), + ), + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.gpp_bad_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.blacklists) + ], + ), + ), + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.shield_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.customRules) + ], + ), + ), + ] + ) + ), + ) + ]; + }), + body: TabBarView( + controller: tabController, + children: [ + FiltersList( + loadStatus: serversProvider.filtering.loadStatus, + scrollController: scrollController, + type: 'whitelist', + data: serversProvider.filtering.loadStatus == LoadStatus.loaded + ? serversProvider.filtering.data!.whitelistFilters : [], + fetchData: widget.fetchFilters, + onOpenDetailsScreen: widget.onOpenDetailsModal, + ), + FiltersList( + loadStatus: serversProvider.filtering.loadStatus, + scrollController: scrollController, + type: 'blacklist', + data: serversProvider.filtering.loadStatus == LoadStatus.loaded + ? serversProvider.filtering.data!.filters : [], + fetchData: widget.fetchFilters, + onOpenDetailsScreen: widget.onOpenDetailsModal, + ), + CustomRulesList( + loadStatus: serversProvider.filtering.loadStatus, + scrollController: scrollController, + data: serversProvider.filtering.loadStatus == LoadStatus.loaded + ? serversProvider.filtering.data!.userRules : [], + fetchData: widget.fetchFilters, + onRemoveCustomRule: widget.onRemoveCustomRule, + ), + ] + ) + ) + ); + } +} \ No newline at end of file diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart new file mode 100644 index 0000000..3e82fc5 --- /dev/null +++ b/lib/screens/filters/filters_triple_column.dart @@ -0,0 +1,311 @@ +import 'dart:io'; + +import 'package:adguard_home_manager/screens/filters/add_button.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; + +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class FiltersTripleColumn extends StatelessWidget { + final void Function(String) onRemoveCustomRule; + final void Function(Filter, String) onOpenDetailsModal; + final List actions; + final Future Function() refreshData; + + const FiltersTripleColumn({ + Key? key, + required this.onRemoveCustomRule, + required this.onOpenDetailsModal, + required this.actions, + required this.refreshData + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + bool checkIfComment(String value) { + final regex = RegExp(r'^(!|#).*$'); + if (regex.hasMatch(value)) { + return true; + } + else { + return false; + } + } + + Widget? generateSubtitle(String rule) { + final allowRegex = RegExp(r'^@@.*$'); + final blockRegex = RegExp(r'^\|\|.*$'); + final commentRegex = RegExp(r'^(#|!).*$'); + + if (allowRegex.hasMatch(rule)) { + return Text( + AppLocalizations.of(context)!.allowed, + style: const TextStyle( + color: Colors.green + ), + ); + } + else if (blockRegex.hasMatch(rule)) { + return Text( + AppLocalizations.of(context)!.blocked, + style: const TextStyle( + color: Colors.red + ), + ); + } + else if (commentRegex.hasMatch(rule)) { + return Text( + AppLocalizations.of(context)!.comment, + style: const TextStyle( + color: Colors.grey + ), + ); + } + else { + return null; + } + } + + Widget content() { + switch (serversProvider.filtering.loadStatus) { + case LoadStatus.loading: + return Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingFilters, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ], + ); + + case LoadStatus.loaded: + return Row( + children: [ + Expanded( + flex: 1, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.whitelists, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500 + ), + ), + AddFiltersButton( + type: 'whitelist', + widget: (fn) => IconButton( + onPressed: fn, + icon: const Icon(Icons.add_rounded) + ) + ) + ], + ), + ), + Expanded( + child: ListView.builder( + itemCount: serversProvider.filtering.data!.whitelistFilters.length, + itemBuilder: (context, index) => CustomListTile( + title: serversProvider.filtering.data!.whitelistFilters[index].name, + subtitle: "${intFormat(serversProvider.filtering.data!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + serversProvider.filtering.data!.whitelistFilters[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: serversProvider.filtering.data!.whitelistFilters[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.whitelistFilters[index], 'whitelist'), + ), + ), + ) + ], + ), + ), + Expanded( + flex: 1, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.blacklists, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500 + ), + ), + AddFiltersButton( + type: 'blacklist', + widget: (fn) => IconButton( + onPressed: fn, + icon: const Icon(Icons.add_rounded) + ) + ) + ], + ), + ), + Expanded( + child: ListView.builder( + itemCount: serversProvider.filtering.data!.filters.length, + itemBuilder: (context, index) => CustomListTile( + title: serversProvider.filtering.data!.filters[index].name, + subtitle: "${intFormat(serversProvider.filtering.data!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + serversProvider.filtering.data!.filters[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: serversProvider.filtering.data!.filters[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.filters[index], 'blacklist'), + ), + ), + ) + ], + ), + ), + Expanded( + flex: 1, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.customRules, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500 + ), + ), + AddFiltersButton( + type: '', + widget: (fn) => IconButton( + onPressed: fn, + icon: const Icon(Icons.add_rounded) + ) + ) + ], + ), + ), + Expanded( + child: ListView.builder( + itemCount: serversProvider.filtering.data!.userRules.length, + itemBuilder: (context, index) => ListTile( + title: Text( + serversProvider.filtering.data!.userRules[index], + style: TextStyle( + color: checkIfComment(serversProvider.filtering.data!.userRules[index]) == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.6) + : Theme.of(context).colorScheme.onSurface, + fontWeight: FontWeight.normal, + ), + ), + subtitle: generateSubtitle(serversProvider.filtering.data!.userRules[index]), + trailing: IconButton( + onPressed: () => onRemoveCustomRule(serversProvider.filtering.data!.userRules[index]), + icon: const Icon(Icons.delete) + ), + ), + ), + ) + ], + ), + ), + ], + ); + + case LoadStatus.error: + return SizedBox.expand( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.filtersNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ], + ), + ); + + default: + return const SizedBox(); + } + } + + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.filters), + actions: [ + IconButton( + onPressed: refreshData, + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ), + ...actions + ], + ), + body: content(), + ); + } +} \ No newline at end of file diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 3001004..92ae4e0 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -7,9 +7,9 @@ import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/filters/filter_list_tile.dart'; import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -23,11 +23,13 @@ import 'package:adguard_home_manager/models/filtering.dart'; class ListDetailsScreen extends StatefulWidget { final Filter list; final String type; + final bool dialog; const ListDetailsScreen({ Key? key, required this.list, required this.type, + required this.dialog }) : super(key: key); @override @@ -218,122 +220,234 @@ class _ListDetailsScreenState extends State { } } - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.listDetails), - actions: [ - IconButton( - onPressed: () => { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (ctx) => AddListModal( - list: widget.list, - type: widget.type, - onEdit: confirmEditList, - dialog: true, - ), - ) - } - else { - showModalBottomSheet( - context: context, - builder: (ctx) => AddListModal( - list: widget.list, - type: widget.type, - onEdit: confirmEditList, - dialog: false, - ), - isScrollControlled: true, - backgroundColor: Colors.transparent - ) - } - }, - icon: const Icon(Icons.edit), - tooltip: AppLocalizations.of(context)!.edit, + List content() { + return [ + CustomListTile( + icon: Icons.shield_rounded, + title: AppLocalizations.of(context)!.currentStatus, + subtitleWidget: Text( + enabled == true + ? AppLocalizations.of(context)!.enabled + : AppLocalizations.of(context)!.disabled, + style: TextStyle( + color: enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + fontWeight: FontWeight.w500 + ), ), - IconButton( - onPressed: () { + padding: widget.dialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + CustomListTile( + icon: Icons.badge_rounded, + title: AppLocalizations.of(context)!.name, + subtitle: name, + padding: widget.dialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + CustomListTile( + icon: Icons.link_rounded, + title: "URL", + subtitle: widget.list.url, + padding: widget.dialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + CustomListTile( + icon: Icons.list_rounded, + title: AppLocalizations.of(context)!.rules, + subtitle: widget.list.rulesCount.toString(), + padding: widget.dialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + CustomListTile( + icon: Icons.shield_rounded, + title: AppLocalizations.of(context)!.listType, + subtitle: widget.type == 'whitelist' + ? AppLocalizations.of(context)!.whitelist + : AppLocalizations.of(context)!.blacklist, + padding: widget.dialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + if (widget.list.lastUpdated != null) CustomListTile( + icon: Icons.schedule_rounded, + title: AppLocalizations.of(context)!.latestUpdate, + subtitle: convertTimestampLocalTimezone(widget.list.lastUpdated!, 'dd-MM-yyyy HH:mm'), + padding: widget.dialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + if (widget.dialog == true) Container(height: 16) + ]; + } + + List actions() { + return [ + IconButton( + onPressed: () => { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { showDialog( context: context, - builder: (context) => DeleteListModal( - onConfirm: () => deleteList(widget.list, widget.type), - ) - ); - }, - icon: const Icon(Icons.delete), - tooltip: AppLocalizations.of(context)!.delete, + builder: (ctx) => AddListModal( + list: widget.list, + type: widget.type, + onEdit: confirmEditList, + dialog: true, + ), + ) + } + else { + showModalBottomSheet( + context: context, + builder: (ctx) => AddListModal( + list: widget.list, + type: widget.type, + onEdit: confirmEditList, + dialog: false, + ), + isScrollControlled: true, + backgroundColor: Colors.transparent + ) + } + }, + icon: const Icon(Icons.edit), + tooltip: AppLocalizations.of(context)!.edit, + ), + IconButton( + onPressed: () { + showDialog( + context: context, + builder: (context) => DeleteListModal( + onConfirm: () => deleteList(widget.list, widget.type), + ) + ); + }, + icon: const Icon(Icons.delete), + tooltip: AppLocalizations.of(context)!.delete, + ), + const SizedBox(width: 10), + ]; + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 ), - const SizedBox(width: 10), - ], - ), - body: Stack( - children: [ - ListView( + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - FilterListTile( - icon: Icons.shield_rounded, - title: AppLocalizations.of(context)!.currentStatus, - subtitle: enabled == true - ? AppLocalizations.of(context)!.enabled - : AppLocalizations.of(context)!.disabled, - color: enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - bold: true, - ), - FilterListTile( - icon: Icons.badge_rounded, - title: AppLocalizations.of(context)!.name, - subtitle: name - ), - FilterListTile( - icon: Icons.link_rounded, - title: "URL", - subtitle: widget.list.url - ), - FilterListTile( - icon: Icons.list_rounded, - title: AppLocalizations.of(context)!.rules, - subtitle: widget.list.rulesCount.toString() - ), - FilterListTile( - icon: Icons.shield_rounded, - title: AppLocalizations.of(context)!.listType, - subtitle: widget.type == 'whitelist' - ? AppLocalizations.of(context)!.whitelist - : AppLocalizations.of(context)!.blacklist, - ), - if (widget.list.lastUpdated != null) FilterListTile( - icon: Icons.schedule_rounded, - title: AppLocalizations.of(context)!.latestUpdate, - subtitle: convertTimestampLocalTimezone(widget.list.lastUpdated!, 'dd-MM-yyyy HH:mm'), + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, + ), + const SizedBox(width: 8), + Text( + AppLocalizations.of(context)!.listDetails, + style: const TextStyle( + fontSize: 22 + ), + ) + ], + ), + Row( + children: [ + IconButton( + onPressed: () => enableDisableList(widget.list, !enabled), + icon: Icon( + enabled == true + ? Icons.gpp_bad_rounded + : Icons.verified_user_rounded, + ), + tooltip: enabled == true + ? AppLocalizations.of(context)!.disableList + : AppLocalizations.of(context)!.enableList, + ), + ...actions() + ], + ) + ], + ), ), + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: content(), + ), + ) + ) ], ), - AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: fabVisible ? - appConfigProvider.showingSnackbar - ? 70 : (Platform.isIOS ? 40 : 20) - : -70, - right: 20, - child: FloatingActionButton( - onPressed: () => enableDisableList(widget.list, !enabled), - child: Icon( - enabled == true - ? Icons.gpp_bad_rounded - : Icons.verified_user_rounded, - ), + ) + ); + } + else { + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.listDetails), + actions: actions(), + ), + body: Stack( + children: [ + ListView( + children: content(), ), - ) - ], - ), - ); + AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: fabVisible ? + appConfigProvider.showingSnackbar + ? 70 : (Platform.isIOS ? 40 : 20) + : -70, + right: 20, + child: FloatingActionButton( + onPressed: () => enableDisableList(widget.list, !enabled), + child: Icon( + enabled == true + ? Icons.gpp_bad_rounded + : Icons.verified_user_rounded, + ), + ), + ) + ], + ), + ); + } } } \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index fe93473..167e2bb 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -119,7 +119,7 @@ class SettingsWidget extends StatelessWidget { ), body: ListView( children: [ - if (serversProvider.selectedServer != null) ...[ + if (serversProvider.selectedServer != null && serversProvider.serverStatus.data != null) ...[ SectionLabel(label: AppLocalizations.of(context)!.serverSettings), if (serverVersionIsAhead( currentVersion: serversProvider.serverStatus.data!.serverVersion, diff --git a/lib/widgets/custom_list_tile.dart b/lib/widgets/custom_list_tile.dart index bfd379d..6f27129 100644 --- a/lib/widgets/custom_list_tile.dart +++ b/lib/widgets/custom_list_tile.dart @@ -23,7 +23,7 @@ class CustomListTile extends StatelessWidget { this.padding, this.onLongPress, this.disabled, - this.onHover + this.onHover, }) : super(key: key); @override diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 8492786..cb9d874 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { @@ -17,6 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); g_autoptr(FlPluginRegistrar) window_size_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin"); window_size_plugin_register_with_registrar(window_size_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 163e042..da06542 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color sqlite3_flutter_libs + url_launcher_linux window_size ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b4f5f0d..1c34d3c 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,6 +10,7 @@ import dynamic_color import package_info_plus_macos import sqflite import sqlite3_flutter_libs +import url_launcher_macos import window_size func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { @@ -18,5 +19,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin")) } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 338e2e2..9346410 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -27,6 +27,8 @@ PODS: - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree + - url_launcher_macos (0.0.1): + - FlutterMacOS - window_size (0.0.2): - FlutterMacOS @@ -37,6 +39,7 @@ DEPENDENCIES: - package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) + - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`) SPEC REPOS: @@ -57,6 +60,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos sqlite3_flutter_libs: :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos + url_launcher_macos: + :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos window_size: :path: Flutter/ephemeral/.symlinks/plugins/window_size/macos @@ -69,6 +74,7 @@ SPEC CHECKSUMS: sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea sqlite3: d31b2b69d59bd1b4ab30e5c92eb18fd8e82fa392 sqlite3_flutter_libs: f20746e4a0245afbee4f20d9afc0072ebff7cc26 + url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451 window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 diff --git a/pubspec.lock b/pubspec.lock index c1e392f..898b60a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -675,6 +675,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.4" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + url: "https://pub.dev" + source: hosted + version: "6.1.10" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "22f8db4a72be26e9e3a4aa3f194b1f7afbc76d20ec141f84be1d787db2155cbd" + url: "https://pub.dev" + source: hosted + version: "6.0.31" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" + url: "https://pub.dev" + source: hosted + version: "2.0.16" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" + url: "https://pub.dev" + source: hosted + version: "3.0.6" uuid: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 135c7b6..34a0e57 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: git: url: https://github.com/JGeek00/flutter_split_view ref: hide-divider + url_launcher: ^6.1.10 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 208406a..3d0e948 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -15,6 +16,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); WindowSizePluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("WindowSizePlugin")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 69d8901..8ca2ff7 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color sqlite3_flutter_libs + url_launcher_windows window_size ) From b8d2ee9e0d521e7c26ae6f55e50b04c704b1b5a9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 3 May 2023 16:35:53 +0200 Subject: [PATCH 067/676] Added custom menu --- lib/base.dart | 75 ++++++++++++++++--------------- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/widgets/menu_bar.dart | 92 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 38 deletions(-) create mode 100644 lib/widgets/menu_bar.dart diff --git a/lib/base.dart b/lib/base.dart index 1c5ad7d..c33fce3 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -11,6 +11,7 @@ import 'package:store_checker/store_checker.dart'; import 'package:flutter/services.dart'; import 'package:adguard_home_manager/widgets/bottom_nav_bar.dart'; +import 'package:adguard_home_manager/widgets/menu_bar.dart'; import 'package:adguard_home_manager/widgets/update_modal.dart'; import 'package:adguard_home_manager/widgets/navigation_rail.dart'; @@ -127,43 +128,45 @@ class _BaseState extends State with WidgetsBindingObserver { ? screensServerConnected : screensSelectServer; - return AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarColor: Colors.transparent, - statusBarBrightness: Theme.of(context).brightness == Brightness.light - ? Brightness.light - : Brightness.dark, - statusBarIconBrightness: Theme.of(context).brightness == Brightness.light - ? Brightness.dark - : Brightness.light, - systemNavigationBarColor: Theme.of(context).scaffoldBackgroundColor, - systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light - ? Brightness.dark - : Brightness.light, - ), - child: Scaffold( - body: Row( - children: [ - if (width > 900) const SideNavigationRail(), - Expanded( - child: PageTransitionSwitcher( - duration: const Duration(milliseconds: 200), - transitionBuilder: ( - (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( - animation: primaryAnimation, - secondaryAnimation: secondaryAnimation, - child: child, - ) - ), - child: screens[appConfigProvider.selectedScreen].body, - ), - ), - ], + return CustomMenuBar( + child: AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarBrightness: Theme.of(context).brightness == Brightness.light + ? Brightness.light + : Brightness.dark, + statusBarIconBrightness: Theme.of(context).brightness == Brightness.light + ? Brightness.dark + : Brightness.light, + systemNavigationBarColor: Theme.of(context).scaffoldBackgroundColor, + systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light + ? Brightness.dark + : Brightness.light, ), - bottomNavigationBar: width <= 900 - ? const BottomNavBar() - : null, - ) + child: Scaffold( + body: Row( + children: [ + if (width > 900) const SideNavigationRail(), + Expanded( + child: PageTransitionSwitcher( + duration: const Duration(milliseconds: 200), + transitionBuilder: ( + (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( + animation: primaryAnimation, + secondaryAnimation: secondaryAnimation, + child: child, + ) + ), + child: screens[appConfigProvider.selectedScreen].body, + ), + ), + ], + ), + bottomNavigationBar: width <= 900 + ? const BottomNavBar() + : null, + ) + ), ); } } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index c08bb8e..3b087c6 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -611,5 +611,6 @@ "selectOptionLeftColumn": "Select an option of the left column", "selectClientLeftColumn": "Select a client of the left column", "disableList": "Disable list", - "enableList": "Enable list" + "enableList": "Enable list", + "screens": "Screens" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index e4bf4b6..90c396a 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -611,5 +611,6 @@ "selectOptionLeftColumn": "Selecciona una opción de la columna de la izquierda", "selectClientLeftColumn": "Selecciona un cliente de la columna de la izquierda", "disableList": "Deshabilitar lista", - "enableList": "Habilitar lista" + "enableList": "Habilitar lista", + "screens": "Pantallas" } \ No newline at end of file diff --git a/lib/widgets/menu_bar.dart b/lib/widgets/menu_bar.dart new file mode 100644 index 0000000..0151b87 --- /dev/null +++ b/lib/widgets/menu_bar.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/config/app_screens.dart'; +import 'package:adguard_home_manager/models/app_screen.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class CustomMenuBar extends StatelessWidget { + final Widget child; + + const CustomMenuBar({ + Key? key, + required this.child + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + List screens = serversProvider.selectedServer != null + ? screensServerConnected + : screensSelectServer; + + String translatedName(String key) { + switch (key) { + case 'connect': + return AppLocalizations.of(context)!.connect; + + case 'home': + return AppLocalizations.of(context)!.home; + + case 'settings': + return AppLocalizations.of(context)!.settings; + + case 'clients': + return AppLocalizations.of(context)!.clients; + + case 'logs': + return AppLocalizations.of(context)!.logs; + + case 'filters': + return AppLocalizations.of(context)!.filters; + + default: + return ''; + } + } + + return PlatformMenuBar( + menus: [ + PlatformMenu( + label: 'AdGuard Home Manager', + menus: [ + if ( + PlatformProvidedMenuItem.hasMenu(PlatformProvidedMenuItemType.about) + ) const PlatformMenuItemGroup( + members: [ + PlatformProvidedMenuItem( + type: PlatformProvidedMenuItemType.about, + ), + ] + ), + if ( + PlatformProvidedMenuItem.hasMenu(PlatformProvidedMenuItemType.quit) + ) const PlatformMenuItemGroup( + members: [ + PlatformProvidedMenuItem( + type: PlatformProvidedMenuItemType.quit, + ), + ] + ) + ], + ), + PlatformMenu( + label: AppLocalizations.of(context)!.screens, + menus: [ + PlatformMenuItemGroup( + members: screens.asMap().entries.map((e) => PlatformMenuItem( + label: "${appConfigProvider.selectedScreen == e.key ? '✔' : ''} ${translatedName(e.value.name)}", + onSelected: () => appConfigProvider.setSelectedScreen(e.key), + )).toList() + ), + ], + ), + ], + child: child, + ); + } +} \ No newline at end of file From dafff9b2427494a91884d45c39cbcfeed2097941 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 01:45:08 +0200 Subject: [PATCH 068/676] Dynamic column width splitview --- lib/screens/clients/added_list.dart | 17 +++++++++-------- lib/screens/clients/clients.dart | 1 + lib/screens/settings/settings.dart | 1 + pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 9bb3ab5..87cae35 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -219,7 +219,6 @@ class _AddedListState extends State { : null, loadingGenerator: () => SizedBox( width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, @@ -251,12 +250,15 @@ class _AddedListState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - AppLocalizations.of(context)!.noClientsList, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + AppLocalizations.of(context)!.noClientsList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ), const SizedBox(height: 30), @@ -270,7 +272,6 @@ class _AddedListState extends State { ), errorGenerator: () => SizedBox( width: double.maxFinite, - height: MediaQuery.of(context).size.height-171, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index bdaf046..22cf0ef 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -173,6 +173,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM if (width > 900) { return SplitView.material( hideDivider: true, + flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), placeholder: Center( child: Padding( padding: const EdgeInsets.all(24), diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 167e2bb..4ae2cb5 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -40,6 +40,7 @@ class Settings extends StatelessWidget { if (width > 900) { return SplitView.material( hideDivider: true, + flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), placeholder: Center( child: Padding( padding: const EdgeInsets.all(24), diff --git a/pubspec.lock b/pubspec.lock index 898b60a..fd67c77 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -295,8 +295,8 @@ packages: dependency: "direct main" description: path: "." - ref: hide-divider - resolved-ref: e22dd0bf64e7d61a64eb99fcd9a4e111e177ccf3 + ref: master-alt + resolved-ref: a6aa2419243cc0abccf9474ce340790d6c0ded6f url: "https://github.com/JGeek00/flutter_split_view" source: git version: "0.1.2" diff --git a/pubspec.yaml b/pubspec.yaml index 34a0e57..04d834a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,7 +63,7 @@ dependencies: flutter_split_view: git: url: https://github.com/JGeek00/flutter_split_view - ref: hide-divider + ref: master-alt url_launcher: ^6.1.10 dev_dependencies: From 769238cff9a0214f4c60526ae277192815eb243e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 01:59:50 +0200 Subject: [PATCH 069/676] Improvements clients view --- lib/screens/clients/clients.dart | 197 +++++++++--------- lib/screens/clients/clients_desktop_view.dart | 160 +++++++++----- lib/screens/clients/clients_list.dart | 6 +- 3 files changed, 206 insertions(+), 157 deletions(-) diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 22cf0ef..9e13c77 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -131,7 +131,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM ); } - Widget tabBarView() { + Widget tabBarView(bool sliver) { return TabBarView( controller: tabController, children: [ @@ -149,6 +149,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM ) )), splitView: false, + sliver: sliver, ), AddedList( scrollController: scrollController, @@ -168,33 +169,33 @@ class _ClientsWidgetState extends State with TickerProviderStateM ] ); } - - if (!(Platform.isAndroid || Platform.isIOS)) { - if (width > 900) { - return SplitView.material( - hideDivider: true, - flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), - placeholder: Center( - child: Padding( - padding: const EdgeInsets.all(24), - child: Text( - AppLocalizations.of(context)!.selectClientLeftColumn, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), + + if (width > 900) { + return SplitView.material( + hideDivider: true, + flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), + placeholder: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + AppLocalizations.of(context)!.selectClientLeftColumn, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant ), ), ), - child: ClientsDesktopView( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - fetchClients: fetchClients, - ) - ); - } - else { + ), + child: ClientsDesktopView( + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + fetchClients: fetchClients, + ) + ); + } + else { + if (!(Platform.isAndroid || Platform.isIOS)) { return DefaultTabController( length: 2, child: Scaffold( @@ -217,87 +218,87 @@ class _ClientsWidgetState extends State with TickerProviderStateM ], bottom: tabBar() ), - body: tabBarView(), + body: tabBarView(false), ), ); } - } - else { - return DefaultTabController( - length: 2, - child: NestedScrollView( - controller: scrollController, - headerSliverBuilder: ((context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - title: searchMode == true - ? Row( - children: [ - IconButton( - onPressed: () { - setState(() { - searchMode = false; - searchController.text = ""; - serversProvider.setSearchTermClients(null); - }); - }, - icon: const Icon(Icons.arrow_back_rounded) - ), - const SizedBox(width: 16), - Expanded( - child: TextField( - controller: searchController, - onChanged: (value) => serversProvider.setSearchTermClients(value), - decoration: InputDecoration( - suffixIcon: IconButton( - onPressed: () { - setState(() { - searchController.text = ""; - serversProvider.setSearchTermClients(null); - }); - }, - icon: const Icon(Icons.clear_rounded) + else { + return DefaultTabController( + length: 2, + child: NestedScrollView( + controller: scrollController, + headerSliverBuilder: ((context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + title: searchMode == true + ? Row( + children: [ + IconButton( + onPressed: () { + setState(() { + searchMode = false; + searchController.text = ""; + serversProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.arrow_back_rounded) + ), + const SizedBox(width: 16), + Expanded( + child: TextField( + controller: searchController, + onChanged: (value) => serversProvider.setSearchTermClients(value), + decoration: InputDecoration( + suffixIcon: IconButton( + onPressed: () { + setState(() { + searchController.text = ""; + serversProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.clear_rounded) + ), + hintText: AppLocalizations.of(context)!.search, + hintStyle: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + border: InputBorder.none, ), - hintText: AppLocalizations.of(context)!.search, - hintStyle: const TextStyle( + style: const TextStyle( fontWeight: FontWeight.normal, fontSize: 18 ), - border: InputBorder.none, ), - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - ), - ) - ], - ) - : Text(AppLocalizations.of(context)!.clients), - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ - IconButton( - onPressed: () => setState(() => searchMode = true), - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.searchClients, - ), - const SizedBox(width: 10), - ] - ], - bottom: tabBar() - ), - ) - ]; - }), - body: tabBarView() - ) - ); + ) + ], + ) + : Text(AppLocalizations.of(context)!.clients), + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + actions: [ + if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + IconButton( + onPressed: () => setState(() => searchMode = true), + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.searchClients, + ), + const SizedBox(width: 10), + ] + ], + bottom: tabBar() + ), + ) + ]; + }), + body: tabBarView(true) + ) + ); + } } } } \ No newline at end of file diff --git a/lib/screens/clients/clients_desktop_view.dart b/lib/screens/clients/clients_desktop_view.dart index 19e6254..0a4b783 100644 --- a/lib/screens/clients/clients_desktop_view.dart +++ b/lib/screens/clients/clients_desktop_view.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; @@ -84,7 +86,7 @@ class _ClientsDesktopViewState extends State with TickerPro ); } - Widget tabBarView() { + Widget tabBarView(bool sliver) { return TabBarView( controller: tabController, children: [ @@ -107,7 +109,8 @@ class _ClientsDesktopViewState extends State with TickerPro ); }), selectedClient: selectedActiveClient, - splitView: true + splitView: true, + sliver: sliver, ), AddedList( scrollController: scrollController, @@ -134,69 +137,112 @@ class _ClientsDesktopViewState extends State with TickerPro ); } - return DefaultTabController( - length: 2, - child: Scaffold( - appBar: AppBar( - title: searchMode == true - ? Row( - children: [ - IconButton( + Widget title() { + if (searchMode == true) { + return Row( + children: [ + IconButton( + onPressed: () { + setState(() { + searchMode = false; + searchController.text = ""; + serversProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.arrow_back_rounded) + ), + const SizedBox(width: 16), + Expanded( + child: TextField( + controller: searchController, + onChanged: (value) => serversProvider.setSearchTermClients(value), + decoration: InputDecoration( + suffixIcon: IconButton( onPressed: () { setState(() { - searchMode = false; searchController.text = ""; serversProvider.setSearchTermClients(null); }); - }, - icon: const Icon(Icons.arrow_back_rounded) + }, + icon: const Icon(Icons.clear_rounded) ), - const SizedBox(width: 16), - Expanded( - child: TextField( - controller: searchController, - onChanged: (value) => serversProvider.setSearchTermClients(value), - decoration: InputDecoration( - suffixIcon: IconButton( - onPressed: () { - setState(() { - searchController.text = ""; - serversProvider.setSearchTermClients(null); - }); - }, - icon: const Icon(Icons.clear_rounded) - ), - hintText: AppLocalizations.of(context)!.search, - hintStyle: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - border: InputBorder.none, - ), - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - ), - ) - ], - ) - : Text(AppLocalizations.of(context)!.clients), - centerTitle: false, - actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ - IconButton( - onPressed: () => setState(() => searchMode = true), - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.searchClients, + hintText: AppLocalizations.of(context)!.search, + hintStyle: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + border: InputBorder.none, + ), + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), ), - const SizedBox(width: 10), - ] + ) ], - bottom: tabBar() + ); + } + else { + return Text(AppLocalizations.of(context)!.clients); + } + } + + if (!(Platform.isAndroid || Platform.isIOS)) { + return DefaultTabController( + length: 2, + child: Scaffold( + appBar: AppBar( + title: title(), + centerTitle: false, + actions: [ + if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + IconButton( + onPressed: () => setState(() => searchMode = true), + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.searchClients, + ), + const SizedBox(width: 10), + ] + ], + bottom: tabBar() + ), + body: tabBarView(false), ), - body: tabBarView(), - ), - ); + ); + } + else { + return DefaultTabController( + length: 2, + child: NestedScrollView( + controller: scrollController, + headerSliverBuilder: ((context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + title: title(), + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + actions: [ + if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + IconButton( + onPressed: () => setState(() => searchMode = true), + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.searchClients, + ), + const SizedBox(width: 10), + ] + ], + bottom: tabBar() + ), + ) + ]; + }), + body: tabBarView(true) + ) + ); + } } } \ No newline at end of file diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index 3ca250b..9d2f11b 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -18,6 +18,7 @@ class ClientsList extends StatelessWidget { final void Function(AutoClient) onClientSelected; final AutoClient? selectedClient; final bool splitView; + final bool sliver; const ClientsList({ Key? key, @@ -27,7 +28,8 @@ class ClientsList extends StatelessWidget { required this.fetchClients, required this.onClientSelected, this.selectedClient, - required this.splitView + required this.splitView, + required this.sliver }) : super(key: key); @override @@ -36,7 +38,7 @@ class ClientsList extends StatelessWidget { listPadding: splitView == true ? const EdgeInsets.only(top: 8) : null, - noSliver: !(Platform.isAndroid || Platform.isIOS), + noSliver: !sliver, loadingGenerator: () => SizedBox( width: double.maxFinite, height: MediaQuery.of(context).size.height-171, From 037bcc7cdb877c6809d586546dd41e89269aff85 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 02:08:05 +0200 Subject: [PATCH 070/676] Changed macOS icon --- assets/icon/icon-macos.png | Bin 434970 -> 435398 bytes .../AppIcon.appiconset/app_icon_1024.png | Bin 431799 -> 433039 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 5762 -> 6707 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 532 -> 559 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 18240 -> 20378 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 1005 -> 1170 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 84277 -> 87896 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 2246 -> 2661 bytes 8 files changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/icon/icon-macos.png b/assets/icon/icon-macos.png index 5bd77ccaad26e33093b6af60bfb9e958763327c8..c201d7007050f637588bdc5c94c6f903e80a68fa 100755 GIT binary patch delta 373376 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

*o#14Ru&t2Oz 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�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 z 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%0AuWEH4_4m&TiuTEl0=DsYZ+p;7I$7;gAH z(&*S8FpC|me=~FPC)uU!msVveRT&n@#Mp>ol^S(;90Ecd!lXRvx1TzHRen50Vg;{p z^|O<|fq|jg%Z#ABL$PNn&vu7hZL%9+SAKa>iu+AnWyfL_+~8`q{m&#bFNdWn{dIQb znEZJS!+&8v4JE=HYYTZm?9BY}D(|#cqje@NGd72-FYHF8ISnSL*3NnAv|od_(m(Ru zAQru&UccV)g_$s-@aZ|s^;x4gGbfYmJuGO}J-%aM{S}s3F_!8n?y3}!mqpQSG;)3t z<<>0(MgpS7#8R}_$r$KvGZ|d*V4)MdY?>;k-mp;5YvH-m8!pb+^+t^yN-C+SF9_K+ zkiStJ25bSckJ~&Iyq!hW1UD=U-k~2w+GrO|L^~KRH1LO?Dp8O5(D((ctOpJx-O)1I za2>^x+%1nZrM}kY*94&0ozX21E}5kmx7&ddKkU$Q!1h^Hk(JM*eP~ruUo@qS z<9)Pr8|pE?D98avCU385MpZ@-@?@qe?^I%hrFXb=t-vEBt}QjGiDG;igCP8;Q3v!R zd%}-}EjKqEdJZ{$99w1_ZyrdP-*+WUcB9(=OQceSB;Z0xz)h{ov@g96YAt&@{P>L> zVEn*o05)5d0$ycQfnOFf;m;4+pR~>_;P?97QT@y~musQjJ}DBZl2&`ZmGKEn=mT$9-2K8ow8 z7g~sIp!ZiaT$0e8UAgi7!g#X{-tSCcdexfvI5nxJ2rCw&T+g@q&e4+am+<_jeT_6c zaS;n@1^Lpt+UIu9gVPArdp993n#sK+<98VT2x!1`SAU|IhaB!)#8rnir$fSeX=J?Z zckEB!D!yt7VxQgdH3a;s&o<>lRX+X08n~RmNkvvUI%F4T%Cp`-`oFT?a$}MsRq$vK z^Q?NaG+xid9p+E)cxSUGaj#&R;#yD_9O#{?r#El2QVm}FcGtV^aE~B`l*uB7(=1+0 z4kW*89$_f+ykOWxw~CyLRKA|aC@6Mx^eBxy^U7(sRPL4cYY_4??@h7U$#%Vg-vZ=2t!9m zO!a2a-XQQ9{Tl04+_)L|GH~Rn&jw`zK>eQlOYh6M2QN2CFTwW=SI&D&yTQSt`-*?P z!ZQN)!ZzXOL?I7ahSMyQuS=c0@{ayu-v=!Y?|W`28>Va)mH)+HX-7Yh-*9q zmyuSj2|4Na={ki$as6rVf#an;z6Zgbf~hPWCyINwAF=oEK1jwC!@GEh=Up|;@2?q_ zje$9a1QqgCF6Cs`7JC%S`}$sl0^gk->d!nivjZH^tSN{35*>av8v@->dk0`d=OE_V zb8n*_q-3HnNF&If;cXHb8KzeC*s?+8ZTiCwK7tW0$TK!))0j8O_bV0>*b^sx0snMz zAGPMdT%8(n6p{dCQVq5CIYjN2#-2WU<>{zO+HR=Q4l}AkqYGAnle##AtV7>$chKQ| ztBgm|gx8tE+s3L9sCz|u3a}$uJf@D72p>X@emj8_>)IT zk4={mStEL{xPWSKeYGdJPv$}bb~s>bl1jfaL}HD@!KJaTw~P&hP-;JYS_A7^7)(@e zgjn7ITDMp*Qo-H22bu?OO;xe6r9j<(%ln^0Q(sX-K=GT{sPS17k> z!qAu4U^`7ltfR4|(W{JGhkgRAGn}x(tIEYz3xrohUaP2-A^o4%5mLaKU3spP4-^K) zCs-8%o=kam4bGP!D>!dPHhjW+n5#Z``vt>7pj0$gVm#TM?OgAabuaC8rykWO5Tok> z>TIQXNt*<-h>wZ8bzq|Y0 zzA)Z`(=+*pSuleI`2Gx8tsusPob;OlV(5;*`uyAOt%`>GlTNzKVnHazDdv90v5=E03mk zCw43SEwJpyowPI55)A)56nr2y*{d4F<9>N3eOvy8r9x__pU;^y9crgb+_`)t&V~-C zXPPhPNFdaL`VU`U#1@dpyoY3f;6Ht4dA_*3pul>K1TmhhZ5Te8M=rZqLbj4cybD{7 zv@%>H5zf9euDdxGwLWI>?UE9{L=UBpXFQ?5?pL*G-=h;Ti&o0|=n^$*z7uLd9@$ju zE5+T$D)J0WvDDqL^VN}I=i>sln=18Ba@>OSuRlNfHN9NTD*VNmd$nIvT~v3;*RKTz z!+~-+m^x7FC{GkoFm5cHny-Vk85ogxKZQ@0R9R`-XIq(QXW!(<&|MnXugG>n^g$sg z8@1*k?8l*(VSMUj@rkF_b1Q0?9fXxdOTy6ZZv~&}hKB5)hH}&xM85$h-}Op+z^ewA zzu)0;DXp}v$TpxE6-V#CXtj>?)l^!Q)Hqy)VJg@vPC`a*|;r4)b<$+e) z{fPt=d7>sHIezVF(K{jSC5bA(UV$TrQ6IVb+KxzzDjvY#4kA|LQ^`|-NbmS^vB7dj zny~S!sdI^jq_cgki*jQrp{!JmZG?Y|gq;j!73i6xaXpw%yAmCwb2iGh4Ug zUyLTT@eRO8d-ImTLXVkmMK#*+37W`gF{}njwNQ*5p-ybech-TJ8aA%Bfryb-;}MIt z4nx5Hfoq3OCH-Is^!#Hmu_V(*onKerHHuHW;)!mp78%$caOX$k9Z!TQL96lcB&-*< z=bUGE>wWE`JA3~F;mSv1KfiM3p0WC28T;)57tuD=)b*-d<$vR@nIQ zb**Rf#$-~>gj-82lu_5hgL`OymaEqq`!kM;|KclhDr~%Sld4s|H*h3R)(X%@tbT3C z*u3P;T=1#A_KmZ$b^lOc;t=zl==%|9TKDa5G0ag34cBx9_%N4)td8C$JrVW(gypvw zw)CN@7V__V{dPU5y!GUdblj`ppQ)^CdV}Ml&64W?n??usOS#g$gwnnDA$$XPKJHXm zal9SB>O7r%)VL0DGIJH5DIjYLl80WTOpe5O&7E?PV-aiDw?9Ys3l8gu+ca|1Jgc($ z_8X2tgQfz~s96m?D77G|1>+gIF0%dkk%Xd8p|GrXx8dV({WB)8C*YFNg8)j;ZR7AO zY4bjj(M2biFfknQu43MJ#=U)V2&ug*=qf8v?`PJ01; z$jkD#_iS@%SiB}`3+8w4Q&0UOY(xBt&C(T_P1vH+YZwt4eNuT58&_$%;gA1^XLHUXAyC$ny#p&oL%W43pi3D7 z3ZIfb*@`8)vf3?xje%g&4~G4qN1m6_SKFNoe@3bm&&qRAI;Auwg7$?{`Qx{9*A-4^ z9|zqnr2)(mr>hoN&`2;uxe)^Uy`o3{Tsio8Rut(6`KK^hVj&ZooUn0!xNVQC8yi|ampBP4+( zfYQGtIA#2DL_qM0S!w4tp@vPr`Di|>Rky4B9x?!22X%2%$nXdufW|q9{lu=vc?f~7 zhmQFpN9RA+`J$K)!G8wp;_D_NdPAE*yrjBn9s4V&%3D_zDq@JYP%3XM1bg}K*#D&I zJlibcvF5F zB9>DxK6g)MBmPFRj(_`VKFPo9CVYY5=a?^#pxDpJdTGBl$d$y}i)Otr7PlaWC%%PT zpaPJIo}pSN$qB`_d7>z9DXWt%A6M%}Tb znD`OkK6#kF;)hLenl-+)!%|P?(CHk^5xl?mK$d^vVY(U1^L7IktK1N-f{uzr?hAouY|00gx6g-h zF5Uw+5~R1fCz+e~KBgB^H8rYVw-k%eBC*FpG;4Az*C4Yu|s@GmzjG5Ctmf_To*HdZq& z#~2WHGzUFNU@O!AT~~s^T=LDQWBz*|B3|iRT7~#{AmBT2L+glgIOB%P!pbdeZMRuv zXRr5^(uQru-g*IYAy*|6d~himp5Hf%Gi|5oPliboXIhZHjKitWrF%3cdv^4FSGN9P z16C5@m#l@Oqj$W?XFNuw*Jg`Nw{SkEtz%GWZ#x$O26e#bWD4vBi zE_+Vw00cgo6;2PopxdrMB_$r)yFTO|om}2YQvDr%AKA=o@QJnKJxpIhg~*3~+-Csk zt8MSq9|Ra9iR6Zg zXx%vABzR%;R%H6}-ZhL%+3G@o#`~5Q&s9~X>bsJZ4B;JjS)|6#LGVKArXxwVVf({< ze%7drhLH1ySErw8nQ!Ju`8V3EIsg;kxMFdtxl}K<6GYZOxY!*Wv*nGE5w>dR*R6YS z8y>!Rw3^USH81!BDv0q(1cjq)bfe$={MTlTm_^g-gzL-7h17Ic0gs1roB5 zO(vBA^gWyKZ96ZUmcI?2_fYxPZ(iU_U+3!M8ZPoeb_i9Dz^w$s>)c2B zBFr7QGFP*F)i3-EoG3l*J%&8{*>6Ny^L$(z;6frb4p|i>(qQk-C7JaK$vB^$h6RQ?)dM5QRdh5(K4ltAugq?E3nsyb3 zj+7*+LtJa_qQFc`rMBe1D;xiX_{KYX;cg-d)Arj00@z@k0d)j|o(bX=M{ew{>1f6(G@7@7%R4|#>>0IpUm8LWJqep4J2wR}|> zN$lp&Lf!H59(|sqKSmo=2~(KE(T1_yrTVk!So6dlNh{aB+Q|>r-BXT0!t@2s4M%vZ z%NLX}o^kB{`BO!sJS+zDCP-GhX@JR(*)!ohSzOu8d|=>*gA^w8V9|h$<7xW$@fa7= zm!c-~JWU$}{8zKF&67&mf9(iAyw!O7K_-1XxM0d{KW0Pcx5PB59kZ7AdWJ^Ir4Ob! z{@ed4o`o};+A9WWOAW`>Z)36iDlnfg#f;@OqC3~k7UIN@0b@j|C`|gSmp@jI4$*(- zVBRR>EmotD~awfk_mkzkO`}$>U6!%btF?SDMBfdjQSMeq+sh}l7w0b?5J#IQ}?gFN|0JwtZ@kN#X-@186xzz-fb}(8{OIi&f%&57+egmkNiyy-S4>LW8UKz|i{Ep7I z)&}jv(#tcYFM)k#WxSAZWzu5!6zJK|Y`wvEEG+9vf{WKX;lzQ=C*7)Ko$h6O9lk{} z&50+nzds0T{l77ZvCXG&_mr-Ey$C9fl&ZHNVtW_S*Ro6=Bk4`lzu z5{HIQ87X(@>>e&Ncs#=etKj_J-`k2<;#7Ft&YD1$P$$kOrs)9nE`PND_LCDT1|WiJ z(o!XNs+T)zq6Q0krK@nxz~Gu4;pl`v!}d{x8W;bB<@#7L-^+G;jmEx*$FR=7DcQW1 zoOx?U-xf)D7Me9vk>#iA8fOHCdsg^}ZJ^kGgZ}{!D$&AWeBeGgRJtX{K5TPm=SekaI0G%gNN~`No_0S=T2nMM&eoqkHz9}}fHMc2&o)WThI3=H`TBN4cR_Q2Q!=bJkX_;pZ$Vwl9U)V!C^E5fsVahoTz_? zqJH`#MsPZ)`5z-2FJw5e#h3z?W*C0@o+zdS~vb-q& zv)Qn>z&aB3Y07XK%O#LYgrrKQ-}gs!00qm9d)jNT5R*+xp5{&`ymTo0JaBJLi{z$c z{2xx@TND&gu#I*KG2fBE-|~tncx^glU(5u?$Kq_^*9K|A+9j94pq(A?t4kv= z8TF5w2pJVsQ0>2@i$|<2TAR#Fgo0ykr|;lm3*SNu2}s;vIswkTgqge#1|%`_ht-cQ z8pBg<=!;CWaizX&+m9Ljxv4#*Er$9~SuI$^96RqLmVcVbhve+vo2VM8(+LYBY*M)TT6K`_qDTV`MY`hBV7Fs}TZYm& zRdppv_8mC9rq~;bssv+!esNaUcJzcOz}%$yZk|R%pe%yo*7QPnKe6ayWmLR=gr;Ks z=YfeOl8wc${`eMkE~}69K{G+R505O#!gY&|gkq5JVOIWpso_`o}RP&_xUh zwO_0bD54@&6N2qjHE5Clf0zIwxg%3TY6*JZjV2wIn|IcHRMiu|%r(D{wrb3nfBFh6 zZYWXOSD7uL*r5Ta%IN}o)K>UKTL$I(;usg!Bb!pgwJ5z3%1Foj5J!F63)scA zCyAB#q8~(Z?i<@b+XTT5QNxJ37_)q-FuPSnX8yP#$ZU@Erw~5?G89g{>JT>K=ZP*fi9iwNE`?Kl)ZugIJ z8x6PYDqW2%VYfSA^=eM*NS#+?qB=bt(Z2NEO_(U!MEK_Cq>aB{2xnYwI`#{x9@|Ai3G3BZhEfNE3_6bT91p{cQ9pUEY>Be{48gKaNe$qA zf}~gK*Ag8vTr}!TA683Nym~rqvCjAJm(;+wUCbrDo`Y?&?n7CksZ6d-im@PzWI?Vm zxpD+;l&ze9xkv+mnUffn-l;02@&B}38D_0`|771d7G!~ZtuFb|)dUZI%R%^SX2&hp zYX)no27Tw>JTW^&@Gs|_UN|<8ZI%N!l#&#yp#gJ0{6JV68R$QX?8F@(zBrKtLj000 zi{SS}!!1gwZb( z1{9+LsVykuLXYlqo;19lWDg@#d>0eA5Dx?&*cMh|pyZ(*uIK~@wMbx7*-J3qUZ5&W zI+<(odQI=NPIXq|Q+kCsbDb<6njZK}_2D3rf{9C(K?9=H#9vZPfdC`Tb?giR|yKA!~q;Xr;YF@ zttgRfu-zGgcC+TU;~(E?YiDcp1N6p-^&-;ho*C+-rk4VaGZX%PTKdnPHYs;=uMr*+ zmw(d5Zrq!&nFKKSHjQ}AG_MUj*8+zDv71)8Pv=VTH5186jM1IBWDosh-hS=5+DH3* zKft~61GulwH-r&nH?lR zJ?d-BJRc-U>|ObcYhX0@e@nku7aNhwl=QGT_|D@c)RaQYndx{CAS*-oi&PT77w(y6-AxHW?iC{J};U00SxfeF<| z(2|l(gy9mO_Rq+;(E)MVl8yLg9X3Lu4U>#;m(A3DW4lEYBk9z^dIUwGNPg)ZK|2O( zwNFtLxL9*6X;=^^hu-{K)pQj=@?)W`K;2|GU7tIUDs=}@Rssqs2v$s5JxZ2OYDXty zkVZmADO9>My!yYSDz!U5o9J+&8<9tfCt%JHcizPeC+_`t=hnywR@%(7xAz;VL2G>{ z=SJHlnUHf__zD^RoQgA&olvg`KNiY_!}2MYZN$(#YnSw}BS-`|e)zE_Y>iJ>QI+Ng zR=3(_iC=@f1WBY+Hgt_L{$pb6^3!fWaZmkRf#9lBa!5^5P-vI0v5^+-;T-z~dq>;c z;BhM5;XuL_Be&j(nb9I%8%sq)P*^-9_pfWk`TqvDh6$!%dX$L}dHN9LU!mE#)Z?jz zLy&Ax2NPca-!oO&Gjrl;o_o{B8drkp#;gnuApu?J`Fb`F6RxR~-G7Wp0w%p*UArA0_(frxrODqrh?jMO+$mw%V`VWX6wBd|c2e)vc)PaY4RV-Qo}&&={`#v@-lvCu z2+uDi&m4>csM{z+)zYnOtp79^DYjwDCsaF}$*3D*L$UN2hU?(r@W+|4SnLfzq2f_E zI;woXWBZ4~iq5hFB7#sp+4_zTFh9YMZz%Ucen18#o#TLgEf{xuCuim&J6LPOF|Z>%|bEQ-ED)5%QF+JH*-{v}!1q>L90 zjN4eKqVvj0Aq|@MRVD5MtuE}s4IzTMH|+Mcu6CY)B&g#OQj*66%6k&^&R~Nl+y)Y& zNU%~A0CXD6ui^ZpCx=ekZE$9Wv)JKr>34e-Bd7#d#wFa?1z=~*U(j9s8ZK|`!I;Km+mQdEIY zsYfqc%18r~)F{UAk@O!QBk1p9FnTs#NJ`z)J4qmytKq+8hoXO_On*&Jl0uG^ey2 zn*%S^l>K9lr%Q_oJGKfNkx4g4fveS3f=47b~_5%-y@ndi& zNywN+QEU>z;x)Cv#>Q(X{jgBR&_{A|ADJDg3F=>2s=tIGSEhogjy~E&SlCs_M=jSX zD$PT{pBq{G>vuKwBs>UvatUuRC!47{y-22o4ibyNdC@$mkQDm@yNw9*{GVhU+!!h(TRS zC-KYETnF_x{QNFB?pQRxPNI0baMB{h;~n=t4+P{xeK{_%UpM6zi3EP0T&Mb7SeQr_k({8oJ)a9{N42k!}FA6$u+- z+l8Kh{Fw`0IDA!yj%L=CjD|jVIH;u^Qzi1u?eMMLEMbI5ZC_S zpnJy@c99k$-8!VF1KLySgs;Dn)KALMkr$CI|8i)XAVPw#3v<3)doOE9o zig1D{Ac?;q`3~o<_Y@pDhw-G2DWQYn(--H(LZJd=;MiyW3}@rI@$2Lp$p{(qs_*ReE&3lSBF9wt%c7LMs35)2&mAd`hTqtx@bX?uoB9Gj`_RD)W;^V^k4i*h{Mc;r@FBX*V2KJn&awRxaED)eZGxXL8A`oACWYaw zAe(g!=Y5?EN3kIpfFHZgtGeiZOn@yKP!T8nbTtWik8f5s0A@YO%eimMe)}hjykKHr zd=;OLZiV$0Mp1l)PIPId=Q7PSw?mnDI`SAr11LZ?+s@C}^UJC!pj^r-Ethj*clZKV zfQ?wGXi?S{({q%*Zz;9vyUxM3(FAj^cnH5_@glh8HkDruW<5AMuuSX1O{8|zE=?r> z1i#ongMedhN2<%d4_g;P%0TUHMUThyRRNr#7xG#cxF#8Ah?R~ZQ7#KbTUiG5u zR=1AU8uU16c{UO>F=z$B+0YKWF_t?gzVqDWCUX$w$`ZXi9BDyJ_H+yhq`p*Uk^B>6 zqMGhFGd3il=E@n2Z+tSkzJi3!7Pi1Q`-j9M1^lrO^Ys=O^&~aBi6QaJe@Vg=6G09_ zIL8MZfk5itppmDq3y7hZ)9Cs_KS^D3Sx!E=IhCIUbEO1Q&s!YNCkM!hiNbBo<2fMc z|3|K+V%H49juKuZr>P>iKI2nEU!=ojyD{!4()JCLRNl?D-eXW_~VGr45B)Ckbzr!sS92zrxC?IY=L+ z!0&Ht_B-wiV^v499a>?E3zuCAzYst8&b?T4EL#Ijl9sJZCSU2gy=Hov22-TrSbj6T zb4RN0c2ge0{c4Kp|ovc_u=6W2rxVrwH^D*zTL z%)U5mx}>hw?N^PxWf$eGQ1@yC33_>pID}pALBzM&E6Y zT`wiBXp#Kv&vl{J^R(_06uJe0jYyNkXU(YojWb!Qc)!+VLx(U~{eu6|>JK0qib^Q{ zs9pve{z@HUG0~xe5i*y9ud9z9;p|uH>F8|haszHu#x47vLO~z)*(&&Qi}n!v+;^d8uA4WHD|((pDJQr4VCG+kqxfY2I?nET_k-Q!xaf?ZSdwf-J}4 ze*v5KDZ{8Ug*aQqC;zn_ECs|>I3M-tjr=*qF01+vvVKbPW<=c`FDA>Cn5ZaEv|xQC zOviX~BfGK(1CeXjqKRnhI9{jPSqAsj-t5%2XcHN;t1$8HC-L|vw!%8DC_BEVeJyvppt2ysAw<6jWl5h7R`)`@I z?*HNAc1ZTL?tyT8rPZ0__*ktbLIX{gVEU9zHS)($sS)rIy>XH#4qoz#zN*KvS*a}j zFee0?H;|W}yY{!Zq*jio{LJ1)8<=LJgBu+P&H6@1w087yxY-L4a{aUg2u$CFV8&oY zjWWcXOmYa4rtb@@MO2Nk#&7%DYVO1~7U3yrmjHP;6gFNfk&lAz4`0kIrp-!sD+8`x z8~aSNS?=%IvP@Gj?E5m&9^&()$tF4I4s9+Lns%0Zwn!!j7Izo~`#xvdy4$qK6J{ge2$L#Y=!heslufo^ zTVa39VmK6Iy@zrVw}Edgm!~a~Z@Q$XasR*ye3F|ZtH6?qN$N=B)K=nI&K%^Gn~OSIFQjz!z`Iz-8`SR?U-0BUh~v1Ba~VQF;zQJI#C$i2%Nq%yp#x&20#Dz zKpA#8=FV{o|0Y^W*)4I%l_c0-mWBPC1NqOSJfe2eKVlA#dGkINvy=9sl4PiNM+bnR zqKPW-8dj6)94Cjo#`Wo=)^ER7a5~4V3IUmuHf@=CJXzhJxi@T&H?JXy_fyM8D6Ify ze|o-l&63-IqKzxH2(ln{5mHu*^Lk_Qv7gb6@ac>ge|$d1ON+dOXf_zOKRyY|*XzC)6eGcyK51IqwVE5>t9 z=+IOtVNP%KeB=JIlL|wI6CNLlrhUppgh+*Wa(mry3`|Xt%|hL)$SKAD4y{SlWJM?H z*FfR@e9`*VjH!M>i|wv2F96vfK-Ayn+&p+T@-*3xdm&=(Z{UfPEPi35O6baB)k^WY zlz<0eG(07Av{mQA+rR4s;9$5XAr4AHa=?IufNE?x;Uq62WqulQc==AMPze!k%pk06 z8x-Q?8L?v>J|*;$Fwn19HEp}TFl?6v+llm=47wl$m1|DQ67Swg3NG4x-9OPh{d1gh zmeEKDhjydp)~+w*xu7s>9`dEq1?O+G^UoI_LiSTq8ZC0*}9i$((>43x#XLr%pc>QTFg42r>b7t^h>hsbS=jLEI9`XQI`BG-ObV^#m)J9$u`ZfurN^b9 zzRP5hdEm3uV**c5CjOG*^W~d0UlUv|fpEBilWhik108(W{azJK%Spt8W$7=~oQ!S} z_8YcRcE)>1WCs!de?e0SLE)JNU_4@@T zDlTQh<1R1SN#>-MB!6aF7i5{;?B2^hZWi0#zg7zD<}vKWiQ+`@Z&7CYFf_8lG9ZiK;;lpNp`Qji-h1$YAq`nS!Y%i_z1%V@L^#_F<#~ zCOqqP2&eh=u#=bJW<@?GCO}B&LF{b*E=Egd^*xcaAE!dg+pNhavdp$7_!VJ)KG=D*6Cw1}HH5co>{BevNBoEv z*>I7{6j<)Amf~}A@$%nCW_#%Z=CaXn?bXElsy8&s_j%$ISH=VX(Ea)517p<+H@*WE zrMVb(2=WVH5rmol<`24hs8HWa(EaAwc(-0z=acFz+*qHZD`~vLfU6b)$j*8eL~{f}_~H-L`{ubah|PjOr#QJz8S{TqN{e;EW$9 zFx)t5=_R$bSYPI0o$YDrJX-!6MGGCb_3+M@%zy@UJ5(ieFaa7}V%M4Xvu7!#3eFjx{k29XGq5|`94Cf`B5(EK+d41TP9hG+|nGSW@lmF zz&**&VY<`9Hc1i!Avt#GjEt|DeZ!v@TuvdoT#HeR&j7|EaC)>T>crelL^2Yjm)s8D zI-1w%t$5jfD@^U`hyQOfKedNRck+7jPX>)avJLZPTO5+S>B^3m*Y$rm+sTw;!528a zhiE-$)Tn@YAo2PpH*r?}wOu3ZF->{R@vT-c^ArYnJv!e?l(>lS9SqZ|%C;Nz;jtC} z-GvQB`ZMWZ>1ELT?_xA>823`iRhub)y@zAdc=WA1X{jkRmqY$kyPyr-HNn~X%0V=t zS`HxOc~JrJ&x*SL$B5G2eO32ss$ShE(se8YXQe&3He{tAGmzJ_Y7AV%ZLBE)x_GFH zAb^YyyuYbG)a~1NagX@Pa&TmE=iu3^Wl%jz#UzDsCMtYl2~#aE2NW`SOg6yfm1kXx z2N-7`n(P?qbRB!pLObXUt)fJn{EZ1M{OHD?!ByVz5i$^^{JTCYT}mJk$@kLP+VmTD-dEv<VK1!C+mpJrth6Py)g~cZGbqyh?(E!E1d3PQ%(!u&7h!a@O03 zY|oQ8Fx(%K-u;a``|6pc`)K(OQPR!yrP^@W&d+0CQy}nfX9>Y2g6f@g#@E)RFB-bE z69WEdHURQhlb{vh#@|yz&&oM+t#{s~ZWBS!}%`F1|mLC-oD01%EUT z%#3BNeZ1c_zWt@E(uIRV< z4M$cgh3(c6Ftq7R3U%&|@oGuC1uI2g&o9rxRa7*!2&nqjhFTdBn3)(8r-*_FBQWr> zIkl^Y-D^@Vz1Ls~Q%CPq><>0)iJm_IEfb$vpp(r<@t%q_w4UG zychX6=x}}q+NKax7+3#v{xaGU8FQcHVkLWFP^K;MffV4 zk$=hNO>NaeXK5!Xh8?eM3?J7XrNWB$X>7pW@(gvCdGn(%S=LkbKe_8l;=d{m3ubK{ z{#RVc4-#5YHb3}C_E7XhiSR+xC=P+u*?7{-Z|~xNos70df55;H<^fnVeNapf@sVku zVF)zm1bgyRiQn`v0%T}%$XI*A`TZynBewmli zblmOHWZBPC|6+zqAq?C#xkxX}FM7iiK7QEN=Oj!ewgbBVFy>^f+&;9$3^@z#G z`eD&%e0G#X_6#v=rW^&t5PXvL%Z2Go_68wJyszLbqbA?As=a9G@IOaGX1_F){TT42 zyL;9OSC?7NMHopEWBn$F?>oNW5>G9}mRWvd0741$+YJX6qEWr8+s05jq^6xGeInb& zSH4gA@?}+@PBAfL)|hI$DE=9qZ(T6;Wbh_73u2>7niF8fg(cWAv%;x_X#QskU!xXY zRva$$)Ae4h<55A132_ntRoSzfd1ww!H4Z>G-PH#Pl|Ek!k7+8O);B2@gG8(F*%O}R zd*7m%0j<$D&|QHJ#vu2H>U`K9Gye6Mccf5Nh}1-OmXiNIaG^51@Ogucdm`kmE0xFn z?*}r#g4A@wUdcJTvxY`i@23G_t%CbCaGAVAfcKuNqN@?p7#uPV#XzHl7@v;10? z186rl=awENmGq>>j*?M2MYl!=VzHy0`xUsiK>5R<~?GZ+B#9A-^K@Z3eEH z8^QBm!PM5@5M|z^9pRNle>q}W^_zR<)>5n$&SM~Z+q66O+TN=AN#J&N0&{{qx~_S^ zLv7X5R_v&%({yfEz8{tVI?#a1v+IS%0t+g}uFrrtYuQ`M8`BH6ExuD?e}Ta6M|;I_#?;eioT7PNWF zvM`qM^bF?bj}S>JTUxGR{)e~xtrV?M6GzSIH_mtj+vH^kLdpQ1)UnH2CMLR*xL26^K)VjDIhCAxPib00@{ZU1Py$bu79LUsnl>3gXhAFwE-4*Ta?<%gH8|l>Zp+bMZLYHpWylG7$F653QR&Yr=CD z-)`8f-^AF^|1x?Yb<7`HZ-TDwR0y`NENlAb{z5jXL%PGFlAPD`RPS@*b4obrqVm0g zfDc@z^z1p3hC+{V?7DB)LH7dA8Ems~v51fI6NSUoyMHiwlTa57R{jhs#@{`tluD?P zl*?LJ5-X``v=*pyDWvNBRqvKm1%K2f%jZ#P!Y`&gfm5!IA_^&&x{JCRE*W9g@IV1J z$*wD|*U@1Zb{w-T^Mi55mKSP2-6AzV%BDs5?F{+^o?mJ^HpFC~U$nDV``5U8!YH1( z7@WnaCDI}4JpYruW(*-%e0YD`WXwXHN9g|%G!WQF_gbMg;AxDKBM~L;72+G}tw|%u zC)CU7v2(gbDTUO>yMH`?5`rZP2V~B-X&RlVvrfD%5}+!6iScpf2l}7vH(S?eS{r1? zBPJ!b6}og?QZb%=UCKsa}T#!Gi)M znecIpIOWb91LBuC@ruL*gadi%e0BEc-HzG&A#uv>R%=7P0zW3?ZFr5IfR{%K?UE|u zs0w^oY)wPogXQhtd;e8XvJKyQc6+Ed={HF{yTf;<_o@U(F=%sGYc(Dd_9r#a z`9m{*P42ERn^*=Elu59rB(zrSfp12aAM%(CZuCsZ z8$I3CQIwA5Bbf^ofTM1IyZVyfmS){n4N{=fE-AQ<*Q%L-y>{X{F#a}x7V;L#*KGaK zsdKTjZvp1D5cd3+9vrdw&M)m$M7_G@#b4I9J70_oj%oSRl1MtS`vUsrz{E{S=f9Rn zd$l1(a6A8@BaZ)~dP8srACm{8)utjG)|>RYHw`f4dgf2<*X zV>=J8`te3GFNylqDc9a=w;yh)9kWbB=*3CK*RUlvEsf;v_-}9L=k>8zz&0&`lWEZy zP=@gt?eu|yVLn)>kjFs-UwzqAWeWlo>B`jpPXWTLBYcV+!3FFG}5qBhbXJq~?WaoAnFGvV;h zF&}@fH`$Ulvq%IRmQr>lUWM-v~iS z8j-%(X!rT&&DMF|e{8VS>79g4hcDKX2_fzY-v34amvx%YEjjS7&xS$UZYh(y1xh_u=}(;tdDK>u7GhY(5IV>si(H&;bB=*G`DTb6u-qlPmh)a4 z-d!f${M*kdH=y_&7oG>?=Z#5#Bu)S zClnu`XJi8J-jS-pfrM1P3oF+Nix4jUn#L6uacaX`)Zvb25?+3oMeu%+=?kYP@iwfa z`%vW(VB~}!2`$A^_HGLk5ES~#g!ZhWY0R6_L{Q4lmmJ%n6Rp+^e7BsokFTe~o6u*h z{_u{X_zX}k{Bcum(G^?#$eGCQoV5k+>;100B3SLzy&E|uA=hRg1RjzACqJz%-H!ldg zetnr8ZRWZyYC&20!1D2%?%0Lp#+5vE@yJxsb$B2@2%DeqKAd&}-6RYKY1NpyRZ`WQUL0>xh6q5~4YVFCLe2GjihONkS6VI;#oLU8OTh#2JKXbaG z8Lu^i-ZOOazo|+Uig2uPQkKEWWbyI}?n;)C5@6-q`L2E)5V?KGa|?SV)IB ze8IwiSOhC6?-lUWtp&Hb5P=u{y#O+m(yO%QrILV4jE-`1Qv-6=YJpdY7mt2&q5a!p zY(C?$Sw7L-hD{5HhQ)pNzU>;I{D%lc zf&-Vs+d(pkIR>96LCGr{@uCuOO`iKhl8Wv8)g7*-sO^xf3aezDPs9d8R3@b`9RMc8t%N3ql8-fX#}ihaGbK4+VMBLceO_osb@N7Llm z(%T!d=1hqkAgN4Rn<*Wt!N%Gz9;omkiKK}yHGQCe-sf)+vp)UZcGZg%yoN^|&+oB) zkTlr&4RkQsxDULqs--3Dg7&E^rS`iNjVfQ|@9}i}r)3DtVC(?Zbbq%BIPRZ~9vd~T zQ*auH)3}_*W$Pl?QM(ukT7&_AXB|#HsaqHZp1}we? z4)$sb^XN)*;gt&7<*B3HPJfhTt{@XqmhEv2tkt}J z@~o3%`L#CA?MK+#WR!YY_zmz<3KkAUA$J@NVcBZ8D*JZnQIlY!1X1RxMQ@HvR2fiolC&7XZZFd(|2uY1MKk#%qKEElBJ%K27Jvdb|2p!0n}wd~ z#874s$}bu#QH@38#x}dM2U)?~k#}vT7){>Vsjw=&>f)IVP~bHMZm`|+4cl>U6ZTl) zFRR)77?oax<*gEb8Hi_}H$AUPip<7|<#tEr6@@@Wq9}pUI-XU}1 zPsQl4ph{T%M(^OJ4|G9pcm*C`7H_W1yI%WwzFI%8w@60%v%S0bHJS?;5LYdJ+<`wQ z?zF>MC(9?$6;jLH)IX*3{bwzFjo~lP$K}El6m3W9tJFzN_Vobvv)lv3X&&~m&?TL) zpF<#HT#~H>XwGLyAY@Rq8HODB4KW+>JLb98gCV6nnQ#)Y&EKi_IoKxZ$w@IBIJLeQ z2em)Nos1zn;Ezz1+UmW~-$gUNmFYWhvqru0n7D`2CTyvnaw5j1xzAi33N5L}RISm= z=Dn)E=v{vq6ndOu0*?G-Npt_lzYx_WF8j2OQ>ZjVZlfv%R)W@iw=6$+RW&-rgwhHA zb3+#w-3<7C|3Yg}NGcf=4t*1NfnLsPO_veU6W@KS7DMYB$p%ikrc4}6`6Y@2`?;`X zYO-M>wy>tx4Af>}euYUaPD`-i7uq_W4=c#V(Ch(ZsN!sYiQ`OR8mdVwGk{f$Md(q! zQyflpc=SWwYw&w_Imuf0;b!W-tNmcL4Uujp-U}!~L&|Y2^Hfay;I3}S_1!YZzfnM+ z-~9ROGZwHJiOB+A=T26(`J=7DxNBs!T({F+~BEJT2#d&R5Q_t?Ap3j{w`t znunAbIS&i!mu7;zfA zqb5M%kj@O2)`i}MW&LgfT+kW&zx$-=+FZAYCepT0Zhgh?j1pUJc+%h3p01p zL-%GJna^4HBEUE6Ya`4+E{&^U0E>=_D>_;WENK`0P*aPq*};ai#HRz(E!T@8Q2~~*OMC+m4Uh)Sp04?yIb(n?Urs?z z3$=;$ii`p5a2*Z?Alp~tr4OHe5PlKvwu+3j5$^wO_R8{_Ul5?xm3y(b3*4JUmByQY zgAp6}Z!fPeW*n~Cfd+wZWvY<3qjZ!0G0>?EFGaW%)lc_91ZiyXL6$xKyslyV1mvhj zob4gkmptAqD7~99iifk@9?!dBBp<3FG_)C{?kdQ8n9}8!tuu5_EKf+(H1{!!_Gr*v z(7}ZtiD-#y<=c2-G?3KXmPy%c(v+o zRbO8!Gd`T%)}~===y9OBb*Tj)6O*Y2v|gEOg6Y*%lig2k0nkd<$w@_z%(0{!8Po?; z)x0xag+g@CLB0I%RwaC4V{TyGp;eH(o3HV2dl(jn^AGm^j88Fr;hVe|!_N5TjfQqp zq2Gw+g$%TzdHd3-Z(E7W2Brd4%D?rrC36F8atmyOj15z!srO%%K@{9i+F#+0JcP=(&{vM4ePIF&IRr*!tnrpUJ zX#;*d`g%I(EybmR!26M&@j)LFK{3Sxg-O?49kn=PZ}bgzM$VS_M8{(^uFxz|mZ~H7 z4{ugZFj1RTio6f?iAWcXfqkj$8zNJ66~@*B*He8)`sl%bE3NpJP| z>|5aA$d>0Qu7Y74oQY_ifek)7h_3g&+4x906f`^tnul;fBOrpi%&{H-6B`$#3E*95 zOq$=zATFW&nf`1(^xNzbNko{_aiu0ph7Cc3-Fe2-jA4upZ=nQv7+lT|YY}p2V$OM0 zDGk6xLXg=VjfY|$(`e_|$C{&x>>-J4H_N!1NetiBqM2{obsg!)40A1&$dmker>Itb z>LHOj&FY!QxpSol{~OmVg}2MIHw!h((eoC~GiEgO=|21MUy0uKA`$>KTNM`8YvgmB z7j3EJ4&(ue6|mH;zm@dHVC*n|IRqpOyIJDe5E;(=Nm26-Mxk2uN{e-?;SuR{{Zh2V zW|UIDB#4(GY`MDv_DF9sjm} zO%$*lSQN@41jXO|ufcmL#c$$3c(T<=A-Y`9J^m|wdXzcTe`ih&v6c4W2I$YcYLC8F z@r$>to%;&Yjt@IPR#m1hujDs3ip5air=O3(U-2rN%|`w9ye;Ii9dpaKt|~+Nc8T7m zWM`agOeeZ)@Ff2Yc6G-C^)c?VWS9U;DB=U2Ytq#5FXWVOcrX(09_QqTXL3asfnwUr zmw4}jd^Np_;?EguAMRH#C4i+&V!AxNUk{krz**l5^jI;N4zrQw)uRu;R*eAGzr`>C z19*Cu>4^w^+XJ42N!$M8e!S`bU3-05BhTdt$U^X(NBF_vSPnn!4Kmt|Olh25Q`bAxH2`=Sb<;3qncuXzIzM6WjEe6WX=RTzd3uz2QR&z`_1~M$Z%g&}c`RO0J zLo+u`I^1%DU+63QNW;&+)ni2GaQ07H3>Vl=>O!1L$A0ebsMmmg>`!? zj&c;rEnY#52Ih!;7b@JDkgj+(v>a3oWrx};KAjV0y}pTO%(N5oUh9xktn1Xcyun6XXe`?9eR}5^um0qhZGgYg zO61n!x;;L7)rzm}Tpdjt{9eaU50iH%R9GGZc7YNi1ZbK&pNBi&j`$V-%fD}AFDGkn zoKB`_G$GErXqiEAF6}2|V2gzv37a{fK6i(7T=O~MxIRJ)!0)pDmH8Su8V&=C?Vapn z3GF?!k;){bgR{deMQk^7|Jwp_Ee(7y}Iso-y#lU8>k zu!x15(q}=XK5Hb2lt2#Pd|Ll{595Uo>{^;5*Bm&57>paBW!kwK8gblF?X$J)q)bHI z-IqvD^q1!e0%pSD+hz?2^USwROsATFm6!E$(yEurTM0UJT8QJJGwW_79i0w4MGxtg=u<+ve z64dVP7ecQ+`xoR0`u+1}!4S|sqgomq++6i#+3tB4m7K)8%3P%uCz};r$SfkZiMV_& zSJW%|8Dqr=x1Vo&@aA7d+OenI;(SzxRI2xFPlK_>ZF#4NU8l4XJZ0lJT0>DbR`c;_ zY+a^bNJoKO(1lQ;KWhy5bvo(#k7AaVs5x#jq%XY2H!_?_S+cLF;Py)scDOsKhb{v+ zY}*}AbJ?Wv4i1A#s3)B<_V4UN-kdH%h{qm`_$@h{1|5wF`2dW9jC8BbO4?IjAu`=2 zgQGYIwvUc|^K5i}Z9Fl+B3fh#e*OCn-cR7E@{K?l`#rYzom>Ac$j9HivZS{JgLILf zl>^pifx&BP9UJF9+FawDE-w2lv88Qz;7LP@F8tLGJHv1Ei@`3hsCBicJ6b49wz#Bo zqs$1ZK;-2FES$Gd^t;ERzC(JOJc(H^g+g_5PvShcU8^@e8jY3f6gAhaOH@c_Fdq)k z9j&EM{M2>X?Jy*8@*B!Et|RIofu2FXl5v@N ze&P8HMCbm+Oh>toMV%~Xj^OAVn^(2W-!qS9oGxyhKp4n~HL2!u!FpBFRN>DbW6VP# zf3k@ckj zyKx-}RnzBT;6cAt_gp7d3}D9OjAmCcCG08nS(e2-c>aMK6tuboOKC z4KgGD*_|k{KM_#>|g4mSDHI(yh6Nq#Q$y_Bh-zGQeF8AElUZQs_>OiRYwvzh`| zoWl=t9Dwe{Xra57kX3&WBpem+)Qn+)3(YSg%>RSSOn^{m%!^1ue4)0^8g}vZwygGu zhih9nv!*UQ&W{l{{AgD;E7ubiyti*M3*bvpuB7UP$0|?_m4vLi?IH*q%cS(dQFLOk z<|STDFX=CRM>gmOvt>OWibzv$^A#;=R>xXg>ei!8r|EmSr_AMg>&F4ZUJo56X%OzC z2?Q}SyIsr!JUF)IM*-#f8o^LuiuzxSva_xevHWgpVDfYs^5h=zTx{&v`+aJvg9715 z3LbGj9to6DrPm6yqdfei=Mm$1T0db3O}ye`2i=6|NK6tyy-tC=FSG+f}LZ`KqPM>yJh*8&&^ec)i zUL^Xa4S(J?J;_%dU-Y-k*6Xg3EIn!7+9%PEZs9k!6o>0S9{oM_!VjO-J05l7MU&(@ zqp`h7h{j0TvKi0IoSEeg$&`e#_M|N$CvonxSgYuNpgOzt0{;avZlscAMd0D`EoTkGd`BL7PJqnw_YL*fitTg@D$F?8*$J|2nP4BmEZ=X)sPJd;Do1rf{ zVSP}BQ;nts_GfvF3<`$t_7bw151lCk%V_mx{^}Nzp33QOp7*`HKihqUdj>Xu!SJZnkYp{ybYlNX9&^_kIJmAeC3F{|GPbJI|VVa&|vohZm zV-9U?Dr{Zw=g^kRy8faUw@Lu@z~o`ZwY`lrb42mN>gQiqqPC1zYAon|O*Gs6w15u@ z{bvDkA9jN9d5|FOJX{mIT$X70T~vcjd1s-3qMf+kz&&k&rDs`m%4f^epG?ml!{cVy zU1IIeQH_@oZ~d7HoLd;kAIE2*F`=BHf;+~SZC2LX6a;TBM>+M7!$i}G`{;w94348`W!tu9;5n@1(dt0wZ`vcDZkkwb$-u zQ$*;tG5VKa-$dBCm|+%@^=@DYe+51u{>r01V-0l~k9>IJqGQ?n1f`^tG%t)BYCxpZ zirQXG-pn|0Bq;LaSI*TkJa{(q6>lko{0$PY@VWf71d|6;2W z4wD}a_U^cgJL3jdo&B#{n(J-?%}Pv9Ggg6c&{N+@ghlP9!s)%FZS2kYE-Ro~=p_03 z(*p)M$n$*4R*!wEf6!4O@WidO;Ou-rcfn8pu_r=5BU?jx<6R5rz}nyToK++F(B-2= zEl+8ZKvi9u!7h_Y9j4g0<~zmAPipMdSJaL}`DPB2n&gfc;sQRi^DoLG{1)kq>$!Y8 zixEz9ozBtu7BJI^v;@;zW>`7)uE&Ri&UOCr2z@+0jyr_1DY6?<=!C`vL0jVxS>-+o ziXPhUifXqFd1!zo7SWZVet<{Fi+xUs>K!ENyJ~w(O`#*n_1@q2)i@&9E5UxMu-)ep#j=derZ3dM4)eYp>SVlt($&H%KubP6H#jC$88aqWnno4xoPR*Hgt>W?WgAqd!PM7$f zP+133*1F8*Odx3IwCyJC1I7z3Hu;L|#{|b8U06bD6yMUoeOOoR=%pX%M_abkppQNF)aKHj(sX(ah`2zm$ij^n}6 zP-&;UOCQerm^iEv&#e^*#|?(JeTkj^CS!qSzyg*vWzXG&i@P>PpP04S7ov?`zU91z z!RORwf#n=#avEbQ?AJw=lO5qPT?IkK%zcH$f(@id!<>-pbiDm{5>>F42oJC8gdy_wFN?=kKDy(JMuXMs zm+@BeiS&nrJ`Zi29c8^H!-&vgL>(74&AP2W>x0e1 zvv}Vc^_&@zTpg}5P6DX|C50d+5@6@cR@UCf|CpN_b#-^waWWv4`6rg7rTpl=)nl_x zvf9~MjsDa%9FlP)m;r8>p?Jg({y{(8e*|Isx`phmTup zL&h9;tA8KkGOWG!oTQCW@5?S?JO>zme>oDw80YG5uhgD#vTuTbto~p2-d@?dWw#Ck zW|hm&;7ExQWe)v7eoj{@P?e;_3}luaNu)&CmPN{DktP1PHXKZhficj%zH_gWvx7bF zJ>Ony&TcgRf$m1n1sZC@5}a0*i_b99#@@gEuCk|mTLvyFITLNVKk>u@=B{3U5(aa3 zl8@8equ~}2)p}OtrRJ>pukz-2++4@G#v<#yllpG#L%)*7_OUAo^?9_>+G?GQd)gW0{*UtjLH@jftu($V;V#}4F#Mt))rR}_Pf)FQ|a6HRdj+34MLuWXDby0LKz{!o? zV>-~8pKufBc1xymhR~gzShx{x#ki|R#1emW#mcAhqn{4lGY+23K;ZwBg=+Ab=Yn^h zynuV1dr7h+pD;R(;2ts#U_lRx$-9g zQxbycU_oAXlEoz9?UTfR1&II>iVj#{=99AskWXMCD-a|D!KjEI`ea0x!Xk0_irIc1 zMYE#^PrQ@-9QvRXcn*8QVnB*OR98gou3ssit0dVL7NcUcTD0xh>-ZN$*EI1m5A8R-d(KW%OtQxu4y1SbWduJm3glxZ-?MEc1}k zL}`kXcgp8l;~7o+%fdld;fUkHY1^@)SnI)_II3+P`r-cmaQ+;F&R0-c@(sPWZLb`@ z*2`;|m#$(}@Q8zd!HSp|n6K~Fb$XtC&bQsHmm<38fZB@2Br z%B6)gopeX`;>aVa3Vt?iJ*H0bUhwbp<9Jd^%taJY);CR%weIHDk~6>eM8Ej*K`+E%RqW%)>j9s^QAi8z zNLNt0&=7+cbi({2v79wNpkuCJ+WuVM>-t#$_-2>wp10xD;hetDL$L16Ss@orb@fEf(Fy_GIF0-P(Cg{y-`(zyX zAehP!T52IdYN{-Ragb$yXYkkEjf7Nl=6DjMN0ckzQ|=LVJ}=kzB_>sk8UM7aOx0=a z==2RAgvoob+`tzSYgg4WJs@b#Yb$g3uI7f73*KYM9X4i;F<}I`U@HwZG~C+li!Y26 z1AByjhbhl=W+RFG?4GB?-TYa8$-3~b8c2wo7LJkcgsh~qC2DAI%I&Ze7vmFrL*IOs zEEs=c+9=J&yKo$}Qi3*$&l$#JO_G&I4`k3dDIZK9MP`xbZu_CE;vOmTA!CkM9qxyciV z%NmOAr%M)wZaLCoE~BEbaM3n|n53bgh5_bwfs1}e3k|!lA)YOdt}!UxW3Hh7C{3_` z;T~hamW?;O>D*A_4S)Ku;0A^XgaIEyqQ(yOm=f$j-3_Wmn3F0EsFak22IfE_v;v(CI~^hH1O|#IX)yd(uU>Sdq-T8#C9Q?hca;**E$n+CyzV3 z8axoZ1rK_l$Z=NYh$nckL~sqKllna&VtlGp^e;?n_uCoFIO>P9{-g&!F+*{xyM=GH9Z0(u{bz0v2Oi#n1&RD`F<$-DxSMIeX}T5|Rt$ zXI0Ek{XoV8$|k$|C`T4i@xDyytBk2wARtYNG2U?@3y#hg<00UF4W8J|pp8f(lCUAD z7fSS6BWa5*hm2WJU=s2In&d@G>qIDPrAKwflc5o@ihIk3yF1hek#pEkqZ7tY84C## z;P3dpbS|W=kLL>>#CgG+dp;R|fmiz6&XMB|V}$tyZF{3x=`p_?OHcGU@JPim7jKdu zOUB&1N`rr=U72vgn}l=Zs`!HWY2Oc8V|e6rX`8gMDSMT-Ot|(q+HcdNH(r<`d!dyy zrsJo4oFVcY)B3uetNuB@A#^$qaqThka?j~GWpvXg;1qG%w^M)o*&$DV@Z5Nx(7i# z!EL2|dnT8wMjys%w`_rbKgSFiGi`InC&p?c37Mz^FV+VzDoT1Fih#wU;+Px9lu88J zh9oAm#nMMbS!&8Wv^38O?>Q;EKR%|$-q((j=gKr1wert<{2`fkt9^$o6{1%U5%)dWzTh)n=Jca5ziRwKKAmCBYpnutrMq{)vu zfb@HG(D)wh9FPnlh-S>(rTqmQzdi#nhNuo07RWS$t8>*B1;;5#e@%cOJo7>74BzL+ z!bjvd*uFQby)uCt_L4rXJdfxuJNGTenjty^X}O$}BgnnNVe2aN>>#`Whe<=^1f3dO zHBhs}PT1uY7L$m7WJQWYU+-vNKy!A}DN{1(iRxbki1%y6 zSIkiW=o_l}I}x(9p%a^$2Of{AUclJRVPfH_gW;*_BnwG+fW(ygI6wjmE2sT@En8Ii z?_H*WHVKcWWPUFw-RUV9#02ym@`LR(=I0U#z~%Vf#?pkv z$6mRLjo~<+m*X;b9A7P-z1;`yBb!{%!sv1t&A)lU;?}RMtzxx#>pCzApk8R1)^GE0 z+Pa){ana%3`LB0xGI2gS9y9IPeDbzw_nqcbUpHoomC{#>8^gD}(0uZy!l`#pg?~OTM2R~y5yvF@L|tR*%u~~lRy33XUR^Qt z_Lm*b6n^B2z2LPATbP~`U(;`MvZp@}A$ZIpLrUyG=$RLX5XHnsP1A3S6$5k7OX2?w zedrPRsP^#Qo2pS^Knp<^7nnO-bb0z=F|bF`oN|bNqL$VYE_1z_#RQ#3&%Mu4VEa!6 zjw%9;o+W%`tY03j_>X)p$PTjUakL_Y9v2Hg5&CYfVtaJ0A*bATA(y5Ob$hZ_bY1=Y z@FJB}q*J+|9t2e~ZREmd`CMTm{aoMY`dI+@ZdV(B+q|VsuYW2!1TDuiCySLmnJlvu z8xYff4IcMaRJRH1+q}lHY4C}lgQ5>#K^c>mT`jxI@W%lccSf~*3%m%d+}1dKmKr4- zsVoB6LJ0_5$yN;=wS!3GK3qf)8(>GusS6BBgE>V6*=R21?4V$9@D)i|O``ttXLdEI zLln&bnbqM5jYujGOo&pAcx|CXDgl5a+x2sQUDkiA6Q0Pdk$F6?JoL5{9MesI zwbB$hwoL1NX9M2S27O@C{W>BhHB+8AW9!Z*^Pu&Ye8o+nL6e^McF|S}j>~xBl=E-X zKmCBi*cGZj%Ag?mn$|iAqGED9O`rI}3GPx==+X%IQXyvu!Y;V)!@-Qrcp{6&*pcip zF6FQEH~7L`Cb1cq((!M)PDcu#8ugri3LC;*`k2P6I4f#c`coWB7e-Z&hh>jOAM!dC zepD3S8YdIMWgBnDS!f+cJwAvCQx8Q;^7W_ZYBKOCb`R6%$MvGyrtpbfL^qPL0eB3( zGmyl+JyBF0{h(|m8 zcON6+ZYa7v!pwZ*9XC`S<;#pqf0!r#^u>ykXXH3h2^BK|-@G28G)!ZZr$7Ug0rpa+ zA3n)%pP=!DsLeB<1gcH}0gXLFt0F$t3dufdSImt!ZVfXB5M|@L^UGH@-z@Lm-hoD0 zY&%}awe*w=WU>8X1Vn(Gw(OyQY(A|R;*<&&8q+FBGoYA#c9lYRIw%{kguw^|Ju*%`Pm|zKP{b46xc(o^gC|8k3w^9v0$OR~*J)b>95LNp(nIhvQ67 z9QdqTH0+sx3EuQQ?Rc=dswHR)C~(jd9NEqe%yqKk8G`rcS2(Ynn@A#mr96r|Hth^S z(@cWVZ&z)25XcakGG>>Vatq2#rMiEMc6{<;e4W8=*en6Bk_m|>)9;_`q;L`@OeQll zD8%g6#OPR>To7j~xH8Sj@MK+S+xMzJLyPK5X~HA4M@BCKbkZs`dwC}G@$IK)^bjZ~ z(aeE^Vd{rJXU;7f#4h`w0p?9urhu+yD*gT!?z=pFw5jYP6zRjF~}oc(!Y!BF@kFtmu@g z=m(T%8CH1_VLSukJZ>dBkh-YHonXrP72uhiO)?LedbOnM$II7$S?F{ug$7}R-)}zP z96Y`+JGHT)0S_F)>{O}$T`DAknWEq8x$38sFkWU?M6$=@D9>sfcIG_tZ1Ht+R_9K92eU@_l&o zvZ^t)YNHvhz<()!z01b?WsAszLH8{{QpjoD&Iwc51T z1uuL1J};5G80?d}yp_Rxg6e}sD~S=#efPa3`oNHCnk}+_5*?K)z|lt-VX`-*k6m*# z9vl?*Fk$i!iD$HHWmX9vFk&wFP^2ECHVmax{j%m>F@7#0CI=S!n+2ZZDgTsmv3sqK zSny68RecEQ>kb{di1$@(^-_=Sd4KMvKiBVk{VV`{v#TQh9&s8$>%Cud6OIBcY{CU6 zowf^~9aPJmpV^fT**zEcs(wkFZAv1A%!6*5$yWpuE{{r~ zJJ%ddoZajEB;gPT$K(qL)^G+BK?W{3M+COUqy2L58*t(d6QniC4TBkI;Y2Aye=Xrn z%tusQQ3o^Ivkwk)Uwygm3J+}~ekuuN3^)>OWd#|3`dDXFnGn$vdnP>C6|*<$uOJ~w zH)&Elklf=Q)pruEd?M-#`s9mele^7=049N%^}gyL(tol|bYNr}!vE$QlJKEMO?Ix5 zMr~(0iCTM2vKxej4T^n|2rYC}XF2k)XD%j&xg7^bcat`T zPX{kBGGjByZ92!_^;7V5TJJuJobU*3!k-V>E(7)HqbI9B@P}=*4Q?F)d?z)k#DEKb%`v)_tN&sv`QZIkUh_@I)=@V;hwb61 zatpU6q?afwnU6d4RIQ_h2k zI<8_8l%P*gCvF)Q`%BD>n1o8&jhjmeB;tIuJc>B1RagmV2(~)0yd_Js+c$VyG8q!6 zIB~9lP5RZHdU&!OCTYh>7=C`veEFmf3>xg(?iP9gne`d^kp^_A1}2hVBw+P_)jXUD zi!Mft{=5hBvC=;~)D7&(h%XI4#WVa9W|Oi&vVu^dyNo#IFu@lzc5v*Z@#RO4FFOaC z2&ooPtB5=F3L?WILXb`|j7hix36IEn<16jZ)g~1fP4pN+b*F8`#elYkM1{s^2g*=K zpH=^YbkT|vGzR%KFUkVy-A)&Op+MIoyIDDu>!OJja5SD?*`%q~dEF8!zL59?SsBV!N-FkSi z<%c{I#!)uePw-zGB6Z z3AJbK8zXnEOvnfveKQ|_Nm=zB>h3tltNxDK%VP5=zD_rXhVcouz#;GtKkJ5Rx4FS1 zOgcx+Y0E*>U$3|&-l+qNVW#*kHtL5^&2$SouUw;QM4#v0`|$II(f)oLUw%%=+v=(A+ve5Hp8f!sx{ZhES{V$v{w{uhu5WeyEC75u1f#oEAmBO3|~up1_^O6 zXe7b0#%0X+WKd+#Tu%Q5KbZybOyPk%VWPuHpQ7ZR=vW*D&cqKixWnUw854Idu6RHr zm(DGrnU@wOltLJP&tJuiWn}7_w+CS)4Iy}P61gHglTw^Z?Dmxz@#U+wFA44bE90Hb z3xDNI1(QMU)<@VG+XRey%a6Z+@mCER6PP0FoxEt2Zi8*wkCp#(&Rneits$yE@)SO7*FkB#+M-xrYCDOl`>f5 z>7a;7sv$-`&p4wF=MI|LKFnbeI+NBEUdA0)-~eB?V9c04&fbakwz`9}c&3D-y)5zt z`>pT7r|rvzPct?;x@{*3-pL)>zCr*brD(QXf!C^F*=yy zIsh$i@&K-X-R~LREB@A22OSd=e4QplyZNlJyw9e|WwYbb?Y@4$`SVSHF8|o*M6AjEg6A<-zbyr)0>D&_-~VN+(oW zMNie>{yYOZt&WlfY*-WoPEo;1KH?aE!yoknsXVI4n4kXBDl~KEcGbbP zC&lJ2KALoiY+P?|3tocr#j0kpMt!$iifYANuk$dt%mEyZPhbbO>#xvOB1b7hv_(F% zA;rT-99hQQsQ~z9*UtjL_q+ZP4uDQXY@H@waosh0Ck3$nq(6AOjKigQzmac}sVZ|Bz9wlQ zR`Bvg06G!zPdlmS+tGC-BS#V+E&r0)tc5}IJrguhTIq14Z^EHDZ0GhQTFOa%0{1*+ zqqC!>A@SweEj4QL0*e{KyNK`?7$*6v;bez@S0+1EQP1<9HIE3*yfta#&(kzxtduq@ zv{av=Oadm$&4n|N<-1c^6Spcja^*8SnHl|#f}%b$0g~W0*vBMttn#RMcYwYo#pzuf zsudQ`x*HO}hf7bpRMUOUFkN0$@=`PfrbA-qqNgK-Uyyc8G6n29CGz#MIMC^%imYJk)q9d+)Ei z^OI7+4&5h{Yq@#oZTw&NzjJBYUJ63*@aFiq7hCg1#@pSmHpLftomw$CEZPZucHSbV z_0@M7%;9pS_BclYhsMY2bYqVdf)Txc_-duRni0rf>ho|=ZQ-;%_Y*GdxhK=nhUfa` zdK>n1Q!3?6hKE~>S`y;E`+UE)^*eOe)8Uxf=iJLdLls)T+YabjWYx(tdgO4^e9B&U zNR=J@sPFoR^h2ze1zZe>XK(*mL`d=;c!a=I*#N&;oW^m2(-Q%A=VV2{9N=hwtpL>5 z@~Z3#sFq|eWFz;O_X%tddGP_P*1P!N3eK&8MMg~C(G7G0t5HjR((w26s%4|Ud>&tT zi!TB)$XZt2$o>r5dqmCmyPwNz{9M~ZU<91BTDbZ++4P%n)%(WW6PBDYPko&0zsUu9 z0BksbFIZGFWAC@A1pHh5zelrwpX+zMeii_}*;Nt$(0?Q1oeW-=WXEH^U*&AFyO+H} z8KIM?U9OJc#&YafPP}*8GX}3Y2fmUM@eG(ezVI6+&r){ZT4@Uc&Mcb;S7W6eSI^6N zq6-J}CgpyFt$6k9JQ|^C;Bw-=ZND5}p1d{(T;t5uZIgefy3n8`=~TUc-$o`L;B=9N zfhdwyBIIpJ;Ob81s#%@Um}bVYIHEy=$sNhq1sx4`O=iH)NGVa*U@QR@-z%f?YxE$C z3o6*zd12BiQ&fZ0yqT9B$0w0711rGrg3B2_tn3rFqng5XyYx;fG`wpV)En zW`%xdw!@pWqvZQyh9oh6VeLww_#UBS>th1?A#SC8OJAad)hps>-d{irDJ2QGE}@hCf#@e|A5_2 zmxjtrpD&)_xQRNbj zbmfNk`C>crEx~}fS&fHGkX1)WlLq9B4;ZNAZ+idngI^^Bfq>lY`)%~OC%8j07o&v< zvTiOdn;<#rv;DfZn-HCxsB+>CP-GS+|2<%4gnTD%h$om>)x$3D5a>V1A3sf4F%_Pf zF_ZsBN_UQ^^9V(MFORv%kds?YW+A-LNos1FI!ne;8MkcvMRVt*;Ayq&GO(b-QQGEp z2`z+%Vd)wVg3nl(i2k@MBVD#Bl+_h^DR^y7ljSnVW!X+CzO>DuqY5$>SWAY)oy4fE zC|$ka!3Cxr7h9U>58X>`m-4+9uM}tX9PqPPxS-VjYy4b)-|G5V0Qh!S{-YYPzl=p( zYCATc^v%@uOpGJ}!x?t;uycnREj=N9eYA`OL`s9?1T9YBt(^Wv__h;b2}Fr=>Jj(R z0@BAFW_5DvsdSGAz#ShfNcgUnQ;$+wpR6Jj_+)&>(@+YjXu9CRQ6=VkPv_1LlZd4w z1HC`hz!CO;uJN2-A)iQ9#+13QP`pCCd@3$La3t#6mo&}5O9SmK-du)Pgx=kK#zA>) zdTCQ zUp&ioZ(q09`5)FVZTF=%zQ^C6YkgPv8-}*sFwzBokvBN|@2_y{i=|B&28&}TEak-~ ze0Q7Oc78f;(8gfF<1E+jE}b2V`-_N@kV)DaXq4R z(<8KhyV_NJ?sw?yjnDpwYy6R%uvolKY#yv-3QqW!ebd*bO=t+GUOe-0d(Ff`GA5#7 zv4A2mm)Z--{fjI!`G?;x_GR@-`w?br*;Hi5A0kw(R@wU%GO)NlTb$-NTL!OQX{bru z;QM4+L}aCA2qnA2B0SI|ResYal$xg2pYK+GrLkOa1ER<3bpA!3Vc@mz|!6fLUVmMU% z274f-W&_=hl^Y>d1l_yhZ{z3sR@cu0!1ufU>rBjpFI-YH9QO;47jf<^i_zM5hXpTx zvx|Fhp)K~$_4!QrE3EWAa`3_AIuP&%^56ryJQypMI_%atm&#IguM-=&v#(sweZfoN>p1)S zwhqP5X&#Mt|21^snT*5IPzFZLQM`g{D;CH-y#Kk=eE_@pL+N2U~nlFaevXx5t z4fw&g)*6w;TETrR75-{`kMRzFIB{f;d8(afta82O;(Ct#j)tgiW0HG=rMwwChOWJz z-USiJWcx3=U5aED+F!C|k}a_Vwq+8rHK?>P6G)&ner_?v&+uncn=kohNSwfl&TuD` zYg^(w+SgRyCvRs(Byc3qjzw_+VdOOaF{RDWqdV#232M+W9ep4v(G0bJJ*~8hX^Vek z*LsfZjQ51hVKyknG}7f*AjgnOfLmegEaHO&?qfqaRz?X_nAf4jsF=_O=68$t1fkFt z=OW$qv*IQVzRI+Six#Y~ib6vW$B~9=7sg=l;q=k3{qTrvl)c zT|Wx|-|nivrrDK+w?HC)0sEe5_35lMw5pSv(A`7yb5H(Lo}rz>-${Zd0^ z!y!aTT)gk+ax#om1}ph5@NqZ13u2u&nwp$#dW1rvlQHAJ9(mpptU=FHrtNC)SIY5# z%|k$2_+?6b+560ltVXYGmZJ}klqj|szJyg>fxz>FBBKL$RIHSL-D4K;r4yOf1-x^R z0qd*b^qA4~^n}`u%w$IOf&`DC0KQfSM8&)#psnY~MuIRH=bqq^ktEC<{+YgNl}gNH zLbMl9L2bZ>!FQL+iyfzc_&OiDtY>)5&eVzU1- z)E4U4Bqz~WyPzz8#TC8YyG_WtF-i7xD_WeBcvpy9p+ zVDd2jzSurm<|@Mwx`if_MNJ#ojW4B#JF$442kaDC(`HeB`dkmIzxbXOQ}P@?ATtTw z6$5?7yBxneTvI!rI8f@3BFtaX-*BvlvZW_iK5C^47SS`p&eyBXh&L&k)pyv*`D7LiUY=vg&Gh)wp$DaXbHYCZ7Z=+jJ0(45Cv^%&~osqT^|jVgl*`5fYxot8asJ@UqVB!P4nMP+ei zjY>E}7?2s?{2EO7k&dElZ1I3N;?au){fPP-(k+C4#^`Jb&&QuNpQR$Alt(rGbO;dp z(A;l6|KC>@{anA>^|Ju*{jR@y|4jNciNUztjz02zB0C+wgzM>Z+us=|>iE>z?X}x+ zXfigF4`8lI%&H(j_QC|9%xPJQP$5C&66_ak8lHACn>x0XN@;)_x|lY_@LzTrfH@~A zLxV$qRmwfFQwc{n*9VKeb9wH@ZCq!yU!fN^$@@kbdetW{d6Pc+fLE^Px zCfg}|9eat|=@MF}-O#e>(+L70ts5oZ?3BPBTktY|W%EMESnWl9 zVH4XQr7T=ThE`?JN5?E$y_@b(9P!(V&qBs``y(Qr7(aZ|lNp2Z<>XvP%0PfZ`9EV# z3fIl#CqmIyb;!o-Pco^0j|kalUE}2YpDp@Xb`&Eo> zhED@1nNg4a`{FVeBS3S=I0RR;L;T9q``(}NSIBklRV?z2ZJI7S-XO9?URW`Ue}mz{ zhF5JN$9Ke(i8E+N+u1w{*K6T9fg9fiMuh1;HX>{yPjn%Vk_GJri@0P=PE-AVT}(mGel_$iIr8>swv7!+1Z}?|c1aggA|uu-hgaVeV+0Hyj4duOyW-58iFpy$szY z)BWQHM&~^%x+sI2RuwGsUe5CMtGxr0>O3Y@h;xKVCUC~g`swJ>*hh96vR0Fn|KKQf zPiF8B8(%Q5AU{V^GHzwZ>*Yv)>)f*(teoed^$c$jaPIaj7cZ-mEh$X|zQ}DR77w1O zyg_MfDt$qEvvlbH@d6G9^*M?t8w;%p(aGd8|ww`YYbu zBW^@Syk|lmAo2twB$6m_Cg0>K8(uQCjL~-^Q0=3?VzNYk`Zv!A#`WALc%~ow2JBbGw#L+PXn(lpz?3_-z~XO-`do%S^=Id3RZE zGkUrf+d1?e2|gTukJ901jI5;%dg=_^vbKi7ii`5L(fRuE9XhdOgRz!nl9~>LEWccnX^h24f}I9`tk(LD63g`h$=+hSa#qVI zg;<`O66fe;j|Y~qIhR#)o;)&q)mnQEd>fPWBf3b?w4)K7jOcECH2ze1nA)SqoK@qGI?}hc9=w%G2gM<^Co>JxOf+9 zzKrPweSE}!GWZMwOu!~D9!;Y3ty0|`^er14^%6^>4b~(X8yQKw#)qf|={TkpwmY$V z&H_QPjgI<~uq%=Tvy|2;4@lckK9xP*es*t0w?;iAA+s^me~jhNu79!FuD(&66yI7j zIEQ`da{9R+bNVCnJp{8G7Q8pUPCJP$k@k6}Fd~+J4Dcz9!WSBSKw5voQ5(9*Y9f$m zg2@^!N){3nhV2#8?{2=80Y0Q>yc|7o&paG-IVxq0y&4xXj5d0D@L0!EyA_Q5E$Pzt zu*v1*jgKRsQa`WuA>4FY(Pr6YAbQ+vRWHE{linJCU$_;;_gCoH7#3(20J#GMV`D!!{XrcB^7w^O zuRGo~$6F}Z9&h2|I{bFXTR+NHb#QQ|o`@rVF*qS{h?D*GZ~1sUb_tzsC?uh2b-p%w z=p&Eo6D^RbiGqeT_`s_ROoJt39yC-ie)jcW;^+ES*UtjL_q+b`7S{1T05v#EfKp9c z982E`OXzZ(LQbMHljD%Sgc#xu0L8xVQueu*{u#JSV&kI?o|D{duB;+ZIL5SI1D^qZ z&Ag#u_y(@#RZdDqd_!Z2Bw84|hePQagQuPq11ELDL`SJuEmn%-pLS1Ve2vdWUQ+^~ zC&v0SSe)o<(AvpBMfkA>StvoUeGu)QD0!p5?E-$aOz>GF8~BclPU*{v_yWzYuOQT4 z7&d|ZRbx#0BcLldj^MKEzYiD}F(2$D0ViJ>B{na0Ucf&L+ zkaKPaY=)JD>5x* zq55Yh*OD$_pP(WAl)nx`e?>z~M|@ol9>`i zBlO1WkR%`cR_ECSnlI%xuU~ox6Vm$q{Vd_dPjACsdyJ0*}HWzWHF;{E6D>NX!KX!6(D*@5W*+-Iqv($ zLeN-zrP2pgy^8c{RT%vW1MzMU==%iT2|L-W&Ri6)7irVKGFAp&yI8%kx!I9%bZ{E!r1-dJ%H8{)S2Qdh}MPHmA8T*r&AwgNNKY(C}Nb& z2j~npGIDEbo^|GDQHR_A&O2A?a3A z#*UaOAGBR6V_u3~RSt3={YR4o-V2FO#NWIm%Mw(zAAt;i7#AG3h~DL*Y`uwLue!7* z|FfurF0ScHHbA`Hd!bEqJC!%KKrlSAa8^SHorCx+U0@60Ek3_t4}7TL&$n8jmyg&v zCQ&NzE9ZuIplCkZT3N)Tj8rhWXa|2phjSb>{S5{~={^a6#|x;i&kT92I*o%3`UN%lh10kkygUd zeJF2i?D>F2x7Y26-&Q|IUmslbqdh_Y2o}|e;XGG=RMffFe8s|(?KvpUpj&mNACRnM zHa79W=sv&N`g@N{-Pdub9vO&XZ~9#h5H^q7l``)rZx=!42Jax^2%wTH7}~lEqzMV6va1DNH7n}iBng-V zfoa7Ju2}T!^nMF=QQ>u@e3?X3w z{W8%v{n4KN*h}Qmz`I!F3kIT}&nlmR1z`5}O0@+TxDlYV%Xj7i8{qqo*6CQuzu6pMETKI>K}znI4{*NBJyvUkyyzB! zh&c}N-k-`m%2LT!f6F10@H+??kNA_I6;kG3C+oKzR&{&PEm0ct--x5>Z3xGIuIm01 z;ZtEtyXJK0FCQ^aGaD%4WRHwrQi%e7z^4KZ`WpY_nc&E*M^#z>O8Bb`XQVpPxz^eyope| zNiCiRcWYj{pcF`kD&DO0%kue|bkrnsUpYLrRkC8@#+`&3nqJhvKa_v3WGR8Ys@K$n zFo4>uz%*VaKIyvv7C7bo4w6*Nz>^g)fmwg40{Wsw)v?`2z;0Lon9}a(ZwXS)@0(XJ zi6%SPO^5(bbk>fE(6POLG~*JzPk2Rml9f}^YJ!zA-WOJGWW7%|VA`uZSKN?TDPyq% z1e@6tTyaJ01vwtuPK%b?B9Bp42mJZD%y9VVyB82dk1|4z{|NpVLwK@L*>kP9XRsOo z03ZNKL_t)mZYnyt+D7vQWB-cw!#B5{R*mo4znBRcbz%xaw5(TuW)*Lf8XKg64u8yM zfw$_x!4Ff`%k#UKO%E})+Usp$<&z#$-^E{Q`y0+$mGeYs(QXpJcaHpC6Om z6h1M{vkjgX`6r8rGR7REDB`@F9Y0WI5@2vtX*NYBhmbLra_Y}Y!o8@{Fsndc#>vGe z+4$jNxaow9tFb|UNW86$ls3SSXzwc&r@YivjM)&dx>LyMp9m zdy3~t$h5T$#<%@{zEJUV{f^hq0>F2>D*n16|30$*+t)aM?}>n>uBDR}I_&W%IL$r* z@-@gQe~exM4Dq@;X=_Nig6>MHeNw5xDj1mVJAvZ3ERfCf+0CuxWu>V)X^kqDkV%rF zWp@}qBzA>hf#uP+9F*D>spWuw}Xp$)m6P!E9OJIs=qM_MjiSQKA+N1-|E z6b_%8gD7Y1V*Px6d_46<*D;mAILAo&pg3VNu(PLsk9aM*_um_Sx1H3}5a*$`-O0_K z#cm!PE_>0taV0Kl*Z7JrS4N(^QFz=0veyt8A^i^9 zxX>AY^6cV0h8}*Syoy8BzT8TppU$%J%c*@z-I=>d5BPH6$UbY zSwqtrN+*z!Wkq!7ZK&(~nc=uz5+p%jf~|OWCSB(lVPDbpm(W}tBoQau&HAC2Be$y*TzsRhG=2;M@QC-h?M+qFoX1OPIbq@Z>BGFrmXE!s=18%l~Wo zzdOuxPWU}L+5mJnuuyVaGZ|N559y(QyY`eHc51=2W*p>)!h{ljuJ3-@Y#+C)TOQ9udEI6VdUk8^PGKkrgFUSinx`_HP_(aHOLN;O)PwWKx_CS z?w#(W|FdNIcGTe!9Z8{~M8CA!qL$uej30-eNk00#c9Ofj1e!23)}=T~!vl6VK^1`R zXg{~Uf(K(n^HBTB7&`f<{yg)@aME%0Uc|EhU{%5Blsq-%b=Da@7CiLX=(;ZSQ&y%& zqmR3aLyP;a$1%d`Rh>QPk-w#X_w>ry8D|?Mk+K8cNnBagWwsW}4)Z#0DO>?-xZ{iJ zedHOBFAIXD_sLg%_s$T!<@3^_j8l8bP(5KKPRTR)O(VGdag1-le#VXO+nwzjJX)f{ zLmPF60#MuT_0CdSanA^lv6U>9!^ND8SNgn&s$IGk4Sq}|0m|!7csA~Tr{@>^l;3Eh zW~zL-`bXh4L44wa+++o!*!(A4-}cK9UHbCxp*#^0@qb3e-|k_4uHX0iSpfKES5^IW zMEvg=@lWO$K+#bjj&1K$Xwn|R^FV5h+o|Xt@%wBR4`}>avS)q6lR0?(5{MNB&-{WA zlpU1$^GLc(tiI<6z%yQdmQiwXl;=Xl&?J*xMuG0diFx_`@N?TN)dLAhsD!%%n?Q2E zi?*3-(lG(pA@skEWAU#9Vm3!K^-2EDYo>hemCHOILF$BLc%LW0h?x`~=i0P=MaC1A zU+-k%si?0J7UkfGf*it2Nc4HX@kaq*BWe=`93tu|*)%Lm7Ki75OQu2sM&E&uc_J1= z43?e`&BeML8i9+-AM#AWOvbDTKVvOJqwS8_n&?a)En{7VY*i0)6oex^gSSqseWxs( z2IDvI6u$smn=ULE&f-kE?@(CEx_u708FJEc!ASw*{)393)dJ1Z$>q=#ir8BE@>nE% zMbn%y6YdL2TQ6sSu_o<1--95CK`vatx$y6HZ?~r{(4P&_$HF9WLQm1ZrN5;*C?sv4 z!+Tq&jVIDk;2hOIc%-ys_?SzF_1U32+IPLDM0LjSye(YFS0&|$CwQcM6BJBN(g&Xn zevFuF;o{E3@m*%-I7US633ULc^u-ok_`(pnlf8V$@Ij7$bfrH-M*xu;oZShA|GmC%&Ls4{gKXTOhhV zU-}^ko9@)v?|_*Rcxko}cj-2AIP6w#TsLE+{dIxx?waL(iEjeZqGQsG!rbfuT))rtvjFhzuKb(G`tz#zAGjMS z4)D73Vu8G000MJelYh3C&)luKIF)g@>zF|=|IYX6tjT~S=RHYNzh_CHJmb!F!?DDr z`yRV{f~)vZPVT0JKWt^%NN>0=F3CYF%N-=i*2t-U?+O5Kg=q@F5~b#)1`H%TAxjpF zvfV@%1?a5r;b7#1@rS>9Tx4X2^hBb71Pd8Zc(Q5i0WCuVUrP`R5pMBk^7!*`5!`XM ztmC*4`nsJxRN*<~GBrIBu;$s@8=pLm6vtE(Z6xDN17%8`>*+LmDkdpn;Z;>8&CJO+UNRg z`lhzE`a7NH5W~Nh!#8}d^sF|UCwkp*J^J5&zU!ll&F#LXA2*(S9AA?1h&Ye@DV$3Q z`5r^?(d!fb2VeAi%9oUhN4PsDtPe8wST1mtPvVaaC&Y;iPT({Y97r#}Je>tYlu@^Z zr39n|q)R%byGEqDOS(k58|I}Xq#LA_P>`06p}V`gyO|m4^4a^VHM}0Pc>| zqX84es&|*I$&_bNH0XU*D3e;1v0>=O+y1CBeQE@~nNzSIf$S19k&Db@qKZS!qMX8t zc6VzH3pLy!)wH}Ao~EPkU6(KF-$A;#gcQJR3^cS)Ei_NNt1r%n*8d6owL-+M&rGFc zg|HO)?$QGk`(1%FT0aq;7%XC->ba4FNLZ$e`fIiv3t;S&j-!m?1`T z=p+lCeouzaI?SW=Cv5EMzHwf&5whPc!H=pZ30Df6^RS`yzMWed#l+8am|SU#u109q zeNqMDL#vdfSKcHpjfBKoVr{2?KyvhqQi)XtS(%FQ_(3Cg$oTy`lS6I$m5KufyfRif zlHRkrtX#8GVxe1cbB_;UV?zM?Cu@7tjcatrwdHbjLMN*VnR@R2iY_Yjwi3H~JPlNL zAdj=*Jt~!v_{8!fHbv}9gCl&$0de!utZ`4QuJEM6UzO@r5Bb|d@$;Wal0mV2x4vCZ zJr*w3ynjNpO=nts0#Pb1>c@t`WvB@#PN(3uee!D#;RL5)r|yN;OnCauVAmL@$04UVl|}U9yh~rha6v>J>K%c*HG$}Uw776t3Y|kZw)p$; z{ahTOqkA+#=VL{F*B~p2ueBX8P;)(ecq9p1@eN^4|7Yg1cffpbMXXn5Kf?Nn=sX`T zd!yj#Dq)D3B z(Kc{W50G0%NVri`C9YXC3WpY?qS@Q0IsCV%kza|@!Hns=@jF|2$Qk>QC%2T*^L^nNISGooXcvSKMVbH z;NFkYbR22$DAYW@Abto?BW+>d8OiwCMTuKw@}2d13;6ZqzDa2~v>~8?J-Y33lE^(; z^^*f$FKkeqJLOqFnMgk)a@#XT&w>@7##FoUhxdou&_#kXSiw&2pmo3t60J%;A8vsz zUN@d=ZZ-|Gb{8(#Zl>|K>V!!vxe^-mGq&`1Iwz>JdnW~44#%mm?|^b-yVep7xp&r7 zV_i1B0HZ@E+qPq$CW;4qK9}Bydwt6EgCY%%^FO)0KfX{ksSC(Tu{*Y|qWq>SHm|)t zaX!ai(Md;IFTHDWaaK?|yI1?(^Exsj0(e%WdUAXGU+l*s@GQG(I{x8vCCb1FiPLT5 z*i~O*w?o-y?h4o|#dtVFcK&*v5M>|K6oC0nS~gEI=LYS@(!L({aZ#LH$%jMTpMGo? zE~|;3(Mi2x8f_SBQG+9;GNfh3+LAl*E{+BmWoB_lo!2FfXD8j>?Kaa=@$1)rjI36n z)b(~t+!lFw`+nO9{f|3(q7t05ocAv_k3J87JFqzVJwix;We?7bfgb9KDHGz}1276f zwu?V>kDLWpfQvY)6@SU6U)DO!!>0x*ddE|P?TlSqcLhb76|>efpe>9jQAG3)h)x71 zR(t9zay~dz@!N)UENvAYEUhsY){JRXUn`AttHO!a+`N(+c5Lez5PThkrY|f{mP0X_ z1u33x&w0>8-0B;xRLEDv9C3@1w$ z@JQU_jdE@S-5%T~F~C4ThIV?C(M)c?F&y1Ch(cD2!cuW;TL zDsbTC&>nc48e3!@)^=3$t3$DkP7%tU$+(64{6qg`} zOgb~Te}e@x_W?s=DO@`2c~WyQ-IkH7O)hxH0L9h`ePc~)8D)0%D(#Lm(5v($i6V88 zX~UT4))6z+Gb=Pil7#AH9{yx|SrIivR-8%sY+F?ofqx-+EWCL-A9^&X!K=Tr}hDQ76|L&kzAh9}?p%OhSRRtUvxOPsSK3p^TPU9J}sYxwHmu z8e*^ri)x7cS`urvAIpdzTl?#3dIxQpX1WCiQpKV{)o)(w`7nu9Ak%-)E}|MG?Aph! zEHd)kWF_FF8P7RzUWJ^uHo6~N>gD{&M&xz_J?F%hlX56libnsPIsF9p56+7?LO6Dp zkNkIyC%+%v(F@&wY(k%LRd$<~QZPoX(t`-Xxi#v=(V%X4zi`sDnA)~#^Tavl)d))M zw8~I^WL{D<(AhMm12ur^(^W<=%-bfo#}z-2BO^P}^qMnXJsP z^^|S1*U>JwF3Fj0M*$*F_%Ya5Jegkzw@w=$&7V^Z0CBQl`(y?znA0MuUvT zrD3#Ia;DblQ9JHG7H_Y7=c_n7X-PcD$q#j05t34!_(r?9bq-hz-9DA=gdu zx4dN~5y{-p8ev%Wf1wdrN-kW+bn_`J`G^L=@$cF)?R9(R}Ve10x z+tHmprJ*^-Ie!m2Zl$oza?8XIT6=! zcEREJc10Bs83r*ieLzc^PS2H%i0_dQ6=XcDuWH2`dMJXux%#Zg`?XXQ&j-L{`tD%- zAWP|>#PKI5e2diIaP z+0|znIy`XtVCZRYK*?L!Fi3F(_;4?J0jxH7=c+bm3Fv1-r5=7z<-#$I!Oy!mw^;HR z(bza+JZ4NwG!PdHnZD+jPo`PQUP_JoJE2h+(T*_kn#O2t{QK6ZONI*Utx^Zg%SBG}u9!*9+llwRilM7KqT1vuT; zYp7AtzTZLkvI@!UW zD_-LwHC$?%^cu8Q(F9-!3r+esxp9W0{}>oDeme}U*M?cwYx4fLjp!xa)yKL8vg$F> z>IR97KFTe_$Gxn?%#-J&?gfCqiMSN84vg9uyB|d0D0(3}rwaVp0`b=H^|j>Q6@cS= zf&UkpAXC%AQa+Nj)>dng$M+olc-`XSeAReIr+X?BlAhxd%jYVDSihvR{2s7@RDqbs)C8}BD6u_`9i#JsL_<- z*DSH$GA(nYO5v=Trxz6~x@JElMfK$A_4aO$3dmcTn5cZ}c6W;A-Kn+yimAQ-+L>e0 zU7B5XGIWI%aOf6E76DcnRZz!(KYn*aK|(o@Z%B)453OhL(!HjXd*R2SuwG#fSNOGk zJxRtN^22?xEvF{O%39k!(lpSzXU$N+%KbsZ{h8XeaKpRr1cz36Ci~fUtgz3nvgVBB zAh1O5$GaHDTcj>OcAp7K|7uD|pC784Rnb|QS`$mbDgPdc1yIvVg3O-A@VLuEe^A%> z-X$ezX3O3p;w+x18Q~0Ez~MjJwwJ=g3-4?z$to|L@_oqrTQ;sr`TaR%!P%j%iiDUe z6WiZQ{<@(49nlF61%3{P{^7k$9%@S3A#JvEMfjl6t`6LoG5)=5y;6Q-V8Jch_+6uD z!k$Yvs%xk?E^vLBvW*iPrm>$~e+`T3hpR$FQ}6zNkTC_NTv+37TxIJ;a-4j|d)q4v zvJ;%WKiYN-Jm$aD;KR7IcJ(?vRpiwC_W>7aHVPLar(lnEBtZPk%@rdGpXV7c6Bj=k zB|Z`i*T3E4X;HIoxk#Zi*d8(LUi5?S?9%~b>N#mX_X6=Bat>Uu{SG!> z#j$PP zgQ6q>-`pb9jl;es0hA;S6RXWL$>$>q=5}+(OS&mUn zQ&ZU}J+6^hUfpnM3rAA1b6VDml{GE^=J>7nudLN!rQzK`(03&Y zc`g-)%CY`!5|@ zM|dB$FwXCle?_W$T>1oc5ud&>ZO94@AzlQm&9!KF6h)SgZXn-%y2;&t>z4odcp58k zH@7ukWn|6z049p>fFC!ZGi5I_Dw3)WTW%bpiPv__7+@LLlE=~i%ZIvVza!)L zA_PLa8vwj^zSLD@^ZxgzNYUHQ{mrI)p47VP$iqum*zHm4mH*n2D(fK??Ik1wPbRzl zKvCv_K$J)S`l{D@w(#UJS_>;8ulTVtbdPcDgZYp(g^zV{g=CIv$#gG&VppTsy@!tA zivKFUD8HN?_*M}cHw}FWz?G=F{csLA)zjP6cD2d0_2l2zqDD{^^73c-7!)nOH5o) zStYc%kN|NmHL3yp0ZJpV>R3guU_FaZdfOv~HK!kIewXecm*W-WkDiD6;6+u9aF^@zA$_( ziS{)l1R%m&A|jEo#X}RQKLhv+71Ys3o$UtS&aE`eXV2^Yj@@J?Cx<$#lXLFI&q0&& z&sqg|(Xk`wnd5%KS)Z6V;}|>^l~k_rll(+1 zyEjc3AgWt0m&N0q%Rr9LEmEiQR?8HicOCu?C51mk|B1V4%QpGmA* zfARid6(zgQ`#nN=m{gOnJ-qZ>Ct!O4pxjiBj>y@l@hFlzo z)2=PU5fx>EPG_IK(8G&BRz(sy)?{1gxyONReM#LFi^`Esi0) zc8ix|ULyt}POF}gge0IVec-eN?~3f`U^}=X28SpRSyn}lj(O|Tp$GL@$`+%E;l;nw z&)^z-?z^TS{TvDy{BVu{alGD>#!0 z=tjdA()`SgJ>OzNpf>wtMku2|wz%io*sShv@rG!ZY;lie!Ul1Cx%obFao^=w435dk z{lw#kMF!8HjVpI*lRgroKD`<_b`C|_isUhQ@lmN=62~q&T6$PokJAdhF2$;^BB`u^ zBgjc%{tbj>)5p9@&$JKvYOuOnXI$yTY#&U(_23(`c)poVI!0Glyxs{wHU;9)i+dI% zO#N?mt$oN0&@jwY)bF(Ex<2d-v7GSVQomC8KQqBoSB_SufvP+An-@eD8j^co6HTao za6AX`xQZ`on;=Y!Fq)zj1MN-MiRZQ3eG~!|o4RU13D0m!Ifdr57Fkx9Fx|rhSPtmFYCdf;dVd zTO7YG*Zj%v_TWYpFDN-DzZoE+A0o&8>g%{iS1z3=qjN`2%dh62h-Zgtn895Xy4;-Z z+}rshX4LChV|?ej&g$$$tlS#*?uQJHzw5>+qvP<5`fYfo7yUAiuzt`&l8M9ME4Q?ZIE1r`smXo z2Db&R5CPPK_~$<5b&^jtyu4`-t_L=8*@OK1X_eXjGDZCEe_HRi4c0l;TYN&~ePdBx zFED4V7-?l%LLN%Y3O=d?nGKSP$>RP@my79pAx0X%Yh1j=v=q{mIv0p5omE+n!kOpQ zdqFo+r1~CADANT8<3oSqTTcYsxvjN)ey=N5&vV*?dgBtCLN%?RS5vtW7tVGNDv0;xI!~C#lKA z70MfRk6u*la=0jeB3~8SZaXw6-JyR0`?EIvX!C<{P-Fp z*VG6m!T;`dQF}IEQazH~qyxBAsA z>1TVMcFz+O23WT2-?3l7roY*RKg&Lz2*>_D>Z6lHtlwJ)zWf(`b=b9A85ECr z#7(I#A|_Qih7lgmyPu|)sxpedXD3~!beZ?M`r|<2s39!;Qr?+g1o;PjfBkYY>E_?+ zcWu-6R42&GBe%VEH&?M2O(+yd{5qS(-HL*4NWT15Enf>f5gSkg(RT6ySR?ZVeGBPh z%av5X*xMgvHB}xuiECP!S{|sp;&H~Jic|(7rqYFUZON~Ul8}=`91I_S;44yEdz*}^ zRNv@`=A8JmZuzn$atf+H89?(;#<~S!N3WqH^$FtZcWa54&N29rCEsZ5OUDm!daxf& z$?csT33&4JFxBintg6BtK?~wbL_8>z2ON{_S*s79>Lsn(Zy!lTXn+2rcnpNDIA)GJ z_2OUH(cfvSbj~56>Ksc;ZRd86-8fX_zIlOdQtP#ho|))QKkt_Y_0Vx5iqmu<<%)bZ z5aZqI)1xrehrb47CnD86A~Y-OSZVIQ%m>z#k57KgTGFt5r@I~*N{4E~%1B`S1(z){ zE%iM0R?>SNdwl$-2&^s&&$#Vgd}^Hy37uu#iaCdlB#8F$40E;qAF&=u3r$*bL~FD4 zS=`dx1YyT3CV6vnb&nxkdr|5;r?Z8O zIFseYikhL7MV1VhXvH8H5BiBo_LC4r|D#Ag&dp7fqUM$1SfQ6Y7x}4nizCX!I-$UP zqOJd<%&Cnt#QG)j~j z4@F)tx*7uPl3%K~Vff5G^aN{*=|qx^krv-V5y^m@0#tQ~btXflb`#gl%2>NSi1Tdy z?R(Wa{oQk!-tJgZpHJYm*yQQ)+Q*x^6f_l<`Eqjyu9x6H?B_`u%?lJ7?N)k$Mjc#4 zg{L;iEUOgf4<_I*`uXYRCZ7aPx%R`(pX(Z1nnNIsDw{Jv9VDNkK(dE47Q{396g4z5EA%DVZVa_Qw;iAdAtVG%f z-Um|Qs7o_pSlnm$ZDCV=B@74REnuJ9BAd?xDfsczvTG%L{eJs(^AHlW<01zB49Km^ z&}LSr~truO|k7(+#Uf5+m&Ds70&D}MDS%6nf!(VBIuI%wOHKX;tleza~XIGg)&~zt?H&@Ju3x{QN;Xt*H~Yy zW<^k~y3DJzf#vb{$VavgDy3b2di}?aZCZaWP{kvgU0C-1MSqq0OotSN5~%^5sqX-W zI&6%86yFgkD-)UhH8SYV-TGv5oRtU~AU+JPMVK3-4g$nlp31A~WAM-#`)NCPyDp9X z+E^CYD@YU@sPw%7^(H7Furpjk(}~4;=%m&tvsJHERI&Q|SC!H7&2qHkG~@ZazDP*n zwy~Vd1Cho}F~bGi;WOlns|5(?8m++mFwOS;+O~i#kM#BMs%PQ{Pw@q7^lGW;gAM?(or3U0z4-z)QE2FX}{6ts^^0IPpo9{DZ(HjM|Oi z*++R$BI;7lUJ(}Kvf1OdTzvYQA8VWuiq@P=^$FjB0GQhgcCuNCm|?KfYdTpaMCL!+ z6KxT`-Ml0B7E)4ye%mjU+##C2Wriylp~)LbWwqn_XM+4q+JjKfVC5g&W&OE{IQLgV zJ^OFaPg(4gd{eo!kXJ`E;sG0}DZ`5Ar{B8mZr(bTx-5d035SzP7J?VEE5`et`;I=( z8`yQ@)UFonGf$4-&$=#Nw}ddNskD}NFdJYyaZ~cR(6#XKBfdX=P=7#Vb_Rd%JpJ3Z z4TrkZ4hP)=pN`Y9Leb-E_l;fKrSIA^Lw|iS9b{T5TJ& z4qVtQZ&uN&W$SoOt{O7?L$Zi{GCo}8iTVv+I>#+s-Q8_8zHgjqlXqNH-2#yU=H|LS z+ixT?_^)Ef69_!f`Q*jjty-$uSN4Nq{`&37 z=rJ4n-PVNk#-#~l%v8$#&ed#dhjkz=Ymcv?up0zVXic}lAlO7xx+4W?@nuvWKs)ym zmETEVCd24Z!oBL{%r-vQi=XLo^o&E42eK~<bN4e@QHk97RwH#yubB zVjwJ^8LXA8ZeNHM%061Y+7<}E+x@3Lx>P;wPphFoIV3MkOOBfT%~wdn?6(|uXggyp zX(Zppe1{9YK@FJ38_zLq@2H!!WoWiEr674ToI+`8sb1=SnOQnBy0a>f+pM1+A8^cH zfzkbSq{$E3i-Ix*uKQuL1Vi-l2x{^i3hX1-$+9>u%OiY1!N?xXI(Y3AoV2~yXCJJ3 zDYKAmT4m2mqQ+6)?(s;f(zQ~R=!iz4{pw?oDj+}yKG(b96`NZ5li5`biuhotDCzcHskN*b*PfZkpRK^r@}DRqxGZFTqc z_&;8KdLtH&e!YD>;yeSRf!%P17CpA=U(CT>P(4G$HA}Wf?0}5<16fEIRhLEWT4Cuw z+I+8r-k`c%L1u4-a&5vAOJyUXECQ=#x%JZzGj4nZ|nk`QI> zvtS>O2(KlVNR7Pz*>{|K0_FNMxG;@L3g4yKB4JzpXlfRQk8ByQoDMI2vHj&RzZz8M z>mfT|r3$i$lSKx{bj@nn(9j&2NcDiCF<->;7j_)(%b;mP?iX{Dn>kT?F?X7T%fvhx znRcIsPHIs?V4Fed-S;OZPS-jo^wm7!F%6w5qA|=%QE+?bg9sWTKs3%gx;sMu?;pAM zZnr#~-6L!e-+xU4gGvPPXs{$T!lrxLfLrN!SL1bAo7>m7y?doNXYuPF_7{0m=tREz z)#&VmQqU`Z)EoRAuSK~n8OPm07^SYw@cRe4 zPDz1WSME0!*Gq-tsldYz)6{Qi^M!noS>O1upSxR@zc&k8OckV9WtvMWFrM#<$@6N6 zck#Qyf*d*P$}3&h)kz4RHu+%0CwR*_;nX33Efu$%eba#)Mbg;heW1yA92F!57=4IEEzWB`sh<-t_$)# zhQ{mP4fo`JUbAqnm&PTRZ&+xKZuMHO4#wr2ISVOPe%?LW%@#6{&^r0plGI`UIYOU( z8E45Mr)P6&1C*jem8m+SvJL5>ogzE@HPi#d61ElJSPuI-=NW}wtQdp8fVZa06TVHd zR&$FTJ?9*o08A16?Gue!vth~)q1ayCL#H_oZtIfXxy5l*{oUW67o%RzGBU;e6Aap& zraO_nN|O5SiCaDN;ppKgEip4g;qoanzbiWRe3gA>3O|q|?X!|tT#vr?J*+uEq*6+k1eW&Z^9Lii?Tz@~g+k_H;{QR= zTPv48_HLvf7Ee+#!0O<4F`<|gw;=1x%+mWt@ZJCX#C4ZhxCGA%L&eVbj#?yJuQoh& zK&MR#dx_T2`PlXBqjzQyj7mI9l6?dW6`7Fi*J(J$fu)g0;7){?Dd;$+=(L=mEBvvsd5^xUBJ2>wvXIL z)Z$^861hAo*A|6g&)ZOf|AWc?SBsKAmZ}eb^WOK>d2XMJEQ@LPufi72TB}T1?!@GM z3AUF`XGrRLqq>K`Hhem-rJR?#f~yWzxwZW?geSCY>Z+1GPclo_CMohH|D`s3;SWcUvvv^Qq)SLgT)aA8Z*+AHVpVnA(k&sd26|Hw8U|d z$qHgqpcv7+R!jjW?H|QLtN!4D$Cm(xar5LHjI~OvHG|A^s!{4QPlG-OmiOt*F z8zF4pRtLRG6JJ&MC1+UECcMokY0+*cko+aY+HE_deZnY81b^U*JRHaFzW>#!1uk8u zH>pB?C-N{UOQfq+Oo01K8cQ7%j4CqjL0hv{h1x}L4qtO_>3r?0NO+lSn=cNCZkkYB z!W!FV{^NFDDYr;zdlF@NrlWcC%hqab(^cr$Fmx3u0Hf`pp*pmQsjeZZad+&To^52g znsV=`7cZ%J3k~vkzZo_z^PgD3KytP`7zh+rf9=~-wo;>vE$JQhp5EOd*E%vBwNGPq z-(-Oz1DYYL(b+>Fe3k57Bmpqd6Q*vJzJzW>!_JXk@s20Hlk+j9vRaBi$3H7D=%MA6 za28cG_<&Sa@ZLm=(j+L2rq$^KQR_sx;Rz-Ne%ws<|OQtOG~?)tveR*DF_qQOM(;qA_}`|bQ=k0XAh9|3kWE%XiDDK``UEC z7S_N59|%5K!Up|w&lI2QyPG>5*!PoELO3y`Gk5QTHaM)tlR%|6i5}>uTrM$sJDrvy z7VnGBltZ8QBA_({Xy9@u&qs0usAn4T%-zYp z0wW!Ia?0}?F91xMj`anX!R+h%$(0tS*Xpe|U_xsx3S>-y{G_gsFvX8~T|>@4Km9DF zW7_@oWqjH}B)X7S&sA6Q?zIB>`aBULu!Z{$cpnDDJNvU^e{>@#L;URMEz-#R1>K zMjTsRwCI58eMHvcIwLm0zEGL%3jQbt9WI(j1=C>0Ljxv}3;fK#hHLc|npLNCN!56- z{!paIq^M$@60R$3*HsjrHQFGHN?#O(+bJEwzJZQ2&BQ4J4lot>LntkjCfttL!BUTZ zdkMR!WmKO)x2wB5O=t3FCBjIuvElgjSngyBX?YkZox~WjXN-PO!9<+!R zhfuj6<01c6T;7_~A)9bY;EUK4N}R~x|9E?@i#=OXGNx^J;sydqK)lxNbMA%ik6U%h zN-yfTVP+bdT6}a_{$0iF_>eXTt&Wi82nq6=9(sqE%r>bdyA8j z%b4{*4w|{hc*z=tZ{ri_Jqn1Za|*gl&y{zr$L#UjeQE3v=idda#+v4JSy zRbq_&7rSpdrxKz=)>OZ`zc%s-dSPb-96n||62}t-(We{Ic=t!`?WO{MjhV*E$ky=Q z4bihARz|EVu$*-fL0cAC9;?AmKneY#f4^+{j%8pmFmkd$qnNv`5}ijOJecxGhodBT z@sLG_prqzM@b8hGDK}r`>4M-jxgj0UILCg~SqqN>A9e`~MB|pLN*Tp*u zq3R07fd9Tuy(YhVv|o}aKF7VA58wbTkyrTcKT(RRP|Tc7Otpo@`LI1E%3Sg%VvxPL~ z(*5`2Psdc@_721+=4R$og~e*Z=8_904w)*?ia)wD{$@TJMn_-GtsA-Hj(BIp>iXRj zL5VDX0xB!@3~-Sl7tX^k!lsnIjN*!mK9<0Vr!3KI>n{!sP)lf-#D7;{tOa;n+{oQx6cvwq zsfn=YL7qb}od+DuAP$Z|UR5!YAi!Yf$hf5nOlP*&fKl=iqKmHl*5-Z^6);D;V7?{^ z{1xIpLPzta`#nQQ$5-+Sy0{>BI#q)9PmTwUDuKAKPZAymKdO6Z=g08u7HXcs@ftL9 z(Es|j5&?^^o7OzdH2~L-IEEy4I*R*?-)|d?K6`u+wU(Wh`gB)X9J^rhS2GCVCRVS{ z^G94^8{4%oOsu+ROBTfd`!;f(>N=q8e_h)RuzmCjB-OiKR6sWr)K??&HViA-BQq$b8`6QlqrKj!8OQN(13- zFdUKhfVG)};fdUUp`+AZQMq;b{31-7=TFcmb6k8-D-P6QVFIjHzH6XwX>#_ob(ot! z97tuhd3axZ{EZ1_jEQSDkBHNc+?)J_l{pA8S!GjqzTDK zBBSpw7i;|8m=-V|2vsG=ALYrv+y(Sn2zCYI}Nvn;l!GC9KzfzFv z)3J;qd)3q5($}GpF_Hc|*^sU8PAZ+f_Q8GX6p^jxyW_D}TGV&&5SrpI)L7ySMS$E3 zf-xTa>m&cUn6h|`)k!X8hzs1aK~Gagyp*|_V|qKIVjDkE!tk93;$kja_~l2|l2uH2 z#IONBi^d??^BLQ_AA!BpI=PH7@_y$o^M^e$aiMEC)rV^ZA{lK5?S81Ec_foh^sCDc zP~R8SFnM?MnYj3s;I6OZ$*Ol4_>p0W{)vKn*n2w!a^$p_0jEDu5-U(u$pVj0ZPc_V zvq9#!)Q*MNMGF7VOHj2gwqzd71gueBZr?Eys2qzBa*TdiGZt;aghaSt=-esbSiLqL z>q*u>Ugru~jH|nPAqwYR*}?GNcm4EqYXhwgfRpaB%bnJJF1lnNRs7CwZ!7v9_;~J5 zSU5i|?m@--_WpC3=;!C5Q^Wjo_pTgsJmtmDZ+<&Y4AA10ey6Smn(*P_dBg)I zBR@TzZ~h(`UBGxrA_D`~$D7=8BXzjZV5deva8z`P@4r zstj>fUf^+Ncq0mt#6_JTz_he`1$K;474E!y|H*(UV5=DQh-7X%w@y5R^fv9JkV3K3 zN2HqFomL#>o&q)_zn3cdakL>hVAyP&xPBn6t7mVOPD&hk{r2kDV%xqZB~@;SNrwBR zFki9YjfDNWV*^Q5aGM#9O@kB2Xcgo2errc$tUp(KQR z!LJK6DC5b{5M(Vr_JQkQH2553gQ2LI=UuKV?f5wNm!HC)@`5hlP}YB=101!D1WAI_ zuXQ}&l7&UbiEhE8Meu(OUl(g&2y7hn@!zvH99d78Mf+kc7I;mFa6K>yK$(6dD-Zpp z!AC0+jqMbGU8X+(a3&ducQx~7uV$7{6W@W!!yZ>L^#&Q(xTKZ#N)pBK&I#~)s5?Bf$}1CYirS2Ntlx{m=w;acT@0Fd!H-Y@$)lYxnN z9t8T)Sv~NFe}d4<72AKt8aRoj#)vzHjgTF*L}DD_IR}V!;8#x>JV6hqzobNqL^+4M z&8i#QH1}+Z&13U5Tmp=*4cL{^W-0Cf>8*kZr{(k-?Cm)V`NB{ z_mQ*Qf1P#k*?jN5b>RA3RIeYv-UerjzB-(0kp|2;T8Sicw_EFCcN~A5m7ne9tC~>%)|_;}Lm*`a zssO)BKI^sG8LOao!L#;Clq1XT`cq2p{?IRwXU0C*hb+O-Vf?tfHfOu&G_fC_y%w!l z2>Z2EZ}JE5+%Wj2;J!#zyie8B-}9A!eF*Dpz{K!_Q|7|jK7vxJ1Pzyoxn=COIfJJ2 zm(+o@1Okd+>AIwK;;-SNaqr2Po;^EXg#ghM^c5YKw=EjO_)eG0p8K%LTBSBe^w8YB z8nuIC>VzB@v2$tf89E6@*&OWoSFqiCqE&jVYK(%LNq5=6{@0VevHg`pig{l$(guc* z7*`fh>f3n|6K0Gtb(U>mpkenJk1O!|RS_{CfsvG->$S?dgA69r+wiO>vVfDJZXk@! zI=593o4Wb$7toTlwJKrJwS4bPUnv>y5;#K1dhV-Ndx z72X-1S87j{3z?^@Gd`O^p5hjRalorVmiy)DX^en#3C6S2)>5~C(F}WrQ9LJQ>6Da! zEWpRouqtXXPjdi+m`J}RxVz&?KFRpi%IJy>YDJ#Q@dGI_s=k6VewK{0xeo!wZ7rOT(N&7emLWvp1D7TRvp#016K`B?W9TU zE;lP&W|pTkDJW6>%ll603u|D-GdKUtEuI&0TP$tlyN~eNQ4VfqS(=W$y&kTq3k2lG zP8DCCSIRmidQ1jN^A$^b%zZn}QmOm=!{>Mn34v()@Ex9i$5>1|J0_m9ts|SRy;sC? zCfH-1Xr0?0mzgIjpH%lFfd~c>Y)5poL50M2qGMR?cf)woK>pqGZv)SEjFxo%SjpgB zdn;O^`@|q`<8GaYjxdIJ5MIg`jZ1E2DHrh*VMdBrOAj7bIJ$PF%Y5wWDLYt8d(_a`mRKXJj+}1=G`dy}>@|Wv6 zT{{Z@V1|lhIj#hZEa*PE93eT>2>Df3^leEnET~)~-O^mp9e`&9Obl~paFYB&4nVrq z58GrW>s^&679M)C{)};Q0@zI^CH|WQ2V1(`Zcj6cl4TdOeQRmAb!P<-Li_N`6T!%l zbxc2;3%lNI^Scco-k=^m>Q@G8k8TN<#dg_D!+PW5DNGAvkZ9zt*VhgnI3p?KQt1wc zAuu+kOa9rDQ{S}r3VmWZYf$O*nrt5kERa!nGTwA#J3 zi+gzfI{!re457%CeG&TA<+o=>z&*p@j?O2WcWwR*k(ofBvD(h!^!mmt4a4|d2$~XV zRmE#=)h5&T=I{MB&CZkD8BH{GFSAKhSIHuGQ&tS<{61ZIx45Tu$#i%{+C^)o8W`M& zFn<;IJz7_`2I0kf8ToAa8T%z#07JPCiRGr;X(W)(NSSlk+a`i_*oVJ!ck;AhavQZO&azk=_$fhJioQuu_5o7#v4V3!tO%NRKI5Vv$|TJccq?fl`&D} zrw-5S2_rjWGBT!FSF3Zdr^UXy3ht2x-%=d%G-06NJ_X`r&~zaq>UXFbbv1kQ&1YTc zQ`+D1rN3ocbG`2_Pr!Tt|(kxqV>EZ^W0lb$c!eF~^4b za!W88W0?J28DI=QMc|;i@YrOV46S$Mgj6~gy^S@{ZEl@{bOuCcewAez=5CQ`1cy>h z<^tIRo_ob;E(efs-b2;^!@*}s1B>LE_2;F38*UGPuRp`9ww;7u*+^>7u^Ep=8IKsB zpAfv`w%G2D_e>`INRh?7;T|8QvBB@Cg}>==itijwE++o-+J{BPQEhOI($L%$JSVrr z{1;8%;Fs6q{+(9KTdlUdW!qd>#+F^nwso>?*RtK6ZJT#@wrxCpe&5&gH=J{>>s)Vc zD-84fJIp`rx>R9Sg!eD{B3>cPubxLV3!s7luXUY=u5q|EwVsPoXt@)JV*7(u9ldoV zzxYJ^U>eE(GCIm3HPhH0Rf;zx=WYUzZLN-ftx9`GEH*Plei;%)ULiLY81eNv;&xPe zb->m$?M^u7&BddS^<^yr)NbL|jO&O$(M@>9@{y`-KkNAU+-2QTPgI9{gr7VCsMGS( z-t*p_AAfb*dy9y!y3prkbUb$5<8#&CetYy_zfTf8$h+%rC){pavVWZ%>Cz)RX>^6` z^qKX*XTf8S$N4BdV}<3G2lZFNh7)mGaqsK}ta|?P82rt=cFtR;dO;{Jml>}A&8=!= z%hQ`JoGII)e z5?qdQiy8ahGK9%2WgaKi@DjxJw@`^B}7_ zCG-wcD`2lY!Yk6+(Ss2BejZ^em-lo6GV&T6l#%(c<@JzD)V1++99o;HADW z>BKW%zKCA!2^NJM3NUk~?1*;0ZQQPENj1yq2=muWegny^NoNLCYS@-DKX3tK%q0-Q=QUze<$JEE&OLo_k|fDr zp4j$6_SK8%ycnhVHwR#8`lJsntdPOM)_$+h{Yo$8Dk&jzq_1piVdg0R8*p|=NOFyk zbNnXE@h7i9yHEINiSqwBAnnm4%e=OO67t#SW^un&VH~f`%h4909 zp{ozeGGZ!_fa#98A-#p$%q+{j(hS1C{IXi=-w5dlTE7tOy$n2GklQad!J6Ou=$;6t zG(Y!KykILBa{@O_x=uCEr2j0wq%c#J3s5*I+j;CB?IZe(_TkiZDQ$k&n~LyP}Bu* zU!u~XP_GatyrJa?`HB9I>-0yBKbxOrjQmVEczh?UiGf&%o9ya9+*~id3CWChYy!dD zF7neh>xhBV4es4p&hGlKc}^Go6*9UT-+l+n=?_dyKJpwLvbr;jHrJKdMZ#YK6eoWh zARtPQ+9(bW{EEZNmy4zC%6)-D>O;^3jo38Nc|-`?p7^{xjnx(l@-wUj^a6`ro5(a-?v7FJ}IP5Ncdaa{b1ux zXFV|-$fRF}YfnenM7dQM45XCBzGQZE-0}o&fuF7z-#EDzizT{oj)*jm++1&GPP{-o zmc2V$@%4v&|E$~nE{f3Sl6d1w9oX_P`ofPe%|p6o9AQ1Q^glrzU@M4ej`1E|K$?CX zPp_5(#3z;*Jchoqz`}}Go1tz-W%~OVRU9yeSqBr?B+}$Oo+U2<(}t0hZ-J+%A&o+HWBjETmuDPAh7lZopGzntaI~88M@yx|#d^Jwy?W+J1H+k*9&s6k`Jrzux}{jM z0)o+ny}DHdrtW4R5XS&c1-BJP7Yd}If(|H>J={UYd}_3m71r@t$pv|tG^(rB=(szl(^ zalJ~lZW`eq37WJgzvUkv+G^iJXsZO5k(z>1$k`ECtc)su$5q=}@uc)2?ft>N>z*3V zwE}r*7dCm7FZ^rZdZ$#*9E#=m!2?Jhx<=CXLQPyTSO;o1QUo|F?4c+fy#?7LHNy2VYftu1 zZnZ@nNqF~L4q6I+1^cC3u>+Q>*G@xfwbFs2bu?6ChCj>vTr|0D{#hIRxd6<;!Qh`u zqh{d#0m>&8Knhi;h)JZv=%I-P=(7Pa`zcFtaSy>p8WgTEalFB}w6?|2l? ze|XesBPo|1$LQ!Qi*3yxOBfOS52piI*_kC+-<Nc?u_LM*Bt zeZ3@>aP5eCU$N1>$bY_d{_s00bQA0J(%nw{tpytp)m4S+nlMQUF7b+c9^2A0UQj)= zvh^#9fm+#LyQC%S?BKNKK)w@U>xfFoZHyolt2umHy_gAh@NvF{eQM!XNioFFk^^0j zC*DPDDU*MyCF-do0J4m}EHFD~bxp|fJ>X!DGd%CA9@w?rf5c&;CK^fwxlT0vT}=7t zd&W^Bu-`EH$C9_b@?`pL^x#(_0)Tq>Kn0D}-tRoy^or3}mQ>OGL>85M7MR`*1bgB? zCLq^t1)@-iJ}%esMDIV^az)kB|2zwBi)){~N|dT9Oo{j|0|@L~jZhrSIa{yN7&Q;K z;vh2BY}n5biWp;xGF4}NxySua{W97Mk7VX^|_nhvkkHTr{r-MFo0TFyRu4! z3FTSRnq70h;HL749{kNN;Kfy~Y#p(B%ig1O>k6au%w+}UivMCOqG{cAF+W`=(AWKA00BtwFkn)vUGj& z#Gq}@0opa!3Ou*S&Xo)rIWhl^1mue~l{RT~7-L2y`zHC1wSPN##KRTabiibQ_Lr6e zBiGspTwIb1zY0l)A!U8oK(KJc+Zi-Y%vca%0R@M~h?Loa1TXQNC1DST^#)A`Y1ZUf&vmu(!u zZ(vyH?IXwGbM-{V1iVGo1~QV$X|RNMF|r@b;%CFF^U|NZffh@m%8mn-QTSeZ;*}2p z{U5b7pL%qYN<3`wB-lU4nNNp1vFPxk2<12jwbg!dgmG8Xk69b!Z%ONBou0TLh@61y zbmlc$AIXL76kxB_sjdH9X3t=-rh0%-(06{qk#704$7g? zbRvaT*Rf^PzVk!Mh-ruLSLl|DAI>d3+s03qQkqZaVR*E`+G7^|4b-E~9LF%lZ~4B* z6w-~dPjUh<8V6!tGxjmwgz!#9+@6(>I5&G`qJ^=6dHa`Q1Hx_w4^eucaxt@TbN#BN}b<}qw ztm~)c7hO?nb_PZnBu{Z1+tMnyD;#4jYeA64DdyHU%5nY>55cWL&fFHWg)cZs1SY<- zd)pfk)rhb8IoZIIVEYM#VL=qk%eU&PN3k||J?b{KT+hvhcpA6YFpq1Ci3F57R!^=q4GykF=i$K1i&SQ0I`&iY9hF(?mcT%Yg-j?(I?$o+Vz-)pX8b^M(TsOQD^_P9Dd`>a!9(<(FOU2 zY_ue36Hnl{MDKhp0RXu;gnh1<;xn*UF$_%s&2oYDW0if z`N+glB%z^DIs;kX6o9&<#`l0%xO?wlVLT%}mZMYSVsMlg3#s;jHuR^Xy` z{9AOsks}=9WBVi(or4aRz2xkO&X5JR7B|B;`yME%o4E-{EY5FU7ZF?BLnt0&F-3u` z7oHC+J{O3cG{3C?_zFko>%_wcX@@214jz8U81Y*A{b6%WAIZc3cJfw4;!31$Ie_la zl(ql`yxMlkTadF24oidkxNgWdM%Ov|0Pe}13l6a-(~ja$A80NlEN2>? zpf(ju`pp9gR>c`b1uN~e&b=l(06n`h#6;Jh7u+=--hJMl*ROCT>W|f%th=_&XZ?uj z=f|tQ%$~Q(+`L$l3yjhpGo&o7VReKH<~W#SZKeGW*As+Fa~)inHogcWd}T;o66pKM zqJL#OoCmcqP7bAvV#H$GbV-o#k)Q>kz{1FRlCrF+>{xMg%U6a}5s-;lYpvQTe)RBqqn(*O>I6^kH%S1`SbpVnYiW-%a0! z8m7F}D{;8^oR4KuXKKy7I?#Cl}MBSeTdTyqly&Uj!V!=Ry(P0Q6p2aMxOdJu2vHQV5<} z!+C1~532_=78cxu+XyaOT%2xGz)yvHojpx_$BOl^H-n6&wcMT`NrM@SHuo!&WDc~kg&r}b zrERXQrh(HIz~tu#$R*Cve8yLqx<1t2rty-4ZWPumafJDz`7HocBjA+5*wcb|`#ssKGbE}hR!XIT@H*a7ecv5D5KV>1Aq(GW*F<`( zR+f158LLVGO;Piaq9N)o9mhtLoTx@F_@4_!uo7&Vwb)X;fTJ{cio|jW%_}>O`FZ<0 z*6EnWHi0fHLF}U(K_U@_c66Vi7E#x&M1-f^=x z_%7MNPS$1_lnAj#EiLExypXLVolaVja16gz(^cgc`TxZPi{QN{GB2?&LOQId%M*Qf zpPsZ8pM)yix4p0@9y`k{*hp$R*=~U!n+Fe!zVl2acQH=?|vI&?%AQ|j8M9#FQK%U zsG5mTC|>xExvn&yMgU853BHFSHJ9P~*D(J*a~SV!A&fey-z@Q%DY;Mn;QSgH&7{TO zhRmu1jb1gwml-tQlWSi257PDFDp=r3U()#KGJd_%@ss_BF#O zN2wzQ_pY9Qm-aHz^~}5qPb04-HB`dl%)d>kuf4W|ldBgBMFG9Rl=sGHSdbpg#AH^@ z2t%3Wpgfw><@uAIKH6)LEDE>y4pHgAb(Sik3>oFgT@P|<#b7DF_Q$}GKKNZqVHEMn>Wc=W zJiPa2twzV!4nU*qUQj?>;q|vbK(UoN2cNq0r4$alKzR*Zsa{cl+_S~iC!&9hf_!@Q zEEnacEv8vr0y3{_95Y0G-`kTW@J4nE_d9lu-dbMt=h&P{RBsuswNb>ylGmMOm4m6* zuXje4IKetX0d+k&RerH_$dd@?s-Fc}blcl6vAUohHGp}av7kbk^BBM0LTu|UfiF%Q zDmw9dx#eRVsdiSjVthCTO!M&j>LoIk^M~rx0naE;yKr8YamVZN3(GpqZ=U_b(+};| zAPP6{xVYEt5&5j8uYYlB9}#bE0U`%=hIm)l&&L!6rwW6@Z?Fpg5D-=m`nwh_lanpa zUV^oJ)PY6b{G8mA;SnSCg42K(zWB^@;`W4{8QCqQn}JQqLq+T7lnT~iuC2sj;Pe}US=SqT!$yg1^139frXU*%1OJ^UZr)%tZNHb-h+ z`*~2x9i!?6op;&=l;Q$5<(b7oIK%x^x1SLb0Zr-7Zj4lSj;?4rH99ElJ_knQ$t2Oc zdbeQnk6+xnKV(ZbhM_LJVmJm)FAsqf3W`Ti@d_Ptp;4A^Ywhd%2iz-2An7L6>* zv@wcpq3-3OBADVti?gN@X>z;JAPfdcjvXg}O|S0aXU3gvdP;~xevyl~WB5n}Mj3#{ z0J4%L0}3U@xlLSoh~>>VfD{D`LJuYus3y>S~{ue2}-GP5-Aw zzL~(`e90X7W}i!?kRg%e>PJt0x_SSP@xUhKw|GgngOY$BlV6HK)#O{{dEWGUy1(K* zphf@T)kGUJub*$GyihZs(j;F_uR)Ur+!VpB+HDpO=$_Lp2QPlvCjB1Gy3#hcVaGR_ ziCuu&#W`RVsUN*HG&tt|X1-oL_ne#k%}fHq>o@A0gqw+AsrDK&Q{pzGkG=d&1cj=SD@i?H$~&q zb?(6jD4oM$NkRm)c|R|BI0@}o(N_u9QGSp0?z zD6Z|iR@{#cA+(NLsUNNXqD%F*sfXOEfVXM2pB;qcabvuh;P2X333OvhegE=(j6ZKF zC4%=oV-ZY2fN?zT-AI`D&;g`g(=;qT&L^dTM|?36G1euB`1xH7Pv>kM;C2L0CY?nd zto8!_?KD&lcAG8#*$#bx5E7tt^U0{_TZvK7mj^D1j!e4wo?)rVh~d-k7uJK&1>f`* zO!t%~A7fywGd;E_T#olVrVgcjBekS$wL5m)^Qw0y=9a8{f;eop}_}<;*47%yH z=>mI3CAv<+$jq-c5aWu=pf7N`g_+`t&tzp3sf25zNm6FQwC@|9lHCjdgr^_bRe~}zfy28uBx`RS5$35)8&hq^9u5_-XItM z5<8tbW8Eh99-rn|vBkI&n%JzbkFh(&5Y*(}&_`Bc{z03vi|0}&^oYF>%gN|OY^9}G`BLyZvq$XrO(&3-J`32J(DQVXm|A%? zE2W>UtdvgVKI6n{97;o2o#M7|UR2wOG4<3$m9ysWX3I4>p5lydqxw;@>pey0&bFw~ z@BeQXBfMj520IvNqjb}ubHLQ-Yhubv?Y9vPu~bj(Y{uC5i?Re2p?TDO+BKIcRLrjL zGAzD3%_|e{{R60Kmbo5QY#(<*MfxJ8Es$tXos*Ho_0*Z|&Fw2husuoH6YvAJEu}M+ zGbfw1=8C}ZeYAVTzwOgJCzb9zbr65@Ba6z0ic)ckb~r#aN4BAQbQ5-uJsT^F9n_}= z$QZ81)ci_HV&61Q1iP`!m2{a_-PO!%BP_8(Mvv!!i6M#AKW0DVBHh82_?RC9nNhC4 zPa*9`t20ze?goxO8HzHT#N{0-JJC(x&W}{~6}#;qweWRoYn*rx;>h7AA{P@RwHXSu zH3qbBPuR8S9|iuLDxq<(tF;@(xi$@}?>3BnZ`Jw>%Cs-|K_1c_nz!-Pbo6jp``j6T zftURU08M%-Se!PeklzfS(D1l=qrYSfJt2F74t6^8tC*!%!%t0`6eV!9*2|bo?djP0 z5w@?Hq|XVPR#%}n+A*hgE8YD4`;64iUxnJ(iWAS!2P0~xJnuK{OO}Fu1~Y%WX2315 zF1vjH_qFcSb%eN|)Koiy@mw-WbCyocb-XJ8rB@FtV6EI``B9DAD+Ikp0DM-n1TkiA z8d17aQgPD);U*vOSYVuWn@yT7(n4|vcZXZn4DRHX<9?c5qPw0GB2w0Wmqbv7bcnk za1f>=hjU=O{#@tRez&}v2pnkO?e#E)egs6a1?3~e78aNrY6jYQlA3x41 zWNX%c$dm$EQp|aDB>4x)3N#iO8;njz)lD719vn;bbUDlEI=BaGlIh&Qg{Dlf+~j z;h~B-1Za*7HtF+^X!t{E#u)LlLigsqI7JGzA@DzyUPIBL!#>dSak;{j`(!|oJK99b zt0{t7sc#aQ89+1^qHH>Xt6?9!$y9`I_tIsYz~J*mv84t!Z*M|c`+SJ3WgpQ0cv6LB zbrOoVd73Bf=fxU9$)vH0Kc-MQr1x8{c!7S>Z+e^KsFgOT?PgSGDCR|-Kv|`?Kz=X5 z-@3(hCob3lR?M&w)P;_ z=FHrh1$HTt@9)5F>o1yfn*htCm}tnt#`AmPIKvg#cuW;%xZnb=s$r)m*M5lY14n9+ z7&YTRqa~vY>8}?hOK#sr7qUNqWm6jFB;4K08xsXYtv`&PB}`!-r}QQ)*Vy|Ifv0SWxg;!8>Lu4)f=YBJVGih-OPEIBwaCJz zW(=(K6VRb6SM8fOn@7?>dMy`Dy~nz~Ei{zJouWPd0{`9eyvk(7g{XA6U8d2hU136s zhAIR%u}FFH`{498gO$G1dX0M1%?b>eZQ)rbrMJQ6()4Ej9)V`J6rYP-+vC%=)^Ofn z@)NpkK09Z9LB4cROb32H#GbA!8Qwe1NF8Fp9S{W$^&d(}!-O#hj>Qk}Zc7h?=lNa9 z1fB)z2bD`(8C)HVmq58ay#~V)Ohq2FPlKI%B}}{{CB3&7gM!b{F{_5C-;y&OyX#gN z7?NS?1yE+oju5DSHB1y!OlvS}o=>Ks;Qs1Zd{qFJKeh0@4`Dk!STMCZ$_FcB97k1@p`?e$z=fX_RG>e&%VZV*Z5RA$4CL6j0p6@` zL38-=R#L?PzVjK+*GgM8SUeCPePY?LH!skC~E>P}7;sTtXhL0Lf&Y-DSiJ z{Q;d@UZ#h`2wp9Dl24^`)@Am_WO3w_rIeaNO+)?CmRcp5a=d7@kDU;29@-fSiR4FP za`>F8%Ou$G_^k#965*XEB&u!fTdz1~K~V|8J;aLyE?@AvU4a{)0;cahc0KSii}_6K z^|FQ2as76l!XS)4#Kj}gbVXsS1hnJVpqRJkJC-r?+ZNVIrk zpd&#<)6iy>3@Kjy{MCN{j#=<+pT3=_>EJ2wLpOj`?W=a;#Erdo@nOyyJzm&v&z-jQ z@%S3K+nyyAU!SiX2Lp|b5P~%_oSHuZTSVo_P2k)8(Io2uZe{j zI2qe1x#fLZPqz*`FaJRumLJqeFC3wm-$tbjiY*JKCUI&pn}z4-WKGNS4=3;jru10@ zOWGE#vZ>zMPsg)Md-wGJQ%WF~cp8jGpeCXWH_=Uxy*jfzv1t7p!cx=6PuBJO$%KHf zwi<_C4!#iYYLA^2-TM{D(%Nl4qW$(HlI&j>$U$ynA=YUsjpUC)EaZ?=TfKTy&e5sV zNS`0MU7qO1`m1#5DShP!Bk@}{D)5D34(*ZFv7IG*5cFp$K@;0@a|rW^Pu(^4I&XF5 zR^v*6uQ+U|KEW-DJl78sHo4FIWe5C5s`Ab0NVCr-4m$i_R_=o~P5vLqr<5=y1Pku6 zpzpNE*hb_m8cG}^M&73r>T?&F6DockLRWAIDjUTN|-t= zBu+E&c49k#du^?kh(PWmTU4=IAH^eyCCaO^25HDIeMg#GC{{C)e3|Dd?LgYJEH9Do z2M`S0bEH@M&Ka1GoGH}oO$rmgY1P-HhVf~65XLMiSl$s&%__XBu;C&H7-PJoUj@HL zUjBI{6R>n!tg2&DSg$}s(Ewlm#y{DCNis>%@=;)))Fu>=uB!*5(}rr5U;nHXq7VBw z*jD8}#$*ZRO}Hjfe1K8ki`QV^dt^n{F%@epPbGrG= zu}UDRU|Sh9YE~S2DH-N*F{qvP?#XMXlK`JwYLmI|^H;xwB&GAV>Doy@YNzLANu!3$ z{^L%&Eq^*9&-9NswN7iqN;+$6oD4d(GJPq5zzu( z-n)|FeoL-<13Y z+t!q7!0&9K_PN-9ZxD$`_iO;xO`~+q_|*wSnP+1OQ|s(_l*e_`Wi0BRPl<_e_&qM) zsmVC|$qxxt6C;tY4U546P<- zKb%A#6NE$HdoDO9Ge_M@poQ#bfJ&y*0o254K#C^n9@Cu3+L0qhJqgiHW2p!j>4C?? zHGWsC)Hq1)$m%$QMuw6CeBtAn3ya`daP5t{nS}4khQtRbatu17RBwUPA{WMV0NWi`|nxi|-eY{Q^(uLTwkE6~F z7kjJUI2Xj_j9z`3u)oR4b-kkno`>Dmk$bI{kz(e{*0kKI-$7dBe15-w-2mtmKbpOq zkP!svM8k^0nl?NtsdOyxxyk5(O|wj4QwGwt2a{{Zj;h|`s4dyE5r_WL+G^P%%g?f+9~A&xRsWmO557 zU`{StCV)W0#nA9eh8~S+Y_FQr50N>Fn=MKOwddjC8YD%~piEmg%g6$if;Y}5z!(*E zk`E=7JJtB3DM^K6b26e>U90LJ^@SC;>F+j~A@B}trWR^*j}#qd#<=GSn=(Dcm=*Ut zn$(zirp7I@dXpEFVV7TaYr11o&3JBcy_4`)e52rmF(}WjXv>Cz=5!S>F%E6(cbKd1 zf0@}G51R3A_a^1!Et@2b>>63Wo5-8pmKT;|C%EtSqJ>A2bL9&DQV0w&cp@{Ze&Muf z8_GMW$Dc{sJJdO{n?foE(}XgYBd&fP$%gh63Ur=jkO$G**2Wx=D0cUbE+whaZ>I}a zfk{JCA_#PMlyVyE_nG+|=BcUr{f=NJgl>reb>|X` z7`Be#R}AB&mlQ6c2ZzlwSnX~jUuG`4@16~kg!@(FfBax)p?JtCK$~j0^cRJcy9WMe zuh$}9`ep9@?tMUop2dcZfQblcRq}(jJvfXm+^LrI;Tyk7t>C1L%)CWbUv34N_3kVG zl(arh&# z>@YBTTM20No%Y%JbAmq+KBWANvk2jap36q;75qL~yPBG}^WH26lq^itx8wcXrTbv} z6<1gr@%V>k7We+AP5UaFsU?)BrGl$c!)_@8T}HAw1%@QJY!Sgv;zinOesernoA6WH zcUI@tm#)FH*dh4ciTtaJ|M}(~LD8xeGY- zI!f&nzpS+s8w4Wov#XAEv%N;PG!eL@+5e1b-aQID1Lsvh2S7z0${6@U_hvM*y<8VJ zaiKtzMF6#S5v{qAxoB6wG)n#1zIKhHR$y72|6jbfHRN|LTuHXqInPY%!8}RA4+sgB z>4Pk;bb(V5asiHor_rxr?wI=SLve!z%oWt4gq&!Z;$i$Ir`vh5n@@-kW$LFEM>a|4h7M!hIdCS>NH^Ecv&&){8W)zDAKkT%Ae58`_gEbYOEz! z=X-2BFR!ua+D0BxM{%4u8aX*7aig5|eOo6+1XL0^VOjYRsuy$r0RYQx6&}DeHMke>*)(hnf={Dxl**6(S61oFXYWps%W(7zSu) z+7H!@XeKzW`@6MSkEScwI=1bP`~+Z29!<(DlAOxmN)5v_EvGSHTU}BzIjM(`_jOtL zABlgeyrO@zw6A%z>+mDztmphp06J`o%YUX-N2^zxOg@7bci!4ETvB&z)UmKuZ^6@X zl3Fu$JD7n>JjP>ik8Xrf3W*xo>;`T->tv#EQRZ2@E!RV$C|&=-5LqV5=}+T0E=$`5 zb#B(y#kOZeeTWyJq)+$airkNzb)UUUYq#kHJkd|hDS~Q0`DghPH@Dp0)tzh|%$lCL zXx8hUUf=bt5wS$ASwDt}o|K8F_lu}lAKIJe1CeJA|94b&eM?`vI`>xr(A1sRi$$nL zX}y+4y@WAP)n3{^8P^a;pu@!+>ErGHp_#OTF$)?G=ir+pl`J#oYbolAd1At0r= z;cA*Q*zm3J6TrjpGnSxT+MON6WS~}Qur@+aBA+q#wUc2DC`7=q_+YG+_IG4x?6?y2 zQ6ilF@<$YtRah1;N1KH$P~c}al!4{|jsoLf!0$Seb;Kokc(Gto91{DFfG{nkFcZ@l zeh&;c$nzj1dj@&rbLZYfhphYyIygJho~>^eSa?3nK%DYC^)sqywk7@^G`#a+;0X?N zod7Gtvzjc=prXh(LOnMteOlB^PF!3n`(>zJP2c*ha{df~L*4uk5CUf^@P>dh@Yy+5 z*)T*Dd_DY0vfQzsnJu=k##9;N4!B>!7LmG0MN!h(qj35;H>{Oa%< zFz_Dt&3vMEBNSMVYV@4siHm8K`Pdt#3W~eFnh~2_t-`F@P#T8Mhp0kAQ1u+=UT{ea z)EmBYtHl1(X;6m-G+W+$y5>k73$!X!qjt^CCD$yUgK^8tChUv}^N}CH!Jnh0Jjv^$ z!(q;PXc2CYuE@SQ+y^$0-R(5xbrMiW6}H(*lVIp5HZF#mVOJ(sGc!|&@jv!F*(P>x zfUZ;hV-azvId5j}e=O+kNmZn$oAwTA{vevT)Z}9*zzZ`6h>%c#h;2Z-v*^vWabVAR3^=?bz7ufTILoY5aMaW?)BK9KFSFXE^*%s{8IJJc*P| z#|1B|(QpFi&0M;r>BmuVng6yg=bB>2)(h(%xT=*g)nPbiYDCUkTCMaAp{^CDxge7c zN6oF*qe$!BcCiMRLa#g$e^Z*8XKt9;QtpB?{TAS?V-#+>>eF{`^R$c!GyH|nA+iCj zR=Il9WcQDTb5iOrW>xMp7knnuAex`^QW@k35C#Axoh~Kqc8lJYR3JrUB{n(*&Im?q z`Dh~QtWxIkLxs2;Ti$CqZ^;`gxq;N4{Q>pBA-}O>dbk6WTZLu_2a6z#CnO~65g&(y zwX@mjiJmKH>mr7}M=SDi9J#O2qGQ_5HbYi#P6hNOfs$F!o@88!sE%Dk6k>rwBZ0HG zr39$a!?ZQ*ROUpmAjI}JBT3q&Ews@{V^9Km?-@HzJVRgL(INz%q|lB-Hw!py@?CD& zlB0E$bwyh&85^86OmkE=!GU+{W~cPf*ebxI%sld`4YKpnVMS2auVv--c+gi-t}YhF zGw*-5chhQYKHmcFZdh^Y1b8=|K<*Yde*smn3ENqLY-VX*5BaDb`u>5ur7`3KwLy6- z`B~2E?8L|;1*1+?t%|G9;~MqC$k_fu55&z*zTBVNTHqo*KRVa9BdO$)i_&!~! zfJ4oG2{t-on53B{1-q-#FJw5orV(t{|9W;2H_`7nb$jQ*wu>lkFB+`5+x=zgF@1v@`&g}gmTagX*M zDZvyQ>$+8wfw}kxoVoac|AH&T#kd)}9_#)&pnbbr(qX^S$rQ{TCRT%{RqqL~`igI3 zg@XIRqR$y&fSN{#b$^@QNB;wq{B5ctIsTAyL*#*id_@v2{mQno%=zu)Asp@8&js^N zVLhcw_D3<8MkcKRnImqCo#U>!GsF!XgHO$(dW>Mwgr>*%LIPeONy}-m0QF$~3v8f< zUd)Ld7_TAO_1JmEf#+8N2Ku7lMXTTTEHaFS=zOYa&{zM-lXXyYf+KbZ8+gpX(2x-U zfkkn5@-^8YSmjQ0TaMVRa(-w$YJnP)=1+xE(V)TMho=*EAx_s5kp!ozdS!vJe+N))u=_l*{)b)wmu!%6G1>t?y1Ph(PcP9>8JM9R|kljdTDN2 zTy(r~F%+NcwZ@{=8n@JFf_TS;)tFdoNk%@lwO95UsFLk>s(Zf0(T}Q`{F{tY-(&Pe zkuGYBnR1u8;tU8!eLBct*#+6-(n`T{;;%dX?VM+W>6sT$()IJucx0!=8mz5d^P$n< z(@@Y*n>aWGf_83H>@Z0GvUUg22E(s(-@R9eJx{`KKhERafR}rnufx&~T1<4G^bjUH za@zz2Zq`_JrUjO)70@B?kvwI}A&^F9h?BC@K~v4~d}&E3$vIl*%SVT^a0wiblI+N; z8DBPh2qC6=?O?>!atR1SJc%w3mzU}7FeIP>(S$Y zU+I|ycN0)wQk#|wwssVBk;bPx&JEs`FvTe^J4Tf-!byK^Wt(e=#^K)VJ^cO~sRZcb zPz#AA4y|w*891w2r;IX@8Q?IDVruL*AioQ4J0qCO7#@jqU|#kC*D%H?UipiPc| zuguLcSJA6x-=hw8ilAi<4JHgm>Sd@9%5aBx{sfn$HAYb4DQob~o$ls|4r51`6Mr`` zKfsQ^y!%P%_qG3XqFQ!%kb(e?p|Kwp9gyqmxm<;?;7kDRLdw=s2CrSYp8O)Wk)xio zQ2c85OC~;+c~XZZOuU^B+j@jv*Vjn%`g%mZ`lb9WCN}YQ2$k8Idr1JkX9F1AOHA z2XIwsIt3w)*R$$J4jYbHVaX*Teb*|FKaFbZon_W|0@EisiH($#E>Lw422?EOFo@H+ zfgf!_`SJ7L3tUm9nG=;1<%yL2_KCBYs7Qzx7uz8=TsEj$3z3( zg4wQ%Wx0rDo5Q<-@l0Ss{wX(W;AJ@RHZw)}D+Gy3OR3dF6TR5`>1l@V24!_vJ4d;n zF70C+wD3k14N#A9Xe!0ki1Kj?cByH6B9|7ys#(0!$8l@1TM)3!)M=6$*l3tE%*)hZ zSczEm#Nlg-?NcK~xU<|m?<+Dl4?@AV@_;NDgRc^kw5T!k*_O$1)i+dt8>wl#KP@}H z(i@_u-haB3k(Z4BXv^Ep%tz&;e=ZKMw*AQ7n@P0V%21IAwd&Wrp!<`<})I!OA#?61MDPV;O+`JitO$6L4F*1(xsZ%2XWe3=6IOG0F(2OI=0zs{0dO|j3oKD0O=2IaWw~DZli?s=a6#$jMg7UNvE-;xt0hJ?i)fN&gRZL%F8#zQGWU- z(a=JHoTUwO*DvcaCWLIY-F+#hiem=ImsF(UzS#x-37<|H|G@Ks@-ggkm}<~LHFQo(YLL))~;1v!iOP@Y^vUZ>|A*M8LBoL&r9kXF`n0ZU6 zDZdb_cvS=6_}J}8O%|MsSjZfEork~94Psk>7wOY6RhXUC2}<0~yhaz#CUF@NKobPX zKAg(;4LB89LKSGX3AyVzg?JcI=GAz2*_sh!zUIXu%T$JU^K2e|#k7hw9`u$Vk3Msb zu;)6HDa)1M6Bb#4GdgH6L7Pi5C$zXCo`{0s8wj}X6ZO#=Oe;@6rcB6wsj)7h3;w5%CJUkO-pfCH6QG*Q3E{K{If$JpE#MvSyQ7WaT0V z)}4x*BA~}}t(ums><>k)4eZ<9mGXW_q_jyRx~E-rKcC`dPB!?i_XCa*I%mIJF*q9F zGMS<47_+OyFQ3>leq%O3f->^A|FNraHrD?2Vyc- zp{wOo87Waq4NYU^zR7zK;Em@UOr;oL+KzEIuRsBd^@HYK>|#M+4ix(qUTG@U)?>Q` z?Xj8udPoP7rl%$ux=Kwq!8?c8kRxS)5r!M06m{}KbK>&6knOSRQX*Nn%rz$S&b%{5 zXOReF@t9b-zRXDaIgY`yYlc|dnXAk~L|ZGZ3FOkp#^qWi+Ejw9Y6IX_$fAM3?{T&H z8yiIj3XOz;296_v2G1+dzclupS}sn&rGVvH_7^K*k-ZBSrT8x#jomr!{fs&3o}{JGMmU z*i>P;QVG;5FPLecmQ}yqMxkk|#%fns5r1rd>iG<>7-4LG=#9_#>#m}_50@~-xGp+; zE*nYaz5jB;C2c@h4Wzg|ejaZSmBi(X6JbAIDN3ZxGs3vEHJ9MAy(mw$zw zuk2J@j&FE;CIG(Ok$}EY zEd0QsxzlFW??gS!%>O}H{3|;8wtq$#%+gj8kOh!XbXl%U18p|=g>ev*{OmMhqiXCg z(M2>*w5VLSFJ_e8+NnASCT7*P55oC8ACaiTMr_F&AS+lPz-S0eluH&9eM16!R6ig9 z1XhF%)exL|>!A*6a)T>#56PM_NkUOuL&10I z+1LFVq#!|dw|=yFGwO~(LALvfL1WuiK5FjK&F)ExdR!xSLsUJl^GcR;waZ)|>&Kg_ z*Y%JxW}E-|9wp=A!D`1v)PIVaH+}TvdW;)#aZ;vDuxY-sz4aFgv+W`ug?~qe5|EpACaYYw z{Gj?AdaX(0+znJcxp?4f87eaZ?V1pLp|P~2^jYh^ikC@DSw67vq{%j4x3)7fdG@Ix zmKl6M`+M6fv0<&)!It=F{_c}_jOl)2+JZtjxN zHAGH^N{uneptT*vyuaFvK`;>aWWp?)2u@g~4mudiBQl;eN=a$7J>gUGD%;iHHfUJ- zR@ZgNCppC?m=oCfD;G)Atn-z{d$;4Ho4gKlX{99Nq3Ho;h<}&{yLESa)h!j8Q9e2d zI-C=JG=cT=fvAFsac*bO5kQRdog=M!|F@a_5qJ9s-DLr}_xJ5DlH67d{;A;C25kqJo|^?%uyj!6Lo-g!86Xf0=KKa#C? z-ocW|LhiDVd^F3}p{tsmAhb+X+R-LuC*xd&$0|ar*+tD@qj|0V2>8J2Wf9SB?E;`4 z)6TO+G!o$FP&>OeZ*SZibB#z?w@o>0Ijgy0b-uPf!wa_eS* zrZU+kSS(a!ZL|=F?h2OY1bIT3?i^^`O0{`iNFR)25wj+$%JBN;)D3Z}YzS>s5ll|> zU|E%*^`aF;`dICytw-W|+Co@Oc#^l=(NoYPu7BW-0cpQuwX7Y_~LwJ$L(kx74XFVz#|;ceUPB_{n}yXB-xl%eA1SolIeD|jEL5Ihbh>a;Ph}T zd~Hm1>%2>vI{2l2Xs?*dFC3}d1NPc<5YIuV?4!BSd3u;f?8&kE^`7L*yI|U6jbB|l znCG^xuoHUte`LcG91TMLX6`m@k~M&+(m)&ji3XJNUL@ zFGRrBUas6!0=b=Z|F=F9q{>thiIY|)qNTXJ%qxp8ANK(rY zQO+XwCU$Sc&uCDnh76<<83pvMupT4JXkbHVHJ^}55u#T58PrOq)G}C1eF&@2eSG^>QRmsKgGnrN{I=E3=iYt|D5PL}v!e z-O)?Te426><-lGp=z1 zE%5>vDuxcM++WHp99ytUsmf=qvhPN)aRIK}e%4#i$7-xhM3X@C-_8hrqJKztNJyPj z^NQc~V$o=9kU?Oi{7_TSf2nNsA28cI1@2Y3W>_Z+w;od;JK)udD0N^hm-@@#G2_|( zl8=b7Co3|-H%jN#AKRLVOVx?(xFs%ZA-l75our|=nuw=iY+P;oYeCEI6PMbAyB_J& zCQZ+aCd#CT)j*j299@Fl(tqlr9d%y={^Wb=W$AR|PBa#Cy#-KH_{{twvdxma=@hTt z_DO83#S8SAti(f43m>WDwmjNa>$Dvr-|bOiMZ>WQ+}CgY)e}uiZz~Q**#lR{6<0tw zS%)q4%tv3Z+hiv3I9Z;n0TVl7N}&(nl?Ip6{znh{*IReJaMUco{(pSvlz%C98>kuA>RI$e86*!m&?UIm zj6S1K&4#Y6p&hGoT`hK7h{}+o13*SCK{$Y>8<4d`^rQ_Q7chAT4co~gkjR6BMPyIR zO;qI_q^kYN!QwAhL4W(`ik&<`jvO@3<%>+HB?&M^TF5YW9AwjF3aQenpM4XvN)MV# z87L4<$C21FpviGVr|ATZdB zmTL~6G6auspI*mS-TbfobPeQvaHt7Vh=0zLhkRZgc}iLKp2w?p z%5-YQ-FE-QmLoF~n` z4xTPp7^UxxwSVPDUC-e|d9CR>xmkxYv+foKnkF}cta;I(Tg!RU&7>E^0H|3AMpk)rM z4y`KsXEXcpu$(AE8*$SE4QB%pS6f@OwluzbXQ)qbG=J60oMzEr*WMJEyFU3G|43Cqj^>JxGyh*u9* zwtv)-Gk;H=t3Ua2DkpivbQhDOB*o>I^aHoO(sOoy_D`vULV4SCtrC$JC%t~gl5;n` zO40tz0ZgqLmm0fo+hp=N%_v_P$}byFgvyR8_>|St0fK3xq62Sew2g@=d$#3PD?rUh z+W~E*{P_TnrnA%nJ`n@zC8c&-zu$ggQGYfA!Me!{pOH5hb|#7KpxzV(x5U81B)Lw1 zDxWl{f5<6NBSN}vUxo^Y6+kP)t_IfeMSI6-)N7TgiG0Q0ISDkrVnD4vEa%yGWICQ|Sbynx zwpG4m7#I>~L7zBYG*Z9YI9>F}l}^)2L;sb-B-SS}>WJg42b9wUdoz{`Wf& zx_ahD(1nB1AguA+GFd*duS9+pXA=OlUhL0+mas}M>92Cm-)sbl=d(jp8hD#}1gQ?beCZ01%(IC*mI-`0tFCF*Y_=e;;P*EG( zvQ^MVA;^(B&dHr#wMsq^Jkp+yK-(*(af=Q!qTwieH0Bk2Ol8sIU}5nTLyvXKYIH{1 zbe$`KrtO5jkB#yw?wtvVvH5~z8E|rXgrYF|+ilSz$+Z1+kblA=AFP964La-Vj zV^wwH=A~9UQ*kjKB4T}Swbq<~VAWYI+mZoOm_=oOsJauBWTgp}LtHUyxUdXpg^c0x zAM3UbA7!VZh|b}1t9z6R=3GMav-yB1F$LP~mHot`y-eF@F&Pk*(SL-fvm32dLMziQ zdoL^p)3lwZYXQ}{_sS!EH;ZDogoP{bd$5%gl3B2J++tRE{UFq*^ACP@**ORSFP5_;BUIXly4kZf^$}{nT zWm+CgBHhYEwzU70&$U#QZFTBSof)_30_3mkYKxYTR+#77Zr->2Oc}&}h8^Q{{%VQv z6DHU|*=Uv(rRZa3*1NK>vyE~BQoyRTRZQ8SowCmx`8653;eVg0{*N{*CXK>ok|!b5 zFev?fGy5amR#z4n36uCF{EU9eZl8VlIlj;FnE?1^#~S$Os?m0%NWjF5{NdqMR017m zURMx^|HUHy@M?<%v;Gbk@bH=yKJ(1xN3x0ypbUlw+G+N*NQa6=u#SArkEjm)?1WI0 zo2I8A$><4=A%9!_HuC{st6~jEtP{};3RN=uglIeaWf#b;Z$nGy9<96h#j}qY;FG6f z8TzUb)CO`78SHhAvLYznUU2f0eT!A~632U0&6&X#4^}o)16HOb4=tOd4A&B^nBI0MBFMo!ct8{ADm;$ugTAgxrKsTR* z9yK}5B0^X!bHk2(EuVbF?Q(!GmwsW{BQdBMfi6E-A|y!iCXmRjy8%07Vl;fSC-%S! z{TppE;bRhen5~Mj&*_y48e`6=X^kY1J5PK!&Ou4pFCe4wwI9nllH^!@Cr~q`Na&ShvB!kzjJ#QnE5!TjEuj zPvVv`Fb7LZINFlfU*Na^NKE4J9RGfH=+EshC|KMf6&M4 zT4-5{9ah`G+rH9q&xV*Z94cahW-}>3d)}4G1(7Al#M?D9=z}XTk~(=cWiYXNIpi^ff!d-AyR>g;Gk^KJ+4!aL>^GTM7T>`t?9g$N+@VX45Yg4nL2t&3 zUg-u6*u#v0^bxjQ*Hs+om^4Bsdu>!4{aljmd#a2f~vb`3`sO z;MTw6W`Dtirb+I=$!YT2cpP#gU*!4_WKaNwFUsytj@(6RT2^th(8a#Vp6)Z)(*b=|yO&5NlOYHevYO+{D|tTc6My$-1dOJy_d$E; z8lvI07I3jWdEa^^K^4ezQi8rJvUUJv*U!W}X%uhxI}&xr3bix1_6x@j3`n}0pD>d_ zA$=|7Ox_N)({^{o^D%>FtP&C-+~w0gn9v{dc5&8YQhl9J$a{uz=!+!4#E;*Z+!T58 z1-mO5A^LG#l0mtidVh3nX40#be|zW~QGgv-CtWanL#s#sj~lWR0^v!{2MaQ}7u#;A zwCxn~G#f<-wOJ;ovv1tA46{#>FO1z-{n)I+7zSh&v8)$%m_}~?sn~mw>uT3LzhPSO z9>?YS?q?N?JOBAb`ZfD$Fg+mq^2IuCSngoN`z+9O_4TynL4PvMByB7<*3K32L%+lm zm|O3x$rq~jlu3+!(@83 z-YjxyLwsq*d^jpxFJLVSsP@IqES7bPBNK25)}nl;FMl7nAK*JJ0goLG!n7I3_b~hK%f&w$JX`5Xk7UXrg(_=rD4rYj&-w0~R;IIryjMGrbi{Z>CAD6wy( zE`uIP9zhX2_zv~xU)IYnwbD6&H_LH*SBZNl1Fvuj@D|YXyp-Vop59*~-yKq@sDYEOyifw=J+N3R_HSj@Qalg&L z5rCna+kYg)O&?4o&9p!4@!ABWA%lw37Y;{xXu~gRIXSqRLi^xDRsw-(ibsDw_1jJE zyzci~d0wl!xKSH#(17>^Y;b)>@m{_Qe_~l_f0vo7JM+;8p>fg2?2qydAL1uy4q59f zf*oypPFhH8fZVc`oHP=*3r}&)DF2~&{W9gTIe#%qTgzYLi0875sWY~KSZc&i1_n15 z8V|hZs;XxVKkHo09r3pH#$UndPkF>EPWPJw>*PgDEMvsv?Fm=HED!|Oi--;1o8Rf4 z#A;&Ab!#=-Z7rUB@><$i`l^JlBo{^qY`G!N2) zq5SA?P-#8-HR$}loBbg(``rU<3^-ce(!9=`MWehQ3&y% zK^>Jd36zNh(}ODt1#B4*2a~C@T=BWa;>sSn&Ak3N8DS`k`n{?oY)B$3wlL}Cf3%V0 zk^EZdb6}f?qrZK8M;}bG`CS4Qb!dIl2c25&c73kwSPeC;Hyf92kI8Seuhccl<$u)Y z%@9BzGFJdUqu`bAqm+XNu2oL!;BD{_-a0$`cK8*NA4$rh+sv|(1i1}ek2eDkKU<7O z`yqHZ`VWJ@nYeJ5#FTG}T8Wft-^@n+5Pl~()sDX4YVt&0pAOOA^c&d!vC3twZ+Z`X ziFjRfj{a$Sw=LjDN8BWcZri8_AAi@;mIBylX8HjQGqkpz$8`d%|IVE<$!6juSB9%h z0sVZ3y%~4paYs~MO!FQR?XnJ@ym+aS-E3W$er?W``t#AEC!LB)AtL*!{mc~)SQHG2 zU0t1v$NOij^@+SO)SHt)mxFqe*kHR?U|fKp+0wwevt5Z@(bvrEoH(?LKoeEts>_1psS)d*RCxZ-3e;lT!v_2T!+v zGXsCfc~sj>x@mXL%GP?C*OPG$;C9SKF+W= z32$)iHfifnt$p2hf3)?U{DsiWYX{aD1hMWe#nDzmeXmPhB7beF$@$Pn8~Vgc{Yly> zk@c=a;cI#TxjkPJI}b`dp}plBFC0eQ^XE6a-h8A?WU1?$=V&~8cT8K+;MdB_OrD1vmARc`JF%ey-$DHEdK2iHDOob$6X)&q5iD= z=Y6%*&+-4T_dT!seOp~?MYH~z8r49#S`LKkq)5Smre^*K5tOSqDXoc!D21fOMGc`u z2Ss3wuG5^D1pX)o;zdMK!ZK7uaW&ZM^<%Al-rwo>8Gk(I-tXuAJm>7Q_xkx-Yp=b} zd0y#w7XV)DaAzOj`hY%{^Hp4qw{IXoOw{_$iuj_R=1V^w2HSz$``p2L+-euEtvc3^4t^iPRtK&HKL2uX|?jsv$S&y~AP7 z`|&ci&GQtgym3Eced)F&i$SB=;nNoT;jgv$+(0nCiUPSvJ+3_M7hKj7@cwD2$CRZs z!Ow@rzExGC@^o(#Rrdw1_~q!61DXAem%(AY_J8GSdOs>&Dt(e~DMi*Glyx)Y;{-YD zyVmenSF`%sZV64?F8KC*f7Yq)pXRM?0!bPqqhbRO5)diZpIleRtqX~um% zf&Vc6Sg%ih@uZ*PU6T6K+aKJ5gikk*erDs+>}N@&X5?c0GJ0ka!*@x|a#61PrTLCE z7k9a6_ntM{M?Si9g0yk*@4kK>*Hlj`Tz@>OjMZF6Pq;i%om7bEIB-In(brHB|fvNME_Fe(euSFw9r#rt@j<6QuF zv15RQCrSYRGFK|W*b}hq7vyl|rw6fXzn2kzw<`Wf3GWKQHT$YX-}vnB4$z0ufqw(q zbKtiVmQaorxQc5R#9ndVq>-7vz{Keze5(ERd6i+vBgY?JXS%{Z4d}tA#rg5vUrwF~ zsXfTkN+!pL%17dD$)wTC$2TaVJK@REM_q-4A)CraJ$$r9a*A+U#xx)gt>tNr+XxLs z_cK|nB@=U`?3>Y6f!=7mWM0Eh(0`VCB6*$$-E!MHp3k!GyH>*WWXA>RfPa_nP9Sb9 z8T8N}oxh@-=^Huku5dZUS>3zdg!Ht6qv^&-h-&F#{k@Y#(Ty`t_r$nor#+9ty=7+p zUF4v~r5jUoovR_QEk{3H*270@fSbFDnfO1Y?)#WlW3;&6Slg%fjW{XWw||5-AA7#r z-Q04Y!np??1_oISz!vO`CyS8vZ7%X^cm8#)(KoD@+XJ70@X7MnN6E5)Z37o9F!JLDTv6Xv7g8Q}UW9@AkJ><6+C&gEoB{XIs@hZjNu_csv7b zcIc0vJmKh#HU4Q9gFcdH#DAVfI~UtBTe9_R-$77^_hn2O!ZWxGaIWUGA>l~ay*B=! zefsgupm-xjRKydu?FS0<<{rhuy(dL7*hS)6e?>hWqWB0GpRM#p{Ts#6e`*)q;^g9Y z$im9R(DA@mjn}gJe-ZKbD)RScxj~d~%oG1cL)0iXv7hlAauw9hIk4-` zFPP~*7oEs|^xX$90c|OXsP4yUe0noAeye@(l41P?C&Yel+CQ7^okrr^NVIA}bAPyA z3~4+`7T$;C6HTiV`hWO-G!x&lnb^rO$pM3flk+EF44tQb=HkODnxx+nb7U-6u1+WwC# zInEn>DgErbZrXNQZR67yxa_>?^DQEz!hxHPvZe19a{3umlfPt=Al+z>Zt zpZ)s%j<8RhZ4bo115J8+wIyn_VBNt_V^vYs>;G;07TbSxb?Rt&e#{hGXVgQ* z?mg{_pOIAV=ps8(zxzdMIX>q&TOln@pF3xix?hqr+1&^_*O@c+PiJhKk`Cofj#t|Y zpYZP1m9ha8wSTu?4Qb@O^EQq&xjg%vKQHfnUGEMEOi&_*1_&%3U0S~7npy9d7+YMp z_eLXT5n;*6DsH;vY+Kki2~uZX;51~QSW1csy3=atKPkV1t}5b8ci;`0^pFVN?;g|=TrujIm#rUhiV?(u{{veY2g^K=im_Vj)ROc);%-_DZq z>g*{jL|ij>mw_#7pTIT0d;5=9QO025b$k!xzIFD7`8|ob$i3MbbUsfJb}}IvaqUhL z*>>29yuw4e^YO`{Yo|KX#%ChC(;wXLG~Q2`?tkQ9(v-$;j`s8O^iG#8*H6sWw~q~& z!M_hacUB+f%EkWoE}!|e2jb06pHM}d-~4}6kn!=38>xq_KmY4%K~MeR)7&sSH&;@B zACtD^4c_O}`_{?4+x0U1ffux*HJ?S^Hh3lod$ma8EBlk)Z*6Uvo#fDU_K~%Y_|zYI z0)JF$J$+5d@wj){zCKM&KW?M#yLTa4wC_p5^mo@7CQFW!juVGPo6OYq4PU9X5iuzo zp+Q!3O(!ab20-bK?c}~{`2C7Q_T#n#8Zp*+w}qEsX3pc&#w1O4 zCiOY0&dw^x(I!>sn$xJ1|CMk1!iQerEPqZA!Q1q^+pc}eRl?4d1C-$trEES+-fHR? zJHLG3%;L}adfxL`^Z-z$d-a@T`#XVdTOt{x|9YG;-AdBl`!GF|qt^LcoLu&(=~+l$ z^GPywxplFT3TF%C>1rpxo=-`zb!29^7OfZelY!jp9T(H7Am3FeX#A@zZPDj&BY(@K z?#=uEWkh`5EPISESu_wnf;?*hOJ9<@Hy{bfLwcHQjs z?BScCjRS!F_q`GEpGJV-*fSaN(Vkpf2_e2u;&Zf9U(eL%KDn)^tFu}``gqFuToe!^nVY&ByG37 zDHNCSA=@^JGPhBWPc|%@o!it0&9;($ucMld3oSeuy#3SlHwWC?Lub;Zf6MwV(_6QI zd@k7ZT@-%yLapeWk7q`TTYe8#mV|<`>p9Ad2j-vE6P@vv&b`M1U(SSVzR>GNV16pJ zSQ~xIX$jg&n}7GaEdyhE`hRPF;S)-XNzymsRIBP~-4R+gpTvt4-EX?-c*jTuCz|?| zp0OW}{~h`&B2l1j*{v;d=hBJ`%eF?eX@TN#EBUC&Bu#%A{d?mRjbn`Kdzx}dQ|GYq ztuq-?f<=N-uVH%99MJR$qZqnUI}%H~cl=6WFzqV(ofzurO!m_z)qll)u@j;AzLuP{ zmLwowtX`~0`V$c|*`#HW%OB2|SOg#5wO<}#{}u(D^tjK9#)H263RLBIo2hTt^0VzXi!j58uE ze92_WxAmUm7pmfWcz+%oIJ=Y*$gI|b(N@3$Qr$&4#Wj(zu=IVr-0>~|yx`#pu!l82 z1QV*Ddk-Ut-Zx%tM!@>Bi1_-9`0u)9J8?aH@}zT90!o#rZm_kGdynJ+anMt%<;P&N z)2jP!!Jnr=X!o@0xBK{{Bl*8`SB?=GI>%p0?RiWDB7_1aDSu8cu8H)0D6gHj3hn{-g75Fukal zu=_+869#3%rTcq1E+?Tw58^muS_3jutp>jmI7;v|{TC?JRy)+c63QMV|ycn5e=YD}RC$5z%Jnz_@7}tJN;VjY?T* z33kqjp<`MGCy=e4LpAJ^fPsrezv8Yn?yyMVnN5Ta<7R*+kIZCY!S9$D(D{Z1^&?j= z!g^f51jGB~kiGETG)3B^Rk{x6B@okwhy(gzSsmvJ_S-A36Zrzd0}rBXNKBtiX6`#a z;l({io_~(G=mWY}0fjpS2DrmN%j6M~f8-?xN8M)f3+=>xa#|9g75U{BQ-O zCm#G%Db$Z{&OC0Y4z>6Kl|2|HH%Kkmq1YG;t{i*Ixl@q`t{!c`FWkvkY+h;Wv z=JlO=k?-e-F@0#~}ZhdL0eXrz*W|bQzxbLjcWu2psn^z0QY?m4* zx8y+M9FscDDI+8!5lFbvey-OjIchF_pJO2T*5PzIjZ7MiPdY6R{ zfyOOwOvpi38Mf9E;P&7&u6)hij8u1&OY#WtB%?|&&zQ5HfpbXc7l67Hv>Q7k%zu6; znuzh;i-3phl&{$0I;3v*bA5c@4s2U{CDMuyZb8&A%_)ucpbpQ) zlxW9Ky+Br$L%Ciy5O$@_i|X03aDQ8(oWP#VQi1;-zYssg;1xy^_t2hJc28K=#hb+Rg_n_ZCgQ=T<;iR&%M*9oqv2d8k7@V zG>0J>b?!@!4@2P0S^IAn2rJ{aBkHRn@_$F`eYgt>cCAO|FSJh-{vjEIL1HcccUeo0TZn!_~uYCe=&5SQ1>h~hz8=~U>4nU4g zm(D9aaf+g!*8>)#%OCaBew{mDGt|pBqhzKnfN$vztFF^-NZD8r4$z+AUI(U;y>g{i7AfC)^D2}^AW zD&kZ)a)2pb@6MCspa)DctZ3c(g)R2ZN>8Ob5{B+uo{u|oIyf(Nk%=V4~UW;KCE?7;ud#I(mfMnYa;(<*#ed3Ndd z@HFic-g)c;a`Idy1I4JKzhf0%GKU7#qV3g|cIDMcKCx?O#~x zCeRq!3)RqtzkdiBvKFn<#i6fP(z8~Kais6KZO`#n(}W!tl&#@o(2j!s%vQj(HWDsS z&O!Q+!fG*h5|ToKA(54b*>e00+Vjg>T!~Ejs*|-hpGB5d|S(k{Ns%H zhf(p{qzyXsf+lUcY@tnApxZ;5eLC`!e#3(^mU=zsfoiQ`=Wc(H>J+Q2OcF<3>i z76t$nyv~X-+N@#%6ATY5;eqrFl2QLPGQMquqnf>-r|OF%*2WHQGoUKDv7pB)s{)`V zh=3&nXB_AoVCDM@dFKrIg48)tV}R5CTk_9@_yNpHvq+AKdzJ8^%`9+CYAo=kkpL>2 z5e1tm?|(3kM##wiZmVnBrmb{Y`VaZ?@{;UhT9#%GSchn;j~ITcE5jJmpYX({-^ zHfjAK2}2JauEZa=+jU@urnKVJ)DPZGx+xhHNva{3lYA7fI}@51p1u$}&k=hunf#sefSNs5Og4W(EKHc`apY96|P?89(sC@6A_xNHS7pzfM) z+=HSzTPNjqPSxtoMk?JCjR)8akeLs(q*2&*g`Ed6F^ks3ZQn_`5wl&sEuS;K6@=NR zDZy0ZNIqjwQr!HnLAnBy(AhtVHNX?+oPQXVb_Tgc&)lRH^VzW?t9Ss>XUoFr#<@{$ zz3@3DgOYeg+#&h8kEgA8ojGO8{Dt>;vB}!odGip-Ffvr2+Sb!Ffao;&1l*&s9tAq= ze4%5@7<|Q=G?mF2xL|w_UR!{ibn|qXeZps4CtaY7w5|4z=!T07J!q2%MZ_TVUw_z5 zVTnRX`Jv)jSg}orf7qcd{iCS*!Yms=j}FQliag@E{==_g1BtG(exP5)sI;naaT`*+ zj~6@M1%MYj_Pi3VtHfPE!)yITE13q2wQ`Zj0U{@$`Peh@&xn5?QQtB18cl#auZaXm z*s7gTI%9bD)-Ay00Tr&;S$Z>NQhyAjoEIF#rIIRSxm! z37TUqlOyV@L!pCol+g$QJt7%ym`pb){E@ezvSs?O9KMpkv284YDvv;p{qCG*`DD}O-LL;GBT z#FBj-K38Ckpl%~Vlk2{Uf{jeYBDpb3zc6Dxt3Ph{CE0|6v^c6xTr9em5;A&S6U_ob zOG23OA+;spsjKZFMW?US_GHaXjGuH(XzgRIk{2{65B+XsH3V(prf5(J_@ushZ zyao%}3UDqrBBRW-69PSN9|NbCqG?Vjo}3&5MN#vA-~uM|+`(4TJ#3NkM{z%;O1p;L zB2JH$k@@YysWiE9<(ty%e^tCa&sZzx5WLApY0D^9mSHaB-k?;tDW{*1Y!6c{tLTCW z#R)vZ&{njIGR%xHTYn4FqsK%4*PUrbbMTl@hOZLaj*4S%-a$jE;OF%oB1PBLDqXcGnCB!BVC%?9mhPQoU}<{o(d zYR03+-p8kSybAy?d3cpRm?NR$&aKG-tWyF-goUFU-~m`qA_j2JU^Nh{$%O=l0rAHo z;`?ooP&yz0B_vvcYfuwd(c^hkRsn)RxK?l@eMo{3ls)JNJK%O$Pb#BjXMq#r3)lpN ziqNWFD}nF?M1O$hpv|DrNs>U@LJuYbzNF-Pt=QkS#!9_0z*{om6RwlUXD1k11xECe z{j|JFf&DyYfrNAgL=V<|VyMAnVc^fx-#k%4I+Wg`@K4B} z!U`J^v~i!{WtL$_F?n(QLhh5lB!g&MCb@vLfQe~$7HET3kjW{zr@vq#WjAxuSr`>I zqKW7|>k|`N#5(z14?(vqChL-= z6?O`7;$T^VCipn%hD>4}X>vmGU`%`@qaZF6@5SRih0cfFl=y%=AWDqAql^Be zH3TnO^37FMsz8_)+%+TpOBUu!UKz^JiXc}krGJ0zGJ!R#FfV(`w&P&2ng&iBNWfs= z8}NgOXe-fJ1i2=QUgSv8P;E2#mOdGEx25=tyjQP)%GaXvH0Y;@Z79^kE{}X=I z!>AquKAXa|*4ZJsmV6+cErkMd>S)yY&K;Dv&x1p$RFTR%xu`T_dTA%dgXE$%Is;asVNt?B2Fd}7vP zAz?Et^JnmF#2nW(0inS7tY7L?c13fB z4`G4}y-3;`FLayx!0=ymT}n7v3`}wooX~Jm1n)KMYW}DdPINe`@nJM3sbo^->~h&B zhp59}iWa1%KVe0tS5`qvqB0!G`I(b+_%7bS2~23BQ-Olf!8XSx<@~}8FMq7a5mWY0 zbI4}Z2qQ`%T*(TiM8bRk1wHf+MU>B#^eS%?&oCNhYSnFHe2kohdw z=>?M6K93k_P&xcrev@SrbY*gtpQ8I5*lVqN+>#8?YTH62-H3$= z=nA;vt2mbXxt$;`6-RD6YK5^L0?ca@9y@-RquC;kf&nr8m_>>&D}VShvX>X&YW zLB8;>9#xzAgME$jsd&OdGJK=QJVj^e6ff}PPPDcKix0ywdB6mNMC zg9iFTFgD-;U19wT8Udp~C9MDu^GK_$m8B(F!R%pFy_GUext2t3s@vnL2;lS)bW<|1 zyO^XfAX5>#&gRx**|=O;%^)DNHbEOYi3Y%)eUD*^Hb?pN;D4M@j7T3e9##A2y_Agw z9@q`-xsvwHmFFRB6c5gLTw$PXAh@rIekvJoTO>6I*vK+0aBib)s0ZVJ1XvR@*Pra7X9B19T`IG|k(mxhm?4DEILe6q*YJBdCO=+@nV<>^i?cUQKA)+69y%wigpMXvLC$w zpWBa#hs1Kp1;r2KKe8}aKt)CUL`HlrK_uW9_m`R~21^G=h>cMLZtfu#b8EWMS0TPOWzLXG{e$}yw ze*;OGB_&t! zmg|utzV|4F!e)`o6AKEEX}SR40%1L>Cye3>qZMxGf(2OtGE?`!Cn_lu_~hYRcm=#m z>Z4^vd@L5xS!_12=OQ7-p$kia-0E*ScTC&5KCO=Lsg5pWk;)~lGr>yQ5>+?)%ZZgK ze3G?P;6-L(<2hxDS-49&0|t%ae{P0+GIFeNtF8nrFl_gHF6UpB#HKt)VT5EU*TbD^ z>zp53yKIxc<(Jc{tPt;Pb{z4!b5x<+e?b;1Ttg1a z9LZZ${diP-GYhqdHANUDjgA3TUeK%A(DF)%3^w448EJGfR^u~Oz}s_DP=&L^NGAxp%}*zby_x%C;O@(52KJ}{o|x3e@)qn8*hqs{b*3G z{?65uwy{Vixu6#-fs_-(3R!WCrWtk$17aefuP9)swgxIKt13*BKsyo$bXi8r@LKsh zCURC-P+}*ml4T0Fx&l9f3IRvud)HEm9E%+Kx}{yf(NN-ElHZN=|-wdLIoA=vbIU8`N)aSu< zlbzq5(M2g0f8J>(9Wzu=#)V?R!hrRB!-Udf!E8cbMV=?UJNBZne-=&N<--s!V zz3SSq(e>E=YJPCKb!!sLF|UQy^Pe#QeZ?C;~(Cit)X z2%Zn^ANd#tAU6QP89$Mc-|kGH2>iBIT zydZZ2e?%5VoJh#piV9poQLtvRg1)f2#mKLK2sNSyt}Zay5&uXd{2q({{EnoSt2-_8 zGZ8NJnb2ohN5P2=C1fj$`k5e;iziVLnoN?`rrrums`>|u2&mRmHYC0%Uv6Xbgb8+R z37l8!(MXAx3LIrJW>KUiF1nYjBZ8~c;YAUqe+_|^86=r_`|n81P`qLyfnhAQZlg-d zmm#;Yftdp*{O)gLpF#_+3UL+nVUno{Ve9HjhI5QTGwXi!yWb^!!gg4#Nlivw)n?;J zVnj~1-vPJiXy*Outc*^+@N5|fSJ1T7NHVkafE6A3W&05eGy!x7o4^_FfmWdcMNXHh zf5xmP1J9kq)b$f}1az1I$L9G|qK(2Z`Nq)8u$8>xbP)>-3FriTy@%X6D&THk7wP zL8vS$m-~ZZOKVq!U>gJD0h=`tzZdz=S%9Wr1nt45p)I#+5w~6Nv-)6YksFgX_!tZM zDAe)x6?huMRIH~(Kr^((^I5urWuhbchoPKf@|?KAddlyP<%p`47V-n=%jwiDf3E)y z4;G^U*iOf4-(0h3U5*XRZd!%H7L>Xth6HoGYcU7Jl`@%GE{gHlSF{y5P{b-1S-?h| zP3QsR)ar{oP0?r(ff2$zq<*+6z76~lWT;omn*us8+vuGLWYOfmOtfi1oG_0`VD+S* z`lHV!RQNt#?06RdUhQafV31)@e=h+-gWr66uAqgvKy?s~=zyCB7GpScEO0dVmT?zOPXIc;vUYA#@K%1`kedPu<{Kk`T3qt#x=ofs5&XF|1X`>RBkbC$ zs8)19=$u?g+-U-K-D$$_unXR(EVN;VfOd&~u8LZCM3tW^>y;oRW-~Lge~2fgi#mw}K&=zpmCGLkQw;fWhDi8&_L$Snc z{UqZlS;0;rVdxUN=M}ee70oc&Q^5uHw=jdZgFcsb1Q4KT%QjJKf90WYgUOX-FPn6` z0qzw4-nvV}OLS$^h+{hjSJE0RFl>di?b5&)+OLo;1!PAom!4?@z~u15{VPHho*eRJ z@rZcol)%Ro9g=olHj*FRL#l{G>`7okbrDr|EPnuQ&VE(cDvpQ=5@U?-ezg{5pkpdm4^J(bky9a8Q?NSb2lbAB2188xmMFjqRV|H){%2O z^5-&XJ`Vo<(~S6>mykOKSp?5B;=8x)I|ge41g?nqXO~<)23H5IsDF?Ve~P!dJ_a8G z3>vxgy8r+n07*naRF~O61~3OSqQ0T3epHtbK?Yq18xfz)%HKV=bU_9I0k?rd1}p&w zyA|?WECZ zOI{zKG#TX>GjE1fJ<<6-KKs6Ab{INtMkEG_nnXQS+-J2)FPD>dOMAhb}R0) zFi{iE&RxaAM26Shs+k^=vfHJ%fjux`_q3Y)kpK%NPBiY9w*75V^(G9ZoQZcS=k z08x5w&w;#)9c*8a&I}bufHbv2mN-Kcd4|l(WW#V9(pRZZUlsO|M!&8n?He5-i~TS$ z3>HXGNMidY@7mrM9_%IG8QRLmvv~y|%WPt=i$R1S*7z*wBDmTq z+UAM?HHSxjWFYc8>K3b_p2?K0cGPf8co$^svK)y~IR0RT_U6?@E1TE_2Y(*Qtc5>e z88ewVeR)BpuNN+Bl9mx&d|f320#Qw40Y*UTHW_t>{9oTDF0Fy;nd-W&0Q-NSYYLnF z=(A6@8;i-IWJJYi5>6dCpQ4Rsxbi^fl((ewC`)abMbhx{7lia}<$eBck*aLxDHy$lK9B zh9#+YU3V8S^ertZPB89VOWcexM89Yer&Dt3*X7~o?y0qCyJB1{ z8yvlC&Lx3MPq=D2+`9+RdSj1hm^gGDb>BDcEm^M1J$E~dV>mH6r&WLd$B6ifi2O|% zrx0Pvcu0Z&O7DAu@5?%qqlr!W>+*r0O-zz~W^9`7@9*Q&Ki&m^7dyPVKf@CO%t?S5 z2udKMK<$%}?EY$86U;lP_nDf3Zmb|g*t35#lz@X&zkisKU!4&@5{X3QPBA!EB`1ei zp4~|tl9`z-X;p~Nty6z~$@3brJ1#-(y=|$w+2q}?>uChYKRNj$zdUDSlv8KPEfbfd zoJLUP)@Ij^)2Q^R?2IS42e>aNk1*Yg{!4nhLl3yVpe_}z(P2eK-;*qHmEK2 z9ZaCm_fB6NZ;CiOZ78fJp$w>a7i==dJzIvkKFcfSgl5`?c@qmaX|fw^5310I+v!X= zC(Xh{QMqm5liq*otQg``iFrV_^9}qlVnoJ;%Az4-7MWsV&X)V+eNEc?liHYvmeIQC zkBG(BvcCtGCVKlsUSsK4VJsjq6@O;W zPsj4=MUQ7X6W;~_Ax*mU7fKCUXUXRylyN3Z#)TfHU$cL2#~|EYQzrW_dMx&@>(dKr z(VFB{h%vcz>gD4%TBEgFXRZGjvGF#gl;b=uO-4M)tuk5jap z-k&q(AD`4ul*2;ZQ`rQb?etA=)o2y*BN_4cBjOLy!+8}7BjZJ6I_sf)<5ojs#$0c^rMTXeAZE$ei}wVIED z!V?WZ)R97E*$ZDZxj^s{1Tn4ni-`E{s`!Se{No7>T`DL5x6xLjMG2j1-IFE*ueGI& zf5)VECW%+jo;QxGLz?Axm*}n<6N&NMU#cGk?Bst~p2lG$CTUCW3V<~No>qK3q0PwH zNzl?7>}Dhw{mGtF9--|6T%QT}P8EDD-6oQfV#`ui;)|0zc{uE@ENNvQ^Xp0nQ@4q# zy{anPP@+4-{FL=W(j=C~^_@P!wyuP-T!ME$1#CCU7%#^?o-l4`oQa^@X{@tT1}9F{Y*RaV-14ex zeDrY3Zu-`2KP_U*#cl3Ju={>!+PQUFJeGe&1SgJ8louxa*z)izw=La;9xr#?zA$^+ z9ynxDn})o`nzpv%j(ps=Qa}BL*L|cDaohdnZnrgZbM44bwWa73>6rb;xCiG3iso}X z@Oz$+iLxYL@{L_SR;M3NzMXEK%XuBxvTacG-@6N@Mq(8XotJ!kU5Jl6IWNP~?bmAralE0Tt{`je>mhK%^`sQ3%VUbV{E53fD@ zbl7#rU4DMh$(h_2Px@0)iorg<`A*$7@VKMmeSGT2y8!TFM_r%cNlFh5>lKJ{0we*a z_py6@8WU+H;TTbn<=?tx?g`^;*PM9fEXDW@zas@ce3KwXTo9$Q93{iZ9F~p z0tk6FAT6+Al9-Q4bV85-C7Z^LT>=}RMd`WMrxi1?ouBU&$?*jh-B$AwrD@@u#I6s@ zFvXLv;P_(#97}lKLB)v48K`CgF(*gP%16Q8L*8W%YlJfm5`P|SmxPXdmR>N#P6ONv_X_+>LelQjNHb9zr7`O6>AchG$K*q)kEe6s zuf~{r)#Tp2@n{$0TMhZ_){xkiwf0wB${al21q$8m9zH4g*luMbyGSJ~rta*09ZnM{ zxcqGN^l?%d>QHZ^OvHSd4Zs<5tS+){L#M|+hnG}fl?tWJJxY0f+Pe6rDD$9%`i zOmc^n85Ycy-jCDForF(n^U|N+<@UTk>-&rXlKD;3M^x@OwP`B*$0PN$sfj%5?c>!? zAI%@taa<;bS%~C#7I&uAOy2~Ryw`+1ad#g6xK0ykK4`vF5x!u7_~d_fmDcYPae9DM5(R+>-Y5ZRD=__|EdTcn@ zp;d1CDZd2{Fn24#FXnhN!bINmu91TU(XmrxW2DQ<3XNCCIX-!lZ6DrdU?9T>7xsQ5 zBL8+p{IoiHn(UvRAPax_)k6uTBxl5nwcbbh($9)&INui#!QP(Y26W-M`6sx+`}mZP zcLCtljznsy1jm6-6>vd`9Q+}`&!GFdIRv_Ws>twU1 zp|jEoH~JB}-1mPwFPkUWqDw+q!{tSn+?2@3jvVD&uVLp#q7ge4a!Tez-bdeKI1czU z*srOpeB|nBl6re9P<`Tpk0=|Qli(g&BWH~JuAIx;E{hup--8cnSZU^rxuxT6@9zV< znH-wGBN@eGZY8-m@{?bNJXb?FziG zsFtF2#*}{=c=FLo@^}o6vXUU3H{U7Z7{WG?;|LEmCi|nWia{0hJVd?Pxcz$}$X-#T zd(qBbz?)K_|Hw|Cs-d6J&qLpH_nv)dn~jK{t&A^=s9%~mZGA>eoq2z;Ga=ZQFmnjT zl*0C<13qxOgG=p8UpsXW4f1B3@8twbG| z*i}GXL-Kd0bXtW{%BtYxXxvK%A3E6)%>D)NxeQ~m06GPnICohxsw4!Xr#8vJp z@Wjmcr9Jvj9SVAk@97avf#cgGOl=32*Q6tDu(EL{{?BdCes5Oj2NMiH9w<5!0@_S1 zeLmoQ&1)+7E{sXt=g(tLOq(%aw5i~vWuO0uPOQ>yd3d|?!cY<8#XHkOMy$!k#9sP8>_ozy z#$`&%6y0O%Iv$5=S<&wxtDH8T#v3~E_C6qdD6OM`31(M#6wn)7 zs74!|8I_imU@a z7sgf1oj0-ieIGA#ybAy?cUT~956tnsTPgB&tK!{`4<98=^X?lAsRA@zvE$ zzh6brn_G~*KgxZay><6w3+QhImeeRXzj=!_rmqxVN8U2=K&!vL&*VrdF*=Wdyy=q=x5M3e*O7>^jRf)+7pA5G|ZK>E76Qw z-%Dit#O~MR)2#x{$Am8x;AKy<5ahbsbh^$9%Cg}S0}gVRFFz!UF7q|QINS%k5Q;u7 z`L>?+wfPPVWjs$qvb9`KEtfHck#~SSQ8` zt;-pHk%kp^UCFZVdRghCz08!XgzT7;rVw9TDXfTDKr&j*V5SWgW#sniL}M(BalY@E z6iRGCPb?WPKhE{F@y`W65~frp?aGT@6Rn;q+V4hW6*QBg=qrfvWX2e#pg%G#<+s zIJe&`?ikzkn06g-Wy5B3GjKzoz3cr5DBWy!*&(*u9L#oDiD##cqf57Cv- zS55uOzNYa*ye>b|fUy^LlJ*>zRg8VGC*&}u&LueW5$k*4^%nU1_|%Vg0pP`s0ixk) zAYt+PHiN|TvxCCSjl54u^8|E!!V1Ij?~gWBKlOxetmo747o*}c5%E(@s;@qtwv$iZ z_7-OHi)X9W{my?q?%A@spLCu)ZOwSAw9H9??4#A(`Rr)ed6qrObuzc-T38!*Z{08j zH64OJ$#iB7d-Jtq{Xz1yr12DB5m>$DzH@VS%w=BXn{8K;y7GznVkk2l4`eww>+31I zm|J0SU0K2O$$4O^Jd$9Ho2FM!YF2<{Ah#2K4t>VpY0-ay;BCSA+=~)fbC8o(%6~H! zHIulNcx*paV(0z|9SO~Rdv{vjK500u_b!Bq4`}B}quy^YKYNlUXp-&<3|PC%hUMnN zKgUWVC%)#xZoh_qnO5X-Cd2hpnzwbrSw85z?LvtwiA(>Q(oa~TnO*qRV_kEygrssL zr#0Kuj9h=$54408YL=XLu_5hTQ3mc9qQet#?;9WO$65NiG$lKj@*LNe59pLTw-|$* zhzX!CMK5oI59Fl1MxT=&7P9*Ke&m4iG<`y5d&QbEu|CH8YL=e1pYOg%Ht?dPo6RG~ zvrft{_{WUl+n~>DIRjfubi|UG>lbZzagem6+K_*@oN}N))M{trMoj-6M=ly*$Bu2p z)L>ob(%&>r$(lB|w)4l7(E#|+Ik%rxRvt8_SK-|jQhEYSvk>Fk^A~s#qR z0$A_UkTC7jluwQEoNqpd7;y?REhOL8c20kt2v@cxPqNb#hn0C_9yIKY^5EKcDxl?) z5#+ej0!obGs+<2aA3=H(B)laaap`V8~{J#4x@Dk%CNeG;rieN&s`W#y{ z`@=4TVO-}IL;LT(A06gMY`kCoNzqtFR9Rc_v(Jsmdj+vzY}zPr&7G;lI1`llMndITNo32%lbC5 zx13EidRDcTU88@|WAqPU||{ zethZP`XlZv-pPp54n4TR)*vIsDy@wrlIQLy=qe%x29Qp>Uo@9|YVQ<+4eVp-mv|YX zPP)$u zeZWxLnHCjW)O<-YWVd&dfJ;B+tJu4ULLZL#2pR0N(1GFLHZPvf;LZx_teGB#EbwZ! z!oMjwv(K1(0w-`@_t)=4#8*eeH%7!CP|i8!!SnmXW@_Qz;Ai(o{aWETj;mqfp0nKiXH2~z;F(Z7`M6dC zE`sH7lvS$Z8GyIHyI-5WU6y?l$umQ#n4LU5A^`ip&aZo~ah%4LVT^^>X+G07EJ?zL zQMee1m;LKPsHHFKdfR`APkQ#`X#8D*Nb7w1MqgicIzHD$?!b&8I_TK$dCH&M59M=p zu>smSW_ReZV1FJo@@RarfqmuQWkElN+}7A-=g}5^;lgwN_No~5U<5zx(!XVA{E~(= z+u&Fw8n%tV4q8auZD8YVy`9_Y;?28t`A^Jp2IA?d{KH8Ch6Nd+TPPz5-h$nVFL-ywO ze&L3lbKmtD|L}*V*TTb`FgrmUBnM9}yfP++y}5r{|17@wL7z+Bqc$n^r*}|8?r2js zE@ZgbVT?|r)qH<(7s&iRck*EaIPExY_^TZOq6;~dt9Ih;P@{pB$l)alq0sc_Bl1hK z;^$pCbGOvQES$I&HgMmP7YW3zb`yEeoGLSWc(Q|gyNbp?^3BUW?)-gx+Q+*9 z@M?zviEyQuv0T8!#KHoaO>)q72g32Y>3+WdNo@6uJ1~DQQd#-r7&ah-cT8|Z2Tof= ze6b?Fx+1YW73DX5505A80Ak36!_Xhc=tP${hDTwRat6C~EKt)Kl*;@Px(3_3_E)rrYRnx$Pw1h984)oE4lIk3fS5OAE$s(-F6vEU#ELkN)hP z0)@bvN~C`*naGFg$I}iLr(v&}am!sTTFpqZZFfGu7h3(X=Fa@nHeHt$81aBxPE$zM z@WZVW`scFoL5k}tbsrPr?O@i=y{qP4Ne8c+MyhKiPn$;HUhCJen(mp~@C8qHtj*YE zupEYVUH3gMG~mkVt1kWG`uV&j(y@{`Ys+DFqE>&?pDFKBf3@$oc90i`>@TE&HYO+c zogSjioje9#W9Y50mXic9$dp~=lHIWXlC9&YRV*C-yBJ zV|CW>&2{BcfFIw71nGsy((S@xnY1v$>{erI(ZzS{uy1Rt+|UY;m9zzyH{^5{w_M2T zAHO_99t@AA?~?3NlJi|pgMW(=!)_n^pQ?XI&=Pu70nC(aoU#GV!)MJ0&GUadBEBh4 zZu`aZt7UlUF=*K_?Z7Z%O!Sk|VD3phnj(k2_rD%5+3g@8`Dn!Y0E zeSCVyy8!U2hb245kp&y7N~f)sDavMVoAbnIfFMqUU(5Dyq*e8a&sPr+K|rwac94HA zKWY8tYTy0-WM+IOB0gU+@Pxr+^lNfL`yDfR&Vpq;{Pp`RKCcAR+Pj=HEZMA`D}1Pf zYbC&gvj<}YiNTn?YzqO(^=?6FuSyc|pZE?1Q1Iz(M*Ag1=k<~^so^pI001BWNklhJIp~PBK`d=_P-|l+4CtlH)6|Q|4}1>%4bQULmu-&l9zs@cGK* zuG*K$Ei1=_Zv^fznygQk-JxOb4jQzR<|1DrX6mzAPV~E+bhyHwajtL{4 zHf*4VL`@T%8nT40oj)&Z4V+r`_h`d*19e$;KaN(I%NTr(4AywuJ2HlhsQ-U%V>}G{ zdyxBm9?g5Kf+_mVh}>B}zO8xK8jKBsLRT**Nz z3NrXI9!FR!-e;oOG_{h)PLDEQ?SFY4w7DTHpYike$>|elw*BDrc}|YWd6`N==f`ls zUNc;6XRaY<`m|w&NKo7C!J&V1t_+d^qruGH<&rL_zyu7}ZIZb#hA(Bc_8hi!&#+g+ zWflY-2qBY<@LxDM58NerOOw0s(8g$kK_Qrvq-@;GP=Uzs3%$6`f_iXX=T>gqh*#l=9%Wd-;rMU1jElYyl1mr~I_4IE_wgdfy8!TN2e80{{Q~)J#zv^l zc^f^i6}ou^1t!htE7gC973~;#gfI(0QUZk$R7)#dBPgPu2C7kHn3=&BBjTI0;vS^8%B=coG}2_>GW}^ z@6c8{9|N>;Rj1aqxDTiKaoe*6EAYtv@!jsB?#(9MHpXg;8=ZfRbp^<<;BEGVwlsan zFk|Z6e9Lv=TOY&v7`kHOV!T2I*58mRZ1#aKCQUi%^OeTJN<=MrnlSSct_9{eiNlyk z*12cK=M>LN_OLJVo3k(470wR<%n>p{Z%#T*2A-sr|LyCQ8T|cb(0z@m-+RcMtH898 zob5r(=5y$aHl%+Jxe`cP=1c$1uUIsXkiR*I?*t0=0Gut^3}s}KvuaMuw&|K&#|ui! zdaqzoS2T3v57*7^TvYT6_KV4hgr>GNcC4Tym$7$VC}`kZH*}tzsN3%v81Tn<;?F5E zAV~+j6|%Pbjx6gW;TO$#QKA?enA0-Ye&s;I_J-+Bmrs8>eL_*)k92Rg!*ih3erY0` zUgLZE{Qha#DR8{768bOiBO>;T8Ce(#!_klrVq%l9NxL@(ZAp6@_)uY(p#I5gE_y)6 z!27!547*zWxok!OvWdykFHxMf_e)GM5_V^B;D`}-)7s(gvFifEPIe3fW{fBa^O6ZW zayvHBNmhStBVC}DZFUzOFo0h$^7LU^UMg;`oty-aMpVcXvT^-DSSE!1NQ$#)Ow9Av zC;2K}!cSVdZM5zFN>zQfs=hfQzUT`Q5we*R-zO0If{O6X2ph(LcSYpr|McB)py_+e zOHeQ`7n$j1`!eL6lO%^{#1de^vFEk(>V3S#@h*P=yxL(wYy_1EIu--%0{M{?Fww9E zA;7Fypk;xMiIRbaR~9`8kj~QQh|<=d`Df4$#M!v80@*KA#%C(y`y%4^{pC0L(BGIm zJp}2epj$?}-&>J2b07!IN`(C5%vWc95EW5G4@J+-!p|TslbP}8* zy*hs<9tQI!pR#+{XBnNw2SbeUqF83eG6Y#;MQYe}g(ZMmv2gpo5}V~09{)Gr*I|K; zfpsS`CZCaUSkOmDdl>f3zKZ^M#NvaQ-CMK!8C!m&G2I)p@_iChSGoNeJUPNZp}R2f1>^lEnHRWyI_wyVZ>yy zT*gZ;ETHxvZtwo{cf$@B#_C+kpT>$Lc-6qJqQw0nTOCCXk}TqC5VU>B1Y!Dg)}?vT zOqGDQnv-|ZItQ@k$AjNSmw>4jdPDI{VkX)5_`T&%l6yHhm(RYPx z4ZQgnxjJ-yjF6F+OcpHW+b?DedFSZQCsvIf@(VKz`Jp<~t@Rk|D1#ObY>&KVjvN9) zoI5^_@gJ;g`yTh$cJtJ`nIcm>aH4-@o>;38LIVrp=P3pW*U+yQH-@UVtWcPq2*5Vk zMUc6A0(&X7H|)pbjl4G@0WW^oKxO*zU_SINIl|DB&1I9GM-oEVhj55;6g7X48Q+%` zpUH?{;Pdt^Xyi&~%%@*UGAsw}mRwi28RV9!z;OpSSg;xMTi%GrHclrAjMaaTw!oqt z7*zX?6)752$br9aXMZ1`_VF$Nyx`$L;{kUhE+HTpVCS6}FphHs{l3V)fh5sj5ElrP z_h0J56H>nQe_^l}6gC#Hs#*dUYxqYI@qooPwaZ>OSX28;Z6B<=+O zV{*o4*x+fVq7<+iS${dMMR4~43q0n3UOdA1g|@&Kry-}$huxl0q9a1SWQVW3d%qaS zf9(XT+1@^>AL#Q8!onUVp(amQmy_*;KVZu3CQu<#zq7Xn#nb$=H8o z&CL91r-%y!AJ86p$9)(dHk%qF5UXegdVZU4s`sK$91J^Hibqw-Cio{(>1S<0M^bh$ zgG!qOL(SFW)0c~rN?;0Y&wVq`XoYM&jbYDFA7XMFcj(I=djE;{^qW&KQ6{LPB^!OHj}myv1)g$jy@ud9f! zjEw*6w;*cmWy1<(~$zo9V0B*rzQKRG&`m_KI`l_&k9^*VF&`2nuW7&<8 zq`|9^&mxV>6EgJ#0C+FfC`(TYkd6%5Tfp%ctLUYzl;DXIKkH_787StYonu=+UzUHg zpr;OWWUpd6jgdGAa9JrEV#$x|?pclW7@CH#L4_suQZ$05g0xmjnv>n7okX}dLYw$ti-bwNrz zQ06XTi!;<8CwXSa4(rhV!Ye+?gw9}pm>{&kxZ}p;h{P1hDE)ze&q^3|T#L*5g8B1Xv zCsHZ9tdNdNya=aUpyn%PAK(r5!98Wy8JrZuhJ-?wa}B>IEzqx&hE;wP;f~wL;piXi z-~Iykdo1QM_zWv)NAsfCz-WKll5z_ArSp(W;XHU2zQIR%wGHZ!oRUup$97l%GkAPx z?%F99^|giFwznrJviNAW1QW=LUyX>biOSDL#1{^2vru535L^UEd^UXp8<8hdm?j6x zK)lSKmIgk$Fb)><@S>>ynViA!mAkq;bNp@EPy|ZhQnpPVY$^KEN2P!8_wnf+?*hP! z9ZZaXOMTW88Thsb7X0CJc;$|&pj}TO(l;Z(ANhkVhVm0L@@@_VfN+MSN*heoI#Th9^J~iqRgNaG8r#269C@ipgRiIr0BWfHsn| zR6nfEk{_)i1LzrdTUdVr`m#w%tE7YJ)(ODgE8}Ao3O6$-B*y^pJ{hA<0!dJ@TF%v| zL6ZeCCNieuny`QLnVh&HzRD!3aOQ=qo85%P2i?N^Y=e7H6O^l3!fiK@xv+72pb!MYZEr!z8-_ ze?~hRYtThZb|!}iCNR8LAiMMgjn@(riSUJb9F#qBz zTzgSE%`S4AG-ZDb;$#Ev|DG6^>>MlKO}|f03cFsab!N_i1fDkDBoNwwpBVvY8#3=IDQpd(8{t#IS#$)*U7sD2%b-*qKYpzEnE~ z2)qAw1anuELug#nv7C=$w-{!UV&NpzxcNWDo#qj=)lzL5mKN;Fbm@U;kemo6)8DLM zg`CQb%v9fn1jh#fJZz8)HAVpA5x^+r*E&pBYvn~aolSH5OUcT#YY@E4hJgOWjFL^sb7*c85wpl&%SrAK|nvjMZ z7QEVZ#R%ZNc_ST9cF0ATvQC=M5x1!-E2yC`lW0F}(Org^9Xay-_wicCy8!TFhsQf5 zbUq=rfMo!W$uXb9!+BfXQ-4YT0C)&kTA|S7)+c|XgHp$r2v&LtN}jaInkBsy~c~e^U{Eqawa1GJZ{y4!ehAYY1DM8oZriL&GyB8y?^-SzsPe-PVFP zF_^MxsWYI?YOit%OA1_cHjCkwtx#fcMD2Zoo>X8e4w+O3!oH`P4&H-_jWNSjurl>Q9-)9) z=|Q#wJM5^I9K!-7WI=uL^Y!M_Mwg6Yov?7M zmNO=V7#m3&CMK|{31w-03S;pV&xu#lo#g2#+qcD%j>#>RLA`)h66A%C9sx$`w1PgM z>QGhES9u9I(D#ca~XEF-iYZ6?8m&Sjd z0^PD_fs|>_h{iL@nDkHooU5_iY7d#hzx*!Be8vyT4K_(fJVM|Lx=e1w-=;HKZv_@q zK_3T;)G0!IA}=$+DxaFd2O%dE=d*QJVHoK;pf2Dy3+x)VvUy>_|7ix%fS#DZyOg^h z6zhn`>?WJvG+Qzo8x%WUSYdErk70i_9mUsyd%_JI>Ea`6E_UyU-?|qXuePf#3R|Wj zj?6hViW@Cc;DCvq{FZ1X57dFRU1|f?(w|~tWUIcV3tW|MAyHbEN z$1m2xzyL6pw0w|VQmVjtFRvF(D5r4f-&iRM7hrqbDVphlnhflS=6+eH&AIV_A zhNNM$@}|2~|^5q7{5uiJ15_eExmB#Csf)BZry1iph#E# zz#b#xVX;Dyyx6c)_E4MSIFo4JokNF=f}*PnK^T= z`+ii8@4Ob{9M?&sC4s#JC$mw#>%rK1cuhdc=}MDCStj-J1VK3>^LVT9*mIhIUMEa- zI#J1D_0uD^q`wpQleo;O)ERH+Lq+~vNS};|pH}J%^LEMejOC0ie6W8niAW_8GnHv7 z?Ox3$HOARKW1Ylk2PDnL-21CUYm3}&+>dN!kKqLOtTE&Svu^h|eE04ZQI%_hS^;Fu zrIPW9;%h$jTb;7amuppkij(*~%Jz>gcyi%E_^W;cO{}nWA`c<%)n*P)1b82(O z;r7@;to}dA?EHDCT!~xM{28B0w6o{6?IV}YdQ&D#T=XPiev18445{W#SE-t36&1F` zD#^S9Z?7MDVlaKoN}BiT@x9tGl}v1V)$268jk1w?x*#iYICH2zkHEs_UZ?W?)J4zX zxu}oyzY?o$k1?~R%8#r9VA)v9G)5OWul1KXDrZC0?bHaP zq}OuoIlnc=bZyjnj2TD!v&y%8)4beSc< z(mLuh$We9{l7EE3t#r%cw2~!}7-!s9nQeAI)$5F{2U~Ym5x;xBVrc3M%J^w1KB>%~ z3&n?*1$hQtf4QT7tA$#p2X&$~$;O-pmIocjP|1eXA#Iah3CH@3QTT>n9NQbkepPUq zj9?Oh*@(>b{dB?!9_{R+<`_!pTbcUVkbXj;PeMtHyV)yR{q#V4uI_A-vb8R2oyW+t+pT$=0YpSUUGc1$Xj`27LjHO0rJ84eqn{XG zIt7;bzn?VKsc;u%%G%QBIX?I)+_hz&Yu8q$f7kwF?;-!f&R9CDnfV&EXE%Ifadg@R zr*p6Wc{|_gz4*vluWOTNKDkHb{g0&Ugt3QO!LSnXoPtI5u!`^{kCJ`M(<~!xU}e=_4l{e`tZ%Ad8C~8yO`XPE?Ji?oj6zGvazV_ZWP!e zf9-a1Hi|t0(@S~Cy~V8ww8PlGEoU5EX6wFMNb2tb7%$ttqDll4FU$V8j@E&DxTH>gBg75EgzrZ%SbbmmX*)B3W@9$b)k4wzU@gBp8ZG$Sa%Kj=vI#3eX<@q^^>Bgew`G z>-uwMvNXu`b^=pZkn@bC`acfVe@}v1rxn~S>hy_SjiD2#`n{^=+4BmYSIf8!aORXV zo@JsP1jbfJS}{pZOW@pnHcNgIyiNi%g|e1Krk#LS0cM2P1sBtk>$&99e|tH#PN>Un zy9EpE9(YFyl^|BKIC||}q^8}cza64G;p&}Hjv0-yS)ZlYJW_qu{v_gI7MrYWH}cH? z$TZZOp!?*^H={j1Ti;KYaeW3WfAN8r%XPmc`39%_S9KXKpzgH&tgd#C-+W$wJ^!lL zM+E2R*r$x{Z|j~(Y-40!`mn()7nQYcOZJw$b>DO1HXFlh&6o9;?OB1hHY&^h#?iM& zT#B<|p6j6&LoKPY+13797cLoZW7=uySAXl|*eun?)bJGsC8G;NYjUH_Pn@Jb9&j>^t4*hHq4`!^cTl?daYelks?i1 zwFqv%K2zE)bv{+5(*2f9f83d!wd|+oZ5NMBRJoN+e(SUsQI8<9EGydwMD;bDi$BwU zyvM6w>3&asKv}m)vFM+f5g_-{!7D(y&}+ZkrT_VXm8*S#meC zHk)BK$2pJ3dH)fg$LsZZzaP)%h`GX*gH{sCIn+Ww3v-M(G$@F+^zHBMoE*3zXklTi zS+#2(ComqQo>;1@*r>1-L@UJINM9-ks^COAE7W~Ws1N^+^I*g1Qsi5Je?F~~Y=J?C% zGn|j7L!wILgKP~w?_X!aNfiXr>9Z_pEB3vrZU?iO% zs<2SH{^TxCe1`OU%AJBcRAg`AA6cju-*v@5QSsQlocvdp>JDd#_4yK(T-ms}0Z4}^ zo#$}#fu?^?_}dQJaxIFa6=|Il@smji_!(5J5qa6~1zl&a`=#&X@xz}?%NAy2x8pjT ztBqUaiucdX0r-fq=$PXH=$OuO0yVKDJ*RcP#S*k`{BcS%mlO@|+HAbz=}=E)>wWwF=Rj&Yqm{4&L_qCZ-=#$&-S>VxYw2{^V7`WE zE&>lwpWRrz--HdI9P&0|-%KgOrZrvg1;dX!$ya`GR6-IXtY6iw`V^^YXBY>%ceM?m zGAxG%i6qE%+SC7EHJ&2`>bX4^eP&x+R+siWQ`aX^JIe9J#XtVnCk&CRdJ>@ZEV?Z4 zn4^`};1zwWj0bNTpWg{FC6|vH4=j-KXVWsf{!N+uX*{Ui5isFe4Fr`nIR7~>-ETF=c6|puCzpl(G-c16l0KQ0BupOec3LBS#lEg99u3CPuayP zWW9GIFq+0{XX5rpPZY>u_15+G2F$I&+FE+^QIXRUOx-r}KhGT=^RK-Jyb65lHAb^m z#t+A1zpVIIHoaeGEu26UaQj!aEqoaxzduUi|7F|1OWvu?X;;XwPy5KPnt59gVV zQQ^TR#nPIj#%&EI_g zyP`M}{>N!+;tG|=bk>gR76tP?%@Mn^! zG3S|{bj!Qty4)1{n;F5x9}5ukBuSG8cAayq_=ug{nM11`zY_i_%dq(#Y}4-?j9v9t zD!kR-t7Gp+i^4u%46(QsdX>Sf@YC-()-3>kqh%lKZ&3oI#3)U({(5+r_-mnSz(Te- z)w9NeRg>2rS!{EsP?#7s(H4g-O3M90dY+xiH$|GvCH1-UH2N?x z+wmsJ5D>w(^~M=k-!`?(3cLesw`K;dEuHu7L&t!tqCcjQyCtd`Qddv6M@b#o!$=N& zfX8#R?7WgC4|y|Po+`Y}TVVgVU+!g^7q8VXlC=T1F>Qr~>i&gqT)SX`xCxgkE4(O) z(}eg|eWXIG?iIwp`L1EFV}0SJ;=^wRaSFm7N0x%Wu!7(IQTf6`y#5mm-05HxcXW{C`?>SbFozrOLJuXcD(sMDTRlbzyw%)E8SJnH*et~_K-^o*!|Y?)|XiE?&aYb$Fw zQ`JXc>e+?`+oQzEK>@}y%_|p89wY53gvc#x?~v6LKQPHi_VAVNE#D3^PgXWQYY?e1 zdiZW+vF;^DTG?@}WQuJGDUkC9)Ma9^PcwhhD<6AMA9m`E&?PZJ2N@Fah5SI2v=mntS0v!nxNpijhn|UT`we%!F*+mK! z%dK?BovN;TA4U$2VUXyFUFDS$#0cCQvO|aeOla+nO)vf~(^7_yvyC11Y?8#sn0w&j ztIlpyh{^j~{%W2PqkfeAuxm}ulgH2tdifUode+IN*D3BJ^HHG_xd@kEv*EoIg1gLhwL~QZH*{p?$cXM;G+nHNO2Bp5RVCS}Ey#%pl!2JZv za<-2&t3(Y`l9F+;?`%-^MAccDuw@Kj1I1g@XwK92(> z&DuBM{y%4J>MM$rMc?9{9)vh4+SS8nF%6;U$QT(vT=xe#Wh3*`xDyfQelq|&Rw2fZ zE#vumR*dd!ct2QB-!6mol!kvCZR&OFsNjS^gw3l~I=s^J;e&pi-?nTX>BFA#J}_?$ zpIgzRS6;qTp5@jU4qck_yFlzg#_MjqQxmb=Ka;p5YorM=*irUC+9*`%1}4Iiebn6k znKGSg;5bW{WMm1-@R1t+wEzH-s4ocg%e91bsl(?Z3iJB{psiQxxW|mAz;$uT%MHVj z!6G6u4IVf3(~H@s))GjfL_`!nY3nYD%?TC+8~k0ClcX}Hum}X#yU@vx-AUXC;F-c( zODDk)oW282dPwP#$A{{6Q7$c}85K9eXlS;|#nzKmBXd6+>%bD<3mpPfHeZ*@KiMJ# zuW|+(s>Y5;=hfcxpS4qUd9iZbkB-bEf@e^ZmX)05d9HQCif(x$T_=`9;Eu1lw(met zr&Q>S?Wjg{`&}=dDa=?wn0j{!c6*a6!w1XjkC&M%FICb;{bevt!}c9=uio&(%U zup9&>JJ8m4U_3#S@5==db*IBkc*|Yp1l^7192IngHEnOGoa!1P*|Z<*{iblwz`P96 z_|qb`WG!ZTe~rl#662YH0?AIDC!@qOeTBAPO*yo3P4Eq-@Aj3sQ31!_)?T}3S(OZO zd<2#OS{cR6ftUHOCtilW|1}ZwMsusO-ytyCW8`er*}F~#=9=KlI*C|~e&x3gv`O-u z+r!)tvtZ~I)yjAZYm+{8tV&(ow6GjLGZsL8ls`bYEi6W@=Q~gfV;avnEv+X>`9- z+=NAX1L2ELem>-(`D-L}8V76sAfy2hBmU|Lc1wB5)uRLIc%sq@*%}|Qb8bCgUe+~9 zDG^EM=($Jk+^7>hIcvpnKNvOINDaZYP@h5UqMO1ITCia#o^B9Ho5~{(-1QT-4t!)8 zTwayA&HJzGErDD!PmGIpxY9ylQij(=*F>MYjAio!7gR)l6J_}RW;=$%fI%u7>{&DN zi|`Wh+yM-AyM$47R^l{r;8ej9J@27J}|v__MI1PYM`gD^vFq zHY|^}We?+Dv(?fC(Pn_%a7z3iOViC?6|o$zvI0p)$XtU}AlJFLEL^nVn3?&4Kdsy+ zr1&%PQD$;b)M`+4`G04Nl{ZUuqABE=D!Qmo68;}{tjf)$Sh<^V7$=9MPKZK&4c0Ph zFeG1!0&ygy+eca%5{98)u5r7&%9^nA(+m2TqDcEk2lm6T&E*as5b45kKE<^oSuj{- z(ryc;ZKfb{o^kHOuGHlA|E7ug)quF;3qO2ZLy#a<^7(Utc-{8NwdS)`@B_49`#+1( zWH(fL^$Sm%XD*8%Z|=#lncR?pU~0t^qzM{JX9P-Y9fHWB-b1FtsYuNdWiq|OzTVd_ zNwX33<35A2&NoAM-y%+S%}2VBOOm-?ffj~RO7-~$%W)muwYn7KiqbH>=^ksL6Vg9c zFjJOAq_+n_Q#KA$QI=%E48hGKLSJZJO)NJ6yeLO;eG1Z)BCXPbe5fs;cdbd%%{qR^ zO{0+g#0{KKo&J|KLM!#}3I1F!g&fsj!U#4g4CJ|-G?AP}%*IePpSkrVK>(SV+~R*# z;g`cx=C?H`A&vrHYpHwvieJ)H;#pL4=H>&zF3{|8U}V&GNTfKR#0(%uqU&L?hOECj3W04jp~#$9H9#q~=PHX@FCr9x8>H zhDF;?LvQWIT^~6MUXLAF!=1zq(_q@kZ z8&n{p@o)X+?x|m@kR{*%Y%ZTw7_hUBLyVsdTkg$VX1rhwPZ}XJ#yZ9wz~2oMy-PlU z15m3IxPDkU+i}vNv6GWkGFWDi67py*z1Co$E+!#2qN>F-EcTTzyqOp${(QhmN zsXvFJKVlsr&l{O{Ph=O4x*sSkYen^bQg#FQiK=zQH!`6&fKJT-I+%QZ)z?ndjMw~r zm`U(TDGx1hKUnS8<8=*=Bl25E_4%9A)c;t;Z`qrfaYhSFfo)H)3vV^Vgd%L9Kn-u9 zKTg`wN5uQD6@vx_i{i27Tped3rkAmaf3^@8u(SB7%cZly9Vg#!vbU1LNqc_%yYDM4 zZNePU0RXBqSqBC1UDuq*xjj=7H9Kx8AKjO3R!y%l8ee}ufRgB|RxTnAEM$WE%_+%C z>UZx=Pa_#i;PRIqrm0fF0W4wvhwKns~__Pc{wq?HQ2emWoP0GE4TiO%AxozV|0jZ zQ4bah|1w}==ozmgFBI~uzvau=BM@ozn_)}~zN9zIZ z(^ff=b9yVc0hQ4)Gv%Zr& z|6+|Tn>5)#q|aLypFu?}stf-3#a<$r)d@Gd_PgiX918{UjynW=(A`?zm_j$KCp2WO zZEv`wW3DWPnL+K-cI+#5l$S23CD(ok5CvH}O1fMJJR;rX&RCtz*piM1%W%@;N#!?7 z?4Eo};@n+Wq$Qb{(4-ajroiknh0=kMHKUh+PMK5|`=4~d&AZgFcsr+Ys%pIl;mW;| zUl2IRv$k|ptY8#3x4wOzrHy96@!$~S4-1e{V`8oVs>tMd%$AhyX%$VzM$f#3GEEy`~fikayA+Qe$A2L)*O%!C5}*T|4WlD6ZnCFWWOJ zE*GFf+u7yZx@c$5?C>ZR3KPxIuU+R}W#V$I2E-%`mLqf5%>rF@Yhd>;{X!T>R|GVO zymCG{w$SIs|3?04?zd=m>W~BTuXC_pPb3aAJLC_z!8ln$&H#Q=W=Hi}Mv?HLE=1#8 zeWypt8u!iWqVEd!==riAbOSG?s@(b@8BSw^l!w*h0&L$F3km;mO7d)p)HGs<{jY;~ z<%X#SJHtBUa@w$3kT&K5gn|h@FIeLj-D7`6Vv1Iv$ zEq#gqzHj4>ahzd-)R83~bzS8m!u&>s$bL7J!OxoXSS9OI!#?28!zDW^+lRwVbY|2=-=@~Q{N7EXUC>@CTBksLTLecEr%9}9p_A2kT>w>P~w&V z5qqll0K>o^f?J19oo6<|HDA^T4mkDs*AtF7Uj z9x3P5DqN)-whG_-23i78hD=(z{-LFRA;GNk+hG~qg8;Qf%6tttJtLTcaP68ko$u_a2aiWnOfg&#+_w!^&%DJuho_R(3y z9IjJ5w;m8P@xLHXTR_^2ooy+`V8nY>%GvnRj8mn8hsJ`B=ZaI=%+$F5$_&mVSeCM8 z(gokowZQ@JNZfZ#QsGK;PSnzUYv#thmfYTqOvmx%JEdoe1J$MT?Ic;RD@{Hpq`*0D zwiAS0_*>M!{8d}1(_+5jOx3yi{1x3XPjQ!`$k;59x0GBCF(30~g*xu}?FHBO=M!&4 zMP6modP&izXPJzk@iIH-1oOs67%#;00nJ^Mj4a@2nkJ&P^%PmH$I9t zaU-6!c~_|vayN*(mX)kC3NP~Pue7;KdOH2`Ji4l~9o{z=SYca*;s~Sz%s~+>@+I@~>HzcS^d{DU62R+lUwVGD=De$D)PIFRc zZ5jYI{5sVa{y0Ftja{o@fOgN8AODw9^m$I3rJq;P_*gY=Mf>WNOo_(entgY8B6TqL zsTst)%=T0^m_|=5gXYM`Rgv^VvJT&(te&p?*`;+L17-iwuZn;XR(Ix>{i1aMv3A1p zmHY>^A4lD#lbl;3_>}@@&9&I5-wxT=StmWQmwZ*shI4Fld3FS+San@{CWvxU>gGskvDKL@SK^W0$=_< zwIw8ZR}l*!&2U!LoJemn*&(S!RCj8VYw`1O6p0{ey9G8mNY+nAlO~BK-B(AEy9L|P zB5v}fcDHLC-O$XSeWtoKYs5W-V2f+sE={4UgI_T8cjMQE5S4T%DEG~mGha8im#3aM zwKB3x3$JBnEW4A{=C>$qhhzaHLjGVDxDv67M?5W7-5Z$xb?cczx7;-;lhxCo#C^*A zDb=!IL@gvMzId8$MaJVUt)8+qwMH{sj%M^b+}<3sjl*>EWDZJMbukXlnW(b3U)VLN zaTkT9%;&H&e0{Ij8-`N%mZYs?JxVc}(ruOr)Jsbc8U8A%xAV!g}NJqT2^G7C=|`GL!M z?N7ejK>S;bCie@3V7_VOV&J8VB>g>Z)R)uc>5D5d(g)6bD?dGNMXDh?4KHPAhjwd| zTDCt!IEzf*BI8EA`{*;~pT}mqM?b`bG14B%jy_|PBLnsENV5K?Cpq&TpRrA@CL+od zlouXN%zW=jde$>8;H*w0?!YB;o z#+<-D^jF;dW4bIz$!sf3+fgYCe#?GjM$P_{pRnz1Mt#@4BfCWF-DobQK3JsXGTWqC z`4!vt#<4cvw4B30&dIUziO5b@{nClAq)dq*7^TIlYg5U`y(FLYiae`3#f_=_oUDVb z%vke*l@<$W?1Ss0ri+En>^&47r^?&2XWwbqr_Vx&9gBN^X=0kyr$V)2fv+VJUDMB7TU@owP325`ehtKwjMj!f zfmjrRtYtWB@vehZCwv!5xQKjlqu*AKE+~F}WuZT9{0~E+A@JBe;?&7##rm(m2=Ice zNp*Y~wB98<+99r|_86#A79Yk%w4S#!2U2tW5uW@4yJT5hCQB&lQ_sOirxYHIkJy#H zCL{2ygQEv7Y`(ho}qZX|2#r_e$!``SRU+8twFRoO>A~hGF>u0^{ixB28yBZ zjCKLf0$jBW%PpMhlM}0jt;)@Ic3_Za!286)GjfxNffBqY_3eo*KCxL+32&X`y2sV0 zLPv?}2u=QVb-r~%+qUu9X2!6*7%I>OxB#Hk(YHH7yo>tY?c?F#K1czppGKd!PsZ7~ z#NM@)@JFtGX52};!m5KM;R^Hvak%Q98f8;|W+XP8CH!9-SZTo2awg^i_`{TeAiD{% zaoPC+?g?yQF~m&A{CcD=0vk+5tfP}~&= zH3%!WGBnUhNbWV~KGrA}c0DHWvpd{$;wlpbLYD5eGZ;|0Lurt;n)g9I5y>VrTYM_R zR7TFuL=BX3B8DH>!TaZc+fFaix!9A=j=!&=2fINTM&K=6_NlOG@b5&NSks>!*mp@) zpI+l%%MmN8qE--;&xULaK>6jV^vrQAez+zrb3>dy6Wj0Db<<%Dw{f(1;pw1KzUOIX z4E`9I#qY;7-V0hU?9^q~?7u;&HX6PRr+e0po?P22LDvzd)w~WEbO(O>{hWeb*n1fV zzoqED!3reZ8lYv!`zFg)mP~>ccE-Y<&_I9oXKRP1g@Nejr@a~@8Q~@Fy0>X*sqk}H zBUH`__fS42=4U{x>cF#?$S)V05hq#WY!G7hqvXM7}!d?qWggmain8B46Sb%s~C z>}Ih{c?^r|J6GQUZp|&^RT6t1`=$~Q@!5tSp$YuVXzEacNMA;O`wU?kqTZK!84T`! z%Vu+Y$_>@XN9`GNY8d-Z0MhFk_a>o+0`Qk1F;%@r%2tiM&=(-x$WR0z?* zeR{-XbR8xwb0bfe4K_A}l1tM&t#0P4wux546%ESuhn*V$m6dO+rT2LW&!46%!E4SZ zJ(Wum&bVZj&rEMKBXkBv(2j8J%$*zeyoh%{xRE3wFMF!LmxgWnNcae_w<7wGQ5%2e zS=C+HR=|f>DZhWP4UOGo+#LkSYd~F4=H;`qbswJoB!hy2rS~t^es)7uF`rtiWFF!n z@bZ9f>T}M((50Mn(5rsiotdAy!=8@?SLJCdZf~zYK_R#2_4UoNEA4UuTRWbn8|6Gu zpQ&@vV_#Q&h{v<@I-mB!1Bg^vrZ8HI`~1Di{zE3wDLjoL0dfEzKTVGw$LMeq_hgMk zGsD&ONdc&co}ByP@o!c1I9Fv)|MbsVGxo^*^y>q5+E7FSmcQSij}Z%j;xg`x2v_xq zMv`o*)OWfsSPe=Fk;%IQH%y*#9}*o1H6*BRIX?%m$5A0&zpPgl81mus3K#zZd{J4O-!IfL*}!`m$n2}LTbrr$hGKNW$6Xcjj;bBA>ucLfG3O;4=BsNMjdEwR6Ra66^`&!rm? zG2^G|%{Y-q5hweY?T=bCDF|9fCJYa7wI)kOEaz=g{rgn(Wx3%cq5 zSV2Z;cVL-2D{B-Kz;u+?fwMGB`2r-S86h zL4PE^b(;UYH|aAdxZ@Au_FsuxO3)^fw)FyIyp-^|l0VBkHczVGzKYPx?3psNa5#7D zRjoFAPqE%m^g}e3uNuty%F=9JT^MjIXj?)yv(j0Evj!4ba**8zly^&yfLQ}Cc1J=| z`@k0mD9KX$fpdKy#SAECaFqI}47=d8vD|r`cTbE^Dw#05{Q?{8iCEzA>A#{|GC%kp+)6pom`Sw}HmZMFMh zwyWI;N3u|fsDY@UqjxSqO(60Xu?Bo3z)ZA>@q7YT%*_r&k{hb%xA5WuoOCR%P7iD*QRX;CH@Idtu zsaHG-Hxov^bU$f|IN=|%pWI77M&x4L2aM_@XH?fMn`ld@SqVnzqlN^?A5OBKQj(Ca zPu(9>ZWL`EN^qt6$6f#X)~)X{2JcIKy`?wCna{2?Sou5+ZlLi-%fslr@f<6H=$i51 z6;X8D_~aEYfL8kaG#TwWQ8Cy~i^uV`V@}Bv<(GE%G47;mn+luw3XY*~4!Z;Ub_#~i zb9AKD5I5df?H;0w1`|$y^IXA!dT9-4?JvfoV5c6eVN~aRh6!tS8!YnWch|D3z~;Ce z4pJEn?KK)mPWG#^0&hF3E-A(=#e2pMo9cc?dhH`_;IEkaZ>?d_Q-y0+vlw91Pcl$@ z;H(~y$u4VYWkfu6MpE5xeImyMTpB099V~=V29LL}@w|^R-^m-7w zgCTN(%oYj5agTMr4m{|SY9Ib{;kIoJdFp$MgQIso_^7Q^y3;VmRA4W0E5PPP zvxR+H1`n^*;qQxFJSx*;rGMe}F<%+knmv35GPxMal%L*Z-al~N_Csf(lwt$?#fGZ7 zzM|MF1<@&kTV~eA7CWtU|2Xh}Rqns)^0+6A4F*lE#DoF-C<&zu&j15Uf^k$5Kv4G) zQl5b^=AJKhnF#32eA6VH>^T5FReH%+7L>laFjAfL{ zppgn~xAQ)|Du)PXI*AIUqVEX<2;bAXt1`9rz&;esy1||F`T>{p?FXTzvHCsR6j-7h zk~Lq@cX>#JTy#yiMd6<+ZU ziLAUjB@1j^eVYRMPxpc0B{H+4*4Bf(mGG_hTBnU9PaPyR;`G-$%T3K zn3*8<3fH(PpA7|cyinZ%;Y&n9(zQJOZxByFR15*(Z7++n=77s~8Sh8F65_o=?E zD}!v6J*!b6tUu}u;~nctO}B<)CXu%RwVQXwG4Uj~JojBZO$@D-8tsm4QY&%Acs@Fc zL9n2`hz$T48^X8LTrR|A6$2;4H5QxO6xP$e$1JAdFAVC(?;ncQTVbgFo2)#9otjOtDR+}@tY)`AM6Slj9Rh4cGB>KTI(rYu2U!*xfj{>I`Du5I zg?1~V%@>1BzB*G?irDgIN2<=uA69CrzeSuYp6v%hqHFAizt0I>Xb$mJ?mTNZ2m<$T zkmzx6TGG!a=H1{ogzIqpdMwS>@`MYa$ z^8>RF(C#e6)|PrC_i1U-wVOt55rN6d&b4d5#j{leJ?7v2oEZ4ZsNVv{JsU?1YM)gZ z%(j@;)o?_=FnX5ajp+1B_?|J})E}FwAC%;qQYcGqLJ z(oY6~R`>V2<)tUM*;7>gh#L>`RcW~L;CbM=RZbl+jW)y}6&GIY7_vZqA6P{U@EQHy zqEJ!S*uu96Ag3z+uvGcXHo)fUkP9R&%Pzs6(W&sdeSWzFo{FEaBK2PP7Taiv7t(gp z&-p1egn_=G0UDa_>)V`pn4S99nu1q773ZU1ef9StXaHgQI_A9hO2+(Hn3tbcw?^}GAfz47W`H7>@g zEXK>;r+Qg_vSO}qHa@7T>Go%eq)i(>3@7(J)dYoz;&-{z)vTEUw`Xk_^sMDkISKzk6Y@PaTQ zKt|R68O#b39=M@hS-)06^G0-|r%0AO7KU9P^ANgBG#(kfsWx2sY#S~CSD*6ULb88* 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⁡QGHm5T|`J>T! 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

wUCS%>~iLHmalx|S*epHuGY=Z~n)j&Tix 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

TC801Ex{fp| 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 z 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�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≺PJ4$YPfU8kX~5~U9mu#?`(i=xxd^~w7XW^9 zbo$wwq+3F@cxBMCV3muVUV%~KdDv4(?8sdrwV*g#P~l(G z1#i!)ZDFRiWB_v55{c$5v70)M03^{TN- zZRTODkcIPHW^-xnqo(l;`klAdV`{IZBfy@BbX(l7ynn`#{O*a=J*B)qvqkDRsp~$2 zc{S7hf6mgL*7@ii&HV58m!P{xH-8Cgy1m`V6L7Ri<|KC?zsYN!q;}GyCxK&`aO?+N zt%2D-#=&;^H$?Zf9L3I9i_yfF{YsQeE5S28*As7}p?3L5SNpjM%(+{39y4FDjY3l)BU;lA8oXGe~@0~NV8%bE+DaZQxzG8V{`5{=q@w7 z?F|xKzol@JNy=R`r@iwe%5ceKQEkv32V>4Cp9=lq;mRSDvq7)B|2lT>zcQI6tsY!htosR12S20maEJr+o#%={owVRu$_4reMxp0uN#f4-x}NVLW%|U;d0zI ze}ZKH`axmYW0K^uIQSRZ(3bINw6!j5*>V8T@3hVtucL~tHvjBjEjL?z3rC|C<2a1G1GFM-+u4$;NQg$-Mp`ty50qVSG(-^{v$d2rN@WA@7aKbr81Yt zrYNDe|%zoatdbpZ2&f1 z1dLOn>cHCQ-rMf?@t(TVn6Egr#Gvt{0z#YXMlW&i$bVnXcyc8gJOzXe?I6EX)x(Ml zW|!PoMWDM>#FukEZf}3GaB-}}YRxsh*JQhMSw`=wU&&i{yevfQiISeFNUhpXO?IAX&dch>l;PEw&-On zguf0$AFd;EZuD$v{3Z|1Yh6Q&)?8xITv^=75pq$ih45Mbn8B9Y>$eo<(tTo0`YDKs z1!7F)_UQH{+wIqGp-W~KtOHM)!2H>~*|iQ&9P3WkC0ub-;)pN0CA9KHf5P|HpK+-# zI-Mjkd6M6DH&Bs_=8Q67ZYpS)EY@@WF2`_;-LWc&9m9qglK=EL2&^y$q4QxpK%eIO z`(=0(CvJj~Z5l81^F#newfJ7N>#em_Fo4|*pWkF?;4n+}Kv_M_X>u;+6)uluHxsXe z_TS(l^~UqUU(J-VkSl;^f5>J0y~l&c8m9jDLBQ|p1+I4i;6<->topA$KK_O0_gVn= zd}^US{kHm|>i8ZdzwHMh+vqkfFd`GIXZwB>yIl=7W7Ig7v|Xnl+JX+bIDr1PgL{`W z&#FyM`+;Al_!J;T)t*ZFjQHo|T$?BPT)=ut>0B=8dtRz|FQ-56e>oLHTcf>G=lgxT4DKy!m%~YKUB2l<%6! z6EjX%;KaZ=0rz&_LC3v2yZPF)k&GmdJ==tIt~paet6e~voz_^x=?L;Zvho}&@ZB7- z%<-AIomuDm{6{?jM2fQ%R!69>qn%yynmj z7^X^@-PtXyb}#N;y!LsCdn=JF6A4Ee#)B1TeeV2pE+IDQHmVojjU{?s-@T(v!U(I` zLGuiq?+&}lUDI_xWNrm7GfCeeXZ*!3s1-02Z}dXYCNGbNf0$tT$y3YbUpjqns52yC z%sp&zAcim=rg8g{OoBSfS^VmO=trS|$GyvKG05F?$btcPfCpcD%wyuU)|Nx-qh7Ti zj&z5!H9Yq1_)#X?S)Qlx2NAIdl%}&iQj#&S6$L?VK83w7~*y5$n7U^f+tpuuIl*FPhUV+ z=3O~N*oDS7I^gd-0U~{pF6vmEcUfjp(5=u;QVfsrF8sufj)R1VjbA*nJPf|Sc$L{b z?dvZ*=J{)nzyEneYIPBkK{{%HYaq&|E#djG!);!ntGQ3sk4=?li-+k<_QlF~>|E_Pd=5A4hVU@$6hi z0AzcQ3{e%|hWCrzwc6S;0V|hp(&zMVHqds)dOo#tmv*s_u>vJ_yDVslt5I4Q+Ct@^ zp|q8%f8xTz!{8moc}Z@EB+l$tTF#`v7rqL{>faaWNs$*CO2N5l)9F0PqqaMvIpy5i zpLR7)79viXWyRuS+F$d}Z2^8pG0sAxHZQVd#&JXAAyG7(3Em+Kw+`P8wFL3>>z-V= zyY8FaZ|b%CcC?9KW9P`}QBtiWb!1}2MGI(ifBV$^NxpiK2s`YbpLsMy@{fg%6_7FK zYQkM4=eG$0Ud){)g9Q1_x;G7>Mq&=fSkEW>r_DX*!*6O}E~;XojO_?kj4(*o^9kg< z9RoI5(Pt_ajBHavdJq-zpt#)^ZO73;9yY{BjX{3$1zl=mKQ$oQui;>WwTk+X<%q^k zf0jgY$to}~js%Wa9Kaby<1hH78A@l|A?5LQ*=TNxtj^eh<;V*M=!YZhLyf25n)Gv# zJ;NWsZ&*?Y$%TF`zOx7+4eE7H;Gab@&_J^U_EqqMF(bNbyZPdDn(uBVK4p&ROWKit z$N(mX!LEKU0G2Sg!}t1&*DS-IRUurme-J+FB#haukJ(RML4L$XsmLRJ0Ye-Hy{d%y zY+)RyOfX@{NOBrBZ(i`*x#S_S555{8K7dcd8rwMtGyhSM3y{>=ZkYH4|9tGlGrbm@ z@`L@tUmpMa<;Tar^YG9Ae6>6H!~6O{uXh39TmBmYS(qQ5RK1KDfeYIKzjNs z1#9mTx!@QBGMkp?VBNJxbFM#F|Ttrc(?oLM?H*gIyl*%_L(Vl?h-Wn3}yVnv}?xOe~q{I?OpFQ|+cz z#{IREqa@AkZkVjlMpLHk-6YUK(=bifMYxG4<_z>rE|EQR0 zQ#obg5>WDu9dvZmyT-7Es@MUdjz`SFLWlV^bxX1hbB85~W?#?6{31;Fgt44CFS!nr zquZtl#1=YecP+xMQRZV_$r?og=m;{=hxsbBUmW}nz>h&Z)m zf)TJANnI$$YW+1E-LiApj*Yz*mx;wa78(wREd0LNXS2Zq?fjcO(5B3>U?t>jwxL)g z#M~ZSEL-6s^swtc$`)@OOI5ss4jqFNw?Nm-`JZheOZk7I`x)j?;R0M=?NnGOT4?8ybAa7Woxp1c-(b(dP`|M15RCr0enKe1LkkUw*CNFXM z^l2Z5g*bo217NGii|fhf8s^{D`+CXiT>yBwE0U<+x$YU5;43qs#Ml6;2v7n%wA_~5 z`v?1szrM&5(E5&!Qdk>@vD4D59vs?qGk|I^K<1(8Z7F&UGlBgI7@AXougk`9H3L{8 zI1&UVfR?QKj=P3u^x-h^tIAA3x?CiXD}ksO*LQy*Q6Ud`w4^9WYP&hcUs>`Xu0S`6 zH$(CrSax{Oiu5S#!58B@oj$7vqV+dd?rg`z$C>h-q8hx9Ae{@}mf$i=fh;nK^uxBw zg~v|Aa5;EF&=QvQ`D$YUmkB{}yrZqzPT5@F_aAF&(u6;H&Sdl`SsM#aush^(TF(#f zCgXp)y6ir{F=I|)UHJE+V=f$-mMC3Anf{J6x)@Xhnk|9WZq$%WpXRXIeXL{+M`_bd zDtF6$XXfs5zqaHTwo+AC*z5OP%CM&dmJNGYs2H%uZc zj$xI9^vMsMCVef_7f%bAE^=YrS3iojN&A0e}8BGi9e zUPhw6M-DGa`@Fc~^vH9wWsW1j# zx|56ther`pSOwW>_~0G)U?Xwjz{ZbPLF!z*hAf@%h1tZG8Y)&1E+7xnGsa}llFg|uui(I>`VI)w(u}ckIz;dWzpJwD)ei-au{KO zTyzktA3c93G4p-B()BI?yx_G0$4?*b@>2)Lm98v@WC-Dtt7oEwj)e(Vu7m;AiB2sEcSmXS#f|? z;8G(?%1HAeU~|VDNdp34E^vyEhUATc1cF@GE%n!TiH420o=XcHw@XhV#6sqz>qZBQ zCR2%$@u!$zL60`(<2o&Q>cS$gbWz|TIP>&H?IMA3qi?%^pxG9Q(~i9dK-Fb+8>jpW%rm?u2%ZA1WjhQ*9 zazyF7Z5Wz#dSRjnYggj+VRF+1+?k#u=)D$UWrN_pYt7|pbh-bR@!@~P64IeXbrv;^ z7ayo36R>g7v0gQZMNqhv65%Bi%UIjkn6BX|<~?`bM)A5orW=+sMO+J2Hdd<5|1_&c(+Q8ss4NK~Z5lavlUo|6J zOcPrXQx+C^XbNK}@{E4hmq>%Hd=O`USJoz*JdI zRRbVCCkFa1q-cNf5z47wfiri1^gKxL4A#d(@Q)n@Z|hY^r{M|!)9zjKCAEgO3Pd3{ zkJ>}Y#uJ2biers$!8-y~K@O#7J;;rv(FkmlB=DaoEGnm*JM=NmQeKuA<^rMx1BtJF z8I8ZHzT57J5PQQ0APO?LW=1eH6-aNR^p3M72u8W`CQpArG{1T&zz$;=MI7Y{Na`ka z2EAm#DkNP!3S&n>rjMXm#UFxd*@g;IuD_u~Leae>u#v;K<3NUp*&g5t5xp>D&*o|1 z$t0BegpZokkvN;;UBPRpB^=1scE`N@v$-f3UP+L!sbcp=_;T?;|2H{4Dftl1XyU@i z%~&L;+EstzL$^gF)DC^U4{d9%JZlyGo?lG9a6&>{204#SutX zbGuyp6b9an=FanwkD3avKa0osor^Uw3rnuU*>p`^N#>NBVJT7`sXLTqv9W|K%Rl8( zz$JgkY}w%uHE~QI-wnr^qk@pI>*9QFSEP^|5$HF|Pkn4f77jTBP8{BVzj|f`J#aCh zSHn(hCUJM)><)dW+bVcoer`o>rwe!&|8f=V--{UmaVUCmBKawEd32C3F`t}+eH^OH zn9N_M#zsS7!k>El_j4`t-&EXqU$1h#3jlvFcG*#)-+p}fC9S|bQ5c6lZI8KCC_Ova zj!Z3Z^+iYST3=4j!ootQTq0z`pdiFBvL1;C{Szz6jfOLNm}qGN+lwy-mVrG*tLlS4 z3p%V&dY~T%fI{FU5ed3lM5Io{R~7@-L)*bb@bI~_*rTJZ9{w=>^lrxQ8fPFG)uMkk z7UEUfrSQT8l9<>{@lJ^NN=~)~9B70bIjL-kzng%-Sc8jF$x>h$e5cgot z1tGe$Lf^>;Q25|KS%k!9h#%wwu0wwf=RV*`t7M^mNZ2OxhA85-U7TwO+le7hgSrX- zHo4L#ZGok|xr+I5C2ZokQzFhUz{i$BPhKG!hQ z5>&@m$dSKI(ZvfsDrFqIV4#CG=$Hjoz`rd+5H_HaVX=*4N@W+Fl8wwpm@hMlDvR#!YAkz z@?9Sw8^aBpHuBR1bWL(v#er!dWwdFhT)U#yX8N3*cl{! zQb)`BfOCdtkqWBm8UuQDd6x8JMFG-_g*aoG+uEdm%dUW1CIXHzq<78?UggEN0b%K00n+4)J$MH$Z)@ajVwQJMO=0C%j8_Oa7}-OBjPYydwVI; zaVGGZPE%z{QXHs-R5Qtt+^xJfb7cV^nKrjh9LP?b*2m*tdi?jdANT)bm&E(};jecA z;N`C6Y-9e`Kn4|0`i`dqyC)-lAOV3l56UZ`_1%swAZHMtZEW9pCdm3q8GM!pyo!V*0-gm* z06MXaj%r7MHIEk%gG@j@@r}pBa?FaGpCqln2&$JFJybywCZ@N-EiXb-p54?PvDo+I~W6`C+DMNv!9>w4+ebJGQPoo zX1J9X7&V5xmGW77A-4FULY=Np_{id)1VtPP-L&z6sS=tnr^@6meXy8_#GY;qV_Ev4 ze}TUB*L(zveC;So#(a;NwAuKL9WDN+&23GH0UBw#TApMvpr|Leh)Xm=X|)p$2rnrJ#wip~ z!VaS-vKHSlMv_H>PO>rE@In{k@guK8L z#-GTwY;k`ZzH9wZkg*C6celM=vw8Zdk4c(lO$80n8f~O2#iALu;aEtyLqr8WhjIW+ zL>pZaUPUjcm}&v`YKE}wEW8$DK<1)`XMKl#>7(;QQJ~w9Y+a@oiEe{NzqcVxvK{7- z*XG%8nG3$J7rNdBfET+2gX1sm)p$<;?Bcee1+RZt!0Ee!RmrK5xHSC0PJ|NS)s0Ef zu!P40p$AhEX^Dv+sk+9vg4T%UnLHp1LqLPPJR*4eYyP|dGJD$fUI~vD(8e2>k0gmvW4AHr zY=8^2p4ZXglj;uMCLvPAkb%ElZjqHt%(i&RXWOy3C( zYl^EMbCkv7T(&isq?%ZnTq2p$d5FLan!9xD=B0(wEG-VFk`q0u7=DO9(XAqs7eS-m z$a_d? zLk?xpe5DM_Nq`r>%oj>KV=m|C(~q3&(zA9e8^I8d(K=ONad~5RwJxK&{#iZ4$may# z*h98wi&NNi4cSv?@bmAt3s2F`7f4#uj~FkElyE%>uPCBb^QBtj&nHGLgc@2TIe%u+ zip^*V8d-g; zuz!7Cd4|Vn*oc#QkvR>Yim^->;01zN$Tj$wHriwn#S-Dfv@z*_(QdY24@F$YOKQR7 zxM+t>plwy|mbc_JUL7&)yoT1cf{Y{?}yBw>*S@ z=U+}~yAw8kPqdY|P7c2!!lDDg+IfTUO3W}JRN%XsjLHRn?y$gw76=d+$_oo-YXisX zmVJc|R)Fu~D^F4^Dz5Kg;U*vI=#IA)wf)!G<5;JtX87+cv2A6?2cV zTyI*=u3#HQ2iF_rgXr$Nqi$;<<^siIB_DV$YNc0_ZN7|u$6UpXxlC)xfi~a;yJ<9; zK4@NxALwy^B??&FU2<`|F4LRs`k-(|T^M%ZI}1*wVu$O7{8x#Z0_aR2>Tw zZi^Efg1fuBTX1)G78=|ZPUG(G9*E!&+@0VM+}+*%WdG;fG44yh^;?bVs_OYosnd~! z9B%!SXS#Pp!CM8QygE`|1BG1kh4@RMy<_F>nkQ?ubfUz^+QH&V!F5)_P-V&hCOr@& z2nk9>o<2q`%UOcgb)>Ny;!V1GB|b&BkIY(neP>Cz>fU&54)MN7$ZVbI8Q*$(#$a=MX=8x68k?@SJbAhV4QZdyXXjjD`H5u8Cm zgH@z=vSaPsweDwVlM2X zEfVO{pp>_p4*tQ7-JY4mqVS;TA%3i%J0#q80R6;YxwOmhMOh~u5eW_A*;72-lmVsf zPc+{Qe>T%k*M@Yq?-L73v)%P_4FgkdOOZ1sJb+?Q<~ieSVR;5hQ}LNx_m;^dJ@9<^ zW=&G?F5~px8L;?YrT#vFIw%kpx<4Q}&9v!(B;2fE^`KTnQg&o4l}~;ONM#LAT)G<` zwClh9KF{gw+oTRP;OUU%jD;x)VU7aL3PTT7*?GxV$X11y>=0CX{4bk#Eo)loXGk;z zET1IUgm9?~MMrDo;p0Vc*H$7D!((so6UT{Rx{Sh@o`{`k0gwX0*?Y3~M^Uq%NF2n8 zEp1L`B)IFOV2{((D<(NbCM|DhG!z&NMH@ftH_VtDL*B89o<=UIelo1n7hspDhI8A3 zG^4O9#v&OKXxbnvcEkT&J5$n$Zo5^0R;f|vx zK?HOJD&nQLLc*E`uJ3@#FYN-`0jSv@I7XeEO_90VUBfa>iAPml#0eP#cnON5p`3d$ zxLa8k)Ek@1YCAc(1Qq;;&b6fHLKfA7^`|!6uaAXHRmA&fEM+X~^G|PR20}qVV0Wfr ztf6@q__d(X=|dONa}KsF)vM*08d;ulQBTkZ)LFeGsb|fCl_0gnjN6sQgFPeEo(#Lh&a+^czQCXUt_e>tiXO9EVw4=VgwgGS$p1b)Iy^c5q#8 zk)>NKCWGt|RxsQ_@Hz}`%to-Nfr*KjIjU0#g@A_zRAYiLT2kdnxGOp4EeG<^^y$j= zpl)bJJDGA?0|n_7AyxO#eEZc41G4lB)cR1Ck~SPvstS%WPJC7eM$9IFl^Q1bg8*gS(L9@O48H^o(}4Cpw;&9b#lT4DY|3yD1cI1F4)? zvWA*xViNFPb5I~E^56d=@P7|a;gseLKfdegPX#gx0xFx~odcUBbAQuo9K|ecu+vPL zi1_|e?dq3QBpPtZ08nnQw#*{8AV)1pf=1XMa9=D(kf;WB4SBO9F`Bz2lHgJHi%K$c zk$sJoNe9yrS${)Cu=Gt1HbBAC;k#&j)4Ds`sF?h9)R-bk#S#$HfR>EM|&(k z%5o5us-y@87e`#FH2?&VclyY?F#`C`B{Fpi{@eY?fMAdPb6u@12$9fzhRT5-_pywW zrkR5}E09TYDfV?GcW7CT=BmV-2rKF|5v^Ewk2&`EuIACwoe9x@4n|?X?c7l09E4#n z=%g56XslTd9QlrPXXy3nH`Kmkjaqy_Lic6+`d?B+ZKgYm_;&@%c9$rhK-T|)1Fh-LDN?5@ zvfxF+NaZ%fKso0PU(hGALYF}|m(Q2LVE7x)5#;OwY>VI}7GvT~AnjyALcbNe`-F0c z)gxrZs4T*o#5fbOoQjysW3B)GBp@4dJ5EhFCET$Eqg>IbaT6wFe%o&_7;cG-v2)0X zA_|M$@+f_k3nE1Yx3;mX3R|SfT7^iwdx<`-?0Dj|{pC4Ko?rg^0DcFv%3@N~h(V8seHa;S0T8iZw0SL6qOf z3IDAE8tRQ&z8#r(Bfrji4LtaF^#6CeTJ`{*9-S%@JRq|JUtArbE3S=l7)Z(qw?!xf}+jR|OK6UzD)pT{7{)Tf>P zTGmIp^y4l4hNZ#DU|qY%f?GbDY(OmzJ0iJz&G4SQ5xq5OsYbxEr=txT{tSY} zDp81Xdp7K0QS*xw6OC1kb+A~*b%23P$Pj0S#0Ctd<1uNM_fjT$^9>>Uc^A2IX;QL< z+mamQ*%Ac`S!MY2afYfoaV1RCl!y!gJFcQWFqS77@ zrTkDAdRQf7SF?^bo~exQ`biq~C`1V0Mal~QTnaFvKheI@oOv{Mk)XDbY@UaJnSqwT z^P!J`zDe}<>V@Y2(4cndw=qwz)E|&z%rAb%IHqe)c-_pV4T$^P`LGNI5LSkwRJ4>U z$%-^4QV_W@=Zs#4A=e$+Fi%^iU-S%P$`@Ujr&XamRtc#(Q`y+J@TPe^WjUQCYw>zk zhMn2&gwTRSc$Zmxs_up(Yq2uZfItk1tlviI-%Ma$7_KyFZp?NfF_*fr zu^JSRxAv!H6kfgTm@N=}q?OHGxdmikP84i1PKDIeYtHXzQ0AdxS44NkiR}zw=ofi0 zqh-akB>w<%MGekn2&mGJBTv)|O!{2GLu4Im+9@Wd1j_3PKvW+tigA)BV4yx|i4b)i zPW$lhei(kert5U_{!NlUr5;5hzwh@N)(2Yz4vZ|@7+C9jA}chY%g0WL(5YmyESF7$ zrqVk|MjkuMQ5<90SCSy%8Ap)?Z1Td0RP8>SLfyK}V(wdSk2Tts^b`DPx8XDrb^Dnz z6h$@!X0#r&)zz6g+hxQBG8Q}2qH)r05_gAeHqaMBRn%@ga8P=&kUo=zhSeAuJVG2) zWYYWUQ%N~-`cEV%5VmUmlYi6<_C z*6BPXS=HhWxtHsBBvCGSD=+y6S$i{)y7iBr%Gm{?jP9+8Mvng-_?JUM-#IN45jr4g zpfV|NerxN~mh1k6VL`+bGeJ`@uk6NZg2k4OE`BD&gu0FBY_)`94$jCsX*!{DF9@h0 znuJLsjWl5?Q8G4z7mU3Gb#gnrzg^tA@3xB4%@z>f-F5~{{WpGgoXidZ=YpcOJL(XB zG00>t2Wub0NTALcHl!{<#?X`sTwIxHc1|&#bjX@|n|FKywWA%+E;7nJ8Tho`Hfj(c zw(mq4h3t?xK$~ov7lstGx*Pda@OF4|YdHi}Ss846BKKWUG^?$5Johjq&fb`o5Zy{Q zVk)vhoXcFju=sX|ER|L*%c9AK@LKUgYNWZfLOIIw7rJrSy58b1Uyh{Ecc!X-z*v?j z2wLVpgD@~@b(#-(a=Q7H8U5zYLM@gN;{QmRN>dblL5jl7Fn6&hIz?E{&k*B)#0Rv! z`Y{IP){zn{Ip~M~uBw$|q#E{2kXhPZ^|^oIA2(8-8f9w{^CJBUpKNL{IY~-WKgT*Y z(N8e28n03%+C-coYLgqIFsou3IQ`h*MuITlKP4!^6Q4udmD=SW@T%J`BogpKqrV+G z?)N9b-Jesx2UNcz^6h>^)%kn3EE7;#8RIYk^N}0&J^1TQ?vkxxZ*+?3c)lOs zK6M%95%dn|=Rm>G#nPagk!FIFR)D?m?pN2F6zlr9qkbPDw}l>Flg#R%Uqir4cJcg; zIOi&!5Ry6x8gU=Dmy=P%WFhEO!YN~0;ilfPTqJY=aVd8x(j(63&6W7{WeT74=D7A} zHcPJ35vzldfIK493E>;DN@3CTo`^^z~Zcw{ww--=1=T+X6$if{G5>FZ;DbS2{Pf;Ez_ee(Ri18G3)u!D zM(Q+8TY7VhL**Fwu^}C+)@((bZ6q*v#v9Xn z`|#dU4E&>ZUPAxWt|eQ|*$kUm0gEVZ0`)BtCfE8ZW+OuhJ<6;T1nEANz}jE!!A;2e_lnwG6!beyj+T`-X0C)_I-ZPhMPJSNMt zhRY;UGGxzs_>Blh3su}HOKU?n$h_H6FrB>#wS`KXlSjn77hw&pFg!Ap1Z@z#}`Q`E5s32!x{qXzbinr)m+skX>+ClcdOv1;l-!+y5=J+3dpG9l|d03B+1VfByFKdIQPX zc;20T9Rg){HhwcFfYXcVrEp9K43~A~Z^Ic(BC*e=kjQK!{$uThgjiY7tR>P3>D&?* zc^@FcM2L;|c~N&3yvN08qb8vqwF2r2q8u?p$Ks>D+k5yBo;RY+06(^C+~%NsRRqiY zqxTc-1RZ+KM&C#vg;SJi{-Qvaope8r7j|6y zkKh`HrTUMPG#+p=F1b1(VIe$izPIN;u90YK5ba~^%}_4S`nz)G)Y$pR(rzJo!U@#9 zm=!VSQm2PF`iT%>Y*=^}VxFl-6LZGSG`^q;DC3b4_;KybdJ9g?J{^+yw$=rv>t^U* z+)SJ;{YcPgemRIDQJuRuyB2<^Y&E-svwPqX8Dd$14oFwn5o#IA!kdJW&Ztian5k}h z%QqA>$r~a%X&_H@%fDz6Iw&)m=mJ(&9oi2!toQbnZ!gm2|CQ@dfvDQQV7$VA>G&9< zgw5MuXx2||Z=D~RgoXDtuW^lVH5?Lds;XG^g^!lB8FVqYt!gRZfVg0l>a1+ENy2Qwu z7|T<3wIRu^xbLGvdiJoBabWRNQS^Y(*oiEv7^z%UNbVn&!l$T5o~+2EE;kwbZJ0zh z;zt`SC8pVJ#K3N`t;)8htax!*D048CSFF*U+SLR|(Ydbeubv6=p;yIPEGDwAc_%eD zrzLII2qr^-z(IB^ZtpWHFuQ9+Ezv@FHRoZbL{E-ppvPCb`&;9EI{)EzJ^`ZqqSVEMG?IeS zds;oLQ(i!wG*&^v9X5X`_ujvZs0u#0Zx(fYX$?-s{VR+%F^+FM5J-bo!dctl)eSH8 zP=}%Hm3;$aDURg9sRC*t&U8HU-SnKQ#E8E-Mk4riCv5bvvla&~S=hAAP$30122c#2 zg2r74NM~grJ4G*^of`JM^xT)gu_|r}r{yh@2^$YjjlM)q2O6t>{%a%c{}7VLubC*;|gd05<}GK zu3Q*&250mWOYpS4AH!iBon|1FVBqFSq$*5|dgo`_+$w*oMVzCjM1C{Q#wbOt>I-laID_ z;nn5UnI{;a-9Hk%ep+Jn5T?#lo^27E_JnweuXu@*?4(pb_&}Agc%h>rSr(FNPvuU* z6+*MradPYBSX;6Y8ksl5 zdj84PP+OLcyU zcHvO`B2O)gHDwoioJ7m#a|>Yn<}BtZ3%7OkYcn)LENHP5LJ-)I5YYdo}{YzfDk zWN)iZkw*xF2s=hS_UI|4DemYes9VTy6-XdYKKC9(FOVsRu153SoHN$}t+182n#oV+ zemV5%wKx$>^SxLrxh8p7aVLWz=ES(A#V8Fi2ikb{R5wltXB$fg1{Zf0kYVlHmE;N91VhRC!S0*(z8{=-j{we>_FF z43eH2nJf?MMKMxQi>29_`^g$e4$m{N8WcKpQ;JaJX_< zLMEwcTSD5|9B&uFRC9=iKVE+_^f?sDuUZpz^7xy*-vU#&j+0 zCIQ#b&tvlkvB8kasqVxxIk~)xjY`OEO0FGDKD`w!Y(4tSl;_|dW(A%fnjQZ)@w3nt z;1@K|*%xn@>nPIk_yy3=&VrPt?pj;R=AVU%ht=Y_yIUwaOjX_mvLYA%&|SH$@pi{O z#K+;F)fiD>5TUrh$qYk9@Mh*HzRazQt5}ufeaVHGjA46DbO5DFTu!GIo|bsDHhQ*s z6%<{rR!uI(Ypa)?g^Guz{=NStsYbOy6qD~wnjWZm#j@4X<_Re7ZdXm)Kll1QxK(t{ zKF8zjE|#yP?q+U0B%P--wh8Bc9%0eAQ#PoUXft)HfABtaQ)J6f%Ri(PJ~30F6F_^f zCU3|spFX(Z6140EE5CMfSbXSc=dKHrgA#Us;5HA6pn8F7UB%zLlkCdv6>C^_QWWt? zGpVXr)46&Z|SHl#`=04rmiGdK>*m`ytk(b4qJnI)HLSZJDOc8aF9}9MWCNuCm zi4T0%^w02h{9hZnc=qtZhdj*;oOmoHm4i%u z{89;9C-3#+Xyf3$efQ-d<^zu5BnZdr&A;WX*%JP>lkDi?;_m(B8+c{H>m@)rv$Jbz zb>A$<+a}53<;GWp?Ye4GLt$|OM_ONfb>*%Qc!9ah8ZpU0usR!p${XBe_FPek8ej7e zx|({?{X7T#F0y`(W-?Cdrb%Oh82XgALxR=56u7b*lz86fSsFIkP!tbVi|66>5u_^5 zU$w~%Q8sAHrz5rukcA^INi>X`F9*h9Dv7&1pvGHS+M6Ru9MI3QCk*h3yz5{xV%~oM z??<4wQHr1_DjUa1aRtmp41=+7TSk%2nZ}ukv~k<;pn-ZvB|>W3o`-{t1bU&bZIQHs zy$}lzYC_cW6OIx&Zbz(lKcDbfB6cz;6wepGqSe2InkaJ~aQhxyFkD&*NU-?DZD5$k zwYcxlL^FMPJWg3^vu7}g;2VI>fFu|PY*O1&EXo`Z#M(f2 z&cA4)Eyg%Vmz8f~2VZpRdQTV(6Y#>CEYHVo#5hg!6`su&uA};=v;9aW>l_+({c(aP>yB{AgiLz z`q9*Ar`L=S`Q%#*4f|O>L7j6~6wg&r1d7>D@!a&Mo(wvTsj`G$1xqz?qe8XkR*g2s zNzi`TvWPRdSvdKBD)Pm<%aj65e_*QxHaDamUivQy+4p|3I-95Wz1!pLVO?cjzPyV8UjzgBE;3$s*nr z)|GUnSMICR|FV!KrGLLugvuKJQ^rFiV}eDd?E^=7*p^#GNfaiGeIDw05(VjKB6!@; zb4TXik9^I4#FBzKiJ0Fvf5TnsdnkHq430{+WefcVcGBae_}(plDm)bGI2^{X z2rp6uY-Ya~NwL{-?j-Q>!Nt(dgpB;bEL4{v8wvG;R~F1xA_OZQPB9=Rr`Z!oB|e@N zt1-=|I?BD@N5*`8F4UV!Ek`DdY|y$t<70HamjVS00^F!R6r zI$!dp@{iyJ{-?2D$1zv)@^q-oM#( zJcYn|8sFlKxa*8)KG=aGOVb6!O>$1a?ecl{e+cNCDxWvXA4KNKpf-YrF!RoKwd-=8 z?5LV1FO)v~S&~nDDwd=9%e#{+V;AoUw7JC@+FOK+iP zQ-!LR&f$$mBKoi+=-YsQF@8uUfbB+c#-(`ZEQ>veVv$fuY+Al!r%-HB0$NMu^2=0U_wbYWXfL@m!DXy+xde7Mv|u*$3D6 z#Zp(b2qn08%fIZCt-4tO$kK;JfBr3@H#}q78n%2&?zjzih{%^1&D=BKtH`wdy_q~d z&t@!?+``W?EdJw{0}WgIn&WNNOO$kwJxxA_%rYN+Nw+)_1M#Q; zJGn#`ys#cAjTtBg-{Hz>NYnpREo)b|-7`Q#*&F#6{M#ybs+t3b^yL*O;M*(ZZHGwh zGf7I0P#$mn!ATZed}zhxbP9PnYqF1&f4`-dos3x5qN%U$w$T2aH-$O8O=-b}FBH$w{N$+wGUDlkd@sfvoY(R!<-${d{ z(l6JM&QDnB!u<4v;Q_>=;9&#L0bVVwlF zE^{s#m6m(Xd?(PoXK7zpvf|Jc`$QMs>F32hDQW*5rNd!!m1(-p;nYjps9v|!OORg+i%A7 zwFyB$chqQZps7gp9!+dh%mR7q57CSv_izV}hY~%*F-H#PRqq+xU^Y3y1cqW4wK-3{ zv4?#E%rMwjTqMQsriX_TI4WpSa6{k4^(_6c5^5m^hG(UR z!O&t%a}D>MU?{k2vV1=a+MBArae64^MirymR|&Yyyec<3J2;x6^D=-)wC$<|P>a&D+Q*_SiiQqZs8Rw_2skLbybf860oMr~A zkpL7(QdwM`ejjYinT=5wqi{x6b0VIitAk~)in>~(lhF?x^eO(g*5cCHVy>J5o}FzW zg0f6$tuJyxm`=4z-P2JtVrr2LvDW<3s8b5CbV;eJ5*CJ~#*#Zzycy>_;yU2Zn8G z@Y-hP;+Rpa&e>MCS2iCGd#~flZ<2i}5ko+yH;y3|G7?lJ`leSX%M>N0!Y8jOX<#?1 zhJFBw4vJQprIsZJ%A6mSi}Lqx^T*HOM}IEP%N4?Vdoi5cE6mbOX7;bdPbQD>~$)#$1)oVmZZ?i$~Gqin2LOd!Gk8EzA|n;p(Bv zul)(q3)FLLacKlqqE#=EdLoK^R)7I`-2TY2#H(zH%_gtBe&oSKjy8)&gRoCCkc3HZ zj~N0HH!gQk^*;P%GL_kO2;Lu@m9~>@dvVTBw36X9&3*Nm>xv^jL+6=d?ZmHFpm8g zPtj{QgOkwqAI%5#kRkB(Sam{eh9WD~;4HQLQeC!S*KhCDV(ae^9wBrkLD# z)?8inyvqic#U}a>Zoe=no1)jufW>7GkYT5EL=+6> zQJoWhc3*B+jOG9sN3>*yB2Mj<@CA!9>2fr=*K5$P0OCMbV=0J1zP_YIdf~^?-BTUt zYD=Eq@i*6aHM5<|h_vNx`eB@@i22)-7MRV+n`Z+nG2HOqOI_+!&0P+c64KV#+|@C@4K9U zFaAnuI|CTd&wM{*^pHyKNS zvdG2)Nr`%Ywiz%+Ey4bFVPvMSitQFXF%_)B(5yL1Kc-v}HbA_0Qx-v)EWQiPBUv#% z$2q)Qs-1wypN}XPJ1ZH^471Kw&OJ)|ZzEziH@s|tQY_c>9m{ui|KBEh>hm~REhMVz zSn3%j0@1`u%;oA2jdGf*<3WvEIuJPo2S^2?KyqXl;Z3CdC>)wI`ECs+m>VH(9~7iL}!; z{S?7XsWR+GJvWD))SRHkYE)b97UMwVT5A6;&zhY`rHobC)g#QUq@N>(12j^3o2aTH|PsNwowQK zYouCJ4ccf@*+{#)!8P6@3hAFyJ{9`O=+G1+og1`mbj(h@28~#kxSJvv2b6!|aLSYq z19CGue5BfD#X_o}`YYi(Nu5r}_K;*ccoKSL8~&SQDjo!=FU3R5>DH(rHJ zBhT>i7$cqa>%bSbkxt6p@uIUAH1OCW2*5*?hFPXkxWUzhz>(uD!<4H}kU`8qMh>y> z5f~>OD5i8wVu{s~z$@E6Oy<6_8@EH{L=g&=*v4#k-=#I_XB14bxW|hb8UTEE(aVsq z;c-QYFrAM%TnUq)ED#7D_^X+>W5$iTc~ZyhJgGM>;*`5k^fOXf)I&aS0Hy+Ie-@7^dn)sRV{EVl6ckrHWj^| z%&%nRH4vQW`H=M~q}P0(sJ~JUPFJx){ItX$wf>A@o51h+x!s1>pzO)Z*e&Ui@&8w_ zf2srC#PcA^^lp8RuSA857l*+oGKvPoItMXOztTdF1o1ybigT-k zY{MFhB(b?JdTt~l=r!BVD{UQZhXnD#zP@r2NRnD?BW%u<(w@u@1z}WH{8(Q~j>WQ< zL`xZ10?(n>JhRMi2gy7$F%pxj!hYBx<{@vXo!Bbr4d65?heu8Ch$r(*+j*U$+p(!9+BN*;mZL~7>0$~t1G*-YmaEzmU~k7a?)3u3G)7JIa;bkx`Bok z@sk0ISPqkR1;3^6$YFI|ZN0b_+sRQzlg&sheUZ_PwO$}Ah=A(!C+yc~g7wm4Ct+%F z$=n1|c{-`{CAubH7VBnJ9C@?8jH@VPu*)Y`#4B#d|gxmCAw!;1WMPkWOdm#aq z1UR;&{BpA8KwejsptI-dm)OZ!s6UO7#lp?G<%VOgAxhg^gS*WFl~(Oi)){VUsAHb7 zP7>JLXltmACxOjy`&Y+5nHXAF%9hTBrnms@plmm*ARH(RobNU&)|tIAqly;J{WX@& zK}+eFiZ^yz>Y6Z@3%|c+SLkfidM$JX*IC%{SGdC6uq#Jd&%iEAo8df7)*)@#CzAvR z?CVR^*k3UqvYtXUXih_Z)nReWK_J4sx47zxMSUSuv)12AYUP>CdDn5rPrjyzS1JLh zy-4k@ItL-U)W()c7IfTwJ)s!ZqkV<_u1#O0 z$tgImHODSfBVNdbZbqm8Q@e5^h`R^j1TvsDzSZ4yM}{dVq+^p*Ny7WZ3^ky->L&1K z@W@?{V_$GKzAQW!*(Y3vxj&8;eYQZHD za!AV+FQkii!xj(Q2HOzv#_e`yu1P#$zoF$Ot~+db;8$D)L>0ZEIS6J@c13=~9efOZ zSN|MqN!l-@#kWZ@@0~pm2K+q$L_;0i{;-JH`r}cdFrvl$)Hp@<_oUWZB!U=R(Cie3txx({zvk7} zda`^2QO2bDh-K?BVdYM{I8}>MnxS5Kx>2E8ORaB+}o; z&^R)1|EYDjAdK&m~_W0VmIAT)2**(vvVI#(U}``s5f ze>M){XU%l%j_1*v z*W~7cwpSw8QNPaWngH&`=mZI>u=7y4Zmbddov5yubN-n^q9n=&44as5VT@<%ei{9# zONZMfg?(Wvqv1rOvOk{?cbNtCy~ADrNZb*I7?JKxeOQA7=w6GUZ;Es*ybZkBV}`NT zHyG>rU;ES$I=@lWoo}5ar57P>XQ4td>e3-JzJDtm7OQ(cEC|8q^}S@8641`%UQTnS zXBP|Oz@e|u&L-1Q?~7`Wtz^4zjnx#+SoBVy_(!@tN=B~4JWdsYXWHyy+ z+|Mrf5-3cb6}G`lAzk@!V#lms#JUK&{&is<_bzJy#lm>>5L|f?%Fa=7j1tY)_^RO- zM3)D2Ig#}yTQDtuxBh4EDOa?~`PJ;Eh0F!#ugLe(!j|FP!n`PqRfLS?V07gdv4JZY z-$bF>W?zVnlt{w*Y9o3Y2n+6uR#4d&jM2e12sE;)2Tk+;hzo|-preDs!XcPNlk>mkjCWy^8;HNh__x*G|0HhI=vW-$k{w{dVH%EWO-Lw{u0^4E>&4%2^HoZxc# z?320QR%bSnIB#XDx@$<_CI{htB zP6`p0%YObnz^B`K-VS#Hf0rqnj(O_yJG(z319Sp5i}S`Kv-wbf6~ z<;dJt8T*237sJTW)?5)zo(*|eYYWEjhh3>1*I6mk;i-Je$0{K zV8}1pQhLTD+wvQt{H!sC$ieFvr6+kQA8^?Pw=m{uQS{`IX*NUe#GrKR=%5x?Z@;=+w7AW3DUr&(i6X+!7v% z+uvpCKF?K*C0Hdy{M0ym*}mt5>dE1T@!AQAF<+c~$asyLP<8H0A98a{{Jqy6FWuV> z`(!-?{}!2!E$!uWG8}aR*5%#4h4qf}KHgWkuN87fJfSLR3clDfos_=^()vfzOL1qp zcBaPvjw%|u2aLe)+$t!=el@{0(7R8tg_acg8@c&oY&4phiEGt% zcZi&?4MzGbwV^|^)0m3vG8hiq(aiUp>WX}J!yT=mcFS?&*s@fV zs;%b_M6!30FU#Aq_w6_Vs0MKh5g=_bagddY@K<9-o1NER$DwM8{!w~~7Pv(yg!0p+ zWd+%~E%fhh5^AI&;WU-=2l%c^X*Ay~5$rw0rT8PAKqT6AydtA2+_W*(L3+t0lT`#p zs2Z@o%a0cArdu?AsuCJLjE3bcrFNqOn_It19h5kC_;4^PWVW|~pNSJMy~g0+=&lzd z!Ndw#TjEEMs39lMbd&j)OPO_2^G&lBnMESc%fKrbFEG5Dd~2wZPmm<(cNdE6Kz%~` z>m@VZCRDd^s16*i9V>YFUX!5xF+S^7n$N{RJgKW60fgxJ;YX4j04b|!xU%%{f`zAi zbsD_z684Xl(@zGV*NpTeC8x9sE2OuoN=>0-po|vTxAsauyJ09I;2a;WLku{2(~4ga zkxV?)|6-t7%A!f+Y*G>PLvDY<6o&dsMPMwo^*g!z$>JKW(7JmXrT9oUtqr zYfOjQBs8*-@1!QIEcs>PaBM8o(HpFRyN~K>EaMz$Q(XwyP%4nMroa%`a`g<)Y^Joo zEa&CM4JLjeY+H?BcKecj;eXbN{(NhZgJy88zeh8spA>`{HB2RW;WFg=sIuhtWxp&X zldOZD9DGHg!5Q*kF&g~?E7*US=1b$7A#hy@hTwjtnM1}<=qjE47&Ak zS@fnc7<(U3;HyQD?Q@`rO=&n8wDj?A$U&w%&{X8>@mm6%<=FmxK7VChAQ>CLF+Nva zUSN}<{7sDV$ImPqJbnNcSn<9GevMrMRZSDwr}44({%&I{8Tn09=8fA!0(AIM+f&^C zvb?5xV^DXZben$H3NYOM3d6+~@5lIL;tdcVD;xrU!sg7l&GCJC;L4_r(tjiAnlaex zcBPuG-g_a%oj%61OK%#C{(5vg{Zzn?>tB1DRK4+lM~dTh@W+lo=)IWr2ki6sPq*8q z`?rJ>#(`gKrM&6&&R5ZQgS(4y9e=I^D!kBC(}hP6d8Nfj-VsEmeu&kg9$(OdbZSQs zRmO&Z&GIsb#}0RDMWcTbflrI9-KTO=KTPdIk_Y8(q_1?ct9Tpd(v$2}Zz(10O+&m( zD?E7JvUzqZ&wH$+7YLNxNbN%#t<>tv`yy=cpMK%dsbkpHh_p4JZ@DnG*j|@Crg^Z4 z?0VkUGegI<1h4g8-O!sAQiY;|~KCL1PnvVW-^O}RU#W*)2D zn}B)-&!^je1i2->D>;E1jGe5!$6pFdS4sM#Y)-0y|o z@AL7S1SD*Jvm^bL`t7ym+`>{K%u%abv$(%|hl1RcTku)g=DAu^%{y8L{>=qY^U7e*f zUdmm7!r3UO1lknd8W-`Pl6(9lppTaUw8~(1>;LgsP_4_u@u%x|hfWq75wNq#b{h3( zp3_?pF8P!p929X=eq6Wx>8a(2uW4PLkiqBl1Y3YIhe1R>sh{9+yWeu-gdeZfort@>m~Rj>;YS-^+>(1Ft-%W#P>xEh~VgU z&rS%VGOk z{_y@_thc{VWAJmNyiIcTbT z1aGwEehASzIKNlez6CARhi${nUTzIfwcOl`-l$%~E*<4Vq9D1r;~o@KU9sKc>$%?V zMyJM55y$Y$b`24apN4G-zK>!vwt+`Awd~$S?zq37z+~@-ZqP{10*CX9w%;&_R`*;w&I>4Yc1fC2!7%AHgtc z3bT%#v+LVm>gq%5Z>&KkG$U=WAF34>&7AEx$_+OZc=z~3m7vj9Xe_wD{uSrgY5C%oDfl(Vo zB6<`Zl8a}TvuB{%t>d)GmR3J$+G%!_#i|#(t)OA`{!SiLUG`2xQuav7arS0Tdy)_0 z74h{ns(M~e#DC#PZLbNYBze~Qs&Dw$W*~XIV__ZYBRWF$f_)<^RBv$yv<(I7C5hZQ ze|XLRv=ZXdzFJeV>eLF3-Y`J>O0(Fd<#$$~@yc?X;|?&73Wrmk4U?oV-PxM8Z^xpW zKcxyare8!5JLK0?wDRY>(g6%H$NtrM8o@Q~r+j7d55dZlVZH?KyBbLvmo5o?G%ID~ z#v|OQWo~ zGL3~C;RWi5NwD0}gj(LXHNRo}fLp37l+g?IRcbn8FsxamS#zvFJB~cFEND9?c=XiZ zbOsM^M#}m8?mmemoGPs4hgY@ay0@N}&0osQlx5Y;lsS!g=l&+g7*7%oUJ`0RpHIa) zy~#_6wW4CP7rKV2vMg{CR=iwo$a)mXi9ga(%>b_Q#8X65u(4_wc{Vc7QrDxj7Z{m& zo|dzS|5dBY|Eg8@$cHEIP^A34r9Km-TQQ2o+F*rUFbYGRm{n|W3tKXSok^6pUT7}Q z5QgqrNGt9C0F6L$zlu^rAc8GPZe$*exub)t!~{Y8o?k$!q_G{`_{DhFc+3P5cxQO4 z#EdGxaDV6;vfX1K*kz;%_l9tc#bCb)tg*FlmABL-SqKkfwR8$Ny#{oy2X!$6hp`ls zHG-LERimRRxqaR%k*h`+0A2pFBL}TbPiG{L=zpfIQB&ia^|$S5u9(!?w%r+{6@IWH zg9IzY$l$ViV`ovr;oMnr6BZi>{qn2GOH;IUxqlGcDZ8wuEAnqTkVJB2W+Yx3nWiS$ zt|8cca>ciYGb9@cW~^GY8)3{k6Oyzk=S)?nX08a`tx@3_kaG!`=^SHXc#?vDfH|{HFPuI6atx zlunzZUr^GNoge2M`a2c>IsVwkrvdQO4(#`|3oj&u3n5@fX9b}VpjTy8dcfPhek4Z= zcj6US*#)nSD-=@%E<5QtL4PD0tA7W8l*TvcC$SjcNbSI}A!!vLDP2|N*j|wmb$bwh zlRf~I%@D3i7zB5;U%J>j*(zI<>8XbReE@&uJ(?E+PV?`}dn7~}BSDJeVO7HNOA>${ zEefFU0L`Fzv1RULr=x#g$K**tYp!%oD}|gpXDwpux}5wfKbZk21-VygOn=%MNuImt zY?7eZypwu{^qZJ7II6+W_+Y^%;959PsLF4Yu!5!%ul@8B-McmpkQT1;GnqF{ZlWb6 znQMW-i)OIK>V}JenfmZMC??zYqbJb&6F`?}cxlfG1_uK4G-y!2xO--R-5h#>XIrOT6d#GJD1$VEAMs^79}QDr2#Hqr@anuE@7c;-hVW9WM&&Gsj7LW z{ZO9hA{#h9;uIAPoY)#4zLfJ7nRu?+{L@!}8L&H#Y1?=h?l=$`Y^MVwEqAyBPy}$ocdwQZn^TD)73WbH3*vf>r7S!Mt|OhaC)d*Wo~WxNc7n-+9EoZcUH#>SH@7Bv@4vXRW9%6o1MfYNob1H+zpPuqVhM zdo#fd)}~!t>L0Hn3#bT(X2Y1uZScKmG_Ybzq!X!5_;BcP9@XwzCt+uDwG)+9Gq~+7 za_4q0sb-{2QeLAlgW%lw;8>R1Z2g$dp_}ldRrxgsvbj(e`E#Gh0;Y5zmfD}sgiDuF z2Fr3py*(OI41Z|Rw@=-lVnyBWhlM7I^p25ZRdqoNcQVI0!ow{1bd6Sd6gYd*Hwsqh zMB|F?IwtKp3gb;%B_Zb9;e{PsE6(#`d2 zGz3S{)k>8rw%e0d%i!>%!!S#P$2NJg!=B|rA0oJ5tw_3-cD`^~Rr%LGBD%fnX!>l( z%UBzID+9yxP$)Ha9o_nk4pfTB=Ciu1MnE(czv^qcxmy8E2aFuKba_>BgqiIFXev&$ zV5!JRJAXe(A(AG5n(PI{nDPqfO} zfG|=%KX2#{G@k_sB|8iA_E^*h@0fGaW_TRA(lKX>rtorI(WHRapR!oP|7y@qPEW@_ zC0OJ7b=;X|-vSkhC#NjJn+=G$#*j({&!Zc=nXV zM6}CCS9`Aa7K(pAyZ?XW@o513$m1vs)~akJF0Z1?wfVDb3-{#yilYlkylSi@1mK|i z8-LKWlu#(q-vL6D+Q%0XZ9=smWD{~6Hy=#Y*xZ;v>#;UpW3|5{m*QQn;&)<$6)dKI zCEjW?WqP+x5b%q9A~|;Kv;?+h(0p(pG}Z@Rt!Jwa3E?H@Ju12m48lwRvQ`2aY@T$F z1A^z2P^FzTRLWzo$RD#(qq%P$4o>DrCV$sSh_)z@N#fadzwN(eR>PFy6T4Onp1MPV9d(5jgE(bO~&8wEHswUiQ5s1uGX@rtt{a z+wR-RMEDqq-XDnbDtJBn19RwOq2aK)K~(IEKD{DXf_3*!A~yBrB_D?tgOR zWgf2LjxUwMVz;u;7f+^%~dQjkrF|$U42Z+JBYS zc!n)4;8)|$MQtPuxyf`3c~7RXfgZ96KN_&@%`5$S=3h;}w(Zvv=22kF-?^v)C}O^w zX2c1n>B1g0#Ho`#7t4}(`!YYpUw;S~G$px?ZsUK9c^XyrHJsEl)`Jpg02)0%VVtN* z&*5i5i-YdLQD!c`ruWu^j(42$Q_|MsJ>{^*y`*ws+_Oa_{0Q{*F`A9rs7KxpOOO8# zndkl~)5+v)5IYUAY1HXac#JqVe~+O*18HTL3PxDU7@xk%9 zdtpziRaJ+Ua|^jd;n0=9tYaphESHn;oq>A>v^VK%_xNP4p3M?@UK6T@pDySM*U-c2 zq^BRKfrFBnV=?KCsF;Y;F3+T{-n@RMT9PXpHoV$24xr(6b0prC-3v(4cESCQOONgc z@PUaY9Y0I{(n8&++1Vi-K2e%02%MV z%Ej?#`{#+7D9pCFGxHti*ARc>-?K#^dCxH;|95l%uW)UTd2+2KcFB86gZ_KU+;ckN zcs6nFI4abcvy+aKm)^A0zOxt33l{-BZW7a8y&67oJq!7fTR5C_>HJCkDT5K~H?6cu zOLfcYTw#v(#ebI?$TuF$d?FMqLcrsI577=Z<{>lV*h+-a<3&}ON5#A8H9oCLJLsAu zV*dR$aY!~8Inw4w4unKkO;IAXDPIk_K6NP5(qmb@ZI+rD@rs1+EA-R0mK?6>imd5N zr&K=2AOH9?0Dj;R2fW{PEf+*8nhn}6ya5BvaSG=FV1Eog1H2Q^Yh3kib$SMnF*a9_ zu}yjnN@t&){at=;01>czu4hQ26#GG835$J>k5|+NRerhLkWU}LIObMP_zrHDbE_1- z8adalaThqpR&Eu~e(v1totiH2M;g1{J+JL?mKrk(l!>O3T2fs*Ke?}Man>r!Xc-Bh z(fFAv(SJrV789dQe31tV}^td{{y$=l>r_H_T3qJNdgkny<->fLUgdSe~0m1J^w)#kjZ zzr$mUPtz9r)CLk{jpP*|`*m%TfX6Ap?A&>_9PVUX&mAnwLdkJ>*dShA>BcG%3(z@@PM*#qrV>WcvcsY;v<&2wvVMb zF@HUK2;!iCo<7?K#NZS_w&O(&(MP8*^zq*MkkSR=MN|!D-q%XkvjlI*bIi8Kw_UAr zZ1f{_gVor&R>%hus93c`_WTVgpI}^?r_;Q_TtuwmTw5S2oO+SJ88Kb7f&><-VT$_6 zShXe=Ec3ZPwYeSo!_c0W!%BOw)5JdLu7BYl7?9U75|VUDBg{`KtqwKvv`~;?4en~H zT$Jo)$td_CV_kXu3tjpZ{e*VB1u86!zX`L#qJH@)+BxDG&%U!a&q~}qV(ErK-D~}L zai)t6l_!==ztd0yVLTb`R9uXye~uq`d>Q~h@|X#*0OtnMGra@A)DEJ})bI?pEPw8k zg3Z+ZOo9p21c|vSIl!ZFzR$bJ>Ev^!UNfaoAf9P#VT2ieCcO%xy0VY^wTNVRl=Vz(J?&NQ8)MwZXSZ6b04>E>;n+L(N>H0Ci9 zs)Ku^1rJNg$d5DtR+zD;Wxh*XXn)h3JBdowTg}e<`CS8AT3C~>dc3AAFl#57uugWe z^0ePAr9E%sEah@)mK2;~|>FO1WiGTY7ByslC z!|q>_gXDOk&%`n|in7A@8W@@Nm)>@EqTZC12dilNS?nKkYAd`kqpdS<9o5FP++Pw>F{RI~SK{jZuN#~zG;y=O=W6L(ueU9$kpF)F+S>fe zSd89&eRKx&n3*)oNU<#6pnv7g zJ7l%*$d~>$&OrKGcQ!U|MKeu^1G4FZ&e;%vpK2zNVFm8yrba*Fd4r^>1L_d^-!i{* zi4kc&#}7C@4S*kZ(0@hPBfSewrV3n7RPwUDGm(A+$qBnjG@jr?Is$uV6QCaRPhjEr zCqJB1DbNft`Il+YNY2I_dH*bNPRVlY$l^(%L(hZWP(7ulFUdNf9{;{CVrRgdfkjl^ zU|dKfHA-kdTQ?(+KgQp*==n2@8lgTLLFc{a%E21<<;@3#fyJy#m_9k1uYi|mrBhiKDHqXS+_Skq0nK&66TPu^yu!sunRoU`irBwzM zwopiVEanZaF4ALFg6!FU0EseZ`Df#TN*EDWVI8`d*OM@*0M&b*Ijvj za#bFgK{G-&ibo7wmu`Acx4{y&y!z z+z`w!kAF<_mJU>8s&NolP1Deg44vzEXd24kxmJ8IQYs)fghe+p&;;9L=T+VzCfaSY z_%06ixfZTVV?*P~66iO3Ci5^2UHFs78G>Uy)wt!9`!q+!m+#5RpzjRrziSVghNkpR zoxaNg1LfDJ|o1A5lR3$cMIrX;Ag_{Ob&DX29QPq zgBe8`JI;XgBRn!R&AHxQH&y_bkzT7BH&DJQ-rl@7uZpP0tmn0}C!XsSyv{9SQ-ZVm z&VTaH{}T8a=nBC>v;aV#$@`pj(sCyBD2~^V3M_8w;tonkJbW+pAG^xx)xtGrt043_ zY4CQt&{9KHp)KPd$pE(2>8w^NmyLcW^h2hU)NEBzyP-Gl6)c~Pvcf3yGlkhS`BwS) zJ0wCp4|)@f7Au@mvd1%ZV*&gPkj zJ^3omp(JE=@e7bH&QKlOzFPWwVeH1DOgo{Z?mUlPyxKdCrJ@_NUZquhxJC5Sz_)7e zYM2F6gmi6i*s^CH#lq_*oA)C{#14Zwlgui(YJ1h^>jmA&cOtX!9n`vR{~|rhO@9mu z1Yyox81rARJs+;QPQLc|nM?W_175DaYCMv$%y8+;JF}v{rDBD~$6{0ap6{1m<@0me z;P^ONXSXb%J17l0Dz6ld_L{5Nu;l)OKifX(SQ%fIyzcnZ_>4B%vHEP$_zj*yhcVG~ z=dv`>%3sTHs{;kjiZ93{Rb1Zw3x8RQX4`3SCA$MMj!j$x#KF_ZsXr@2P=i+G) z?nQskdk4XkRf_yl?2w|?^LnZ6eoV0*+p60G&t(AauyBC~o3M^Hz1nd#zQ1SdrZJnF z#sw_nE+f%uvR2KV8quNtzQcnO-{i^md4Ov}P8ce(ThIx0!P#g>7@M(Up?`t3M_Gs6 zK{uNJlF5oKj;1U~Ox_Io#s4(d`0KWT z6E;4_&p18}fFF0L%bL#h1$5ith(%1eQaH_(&qwm>U{f`Uje&?GwD}_i=sO)blCKdO zlzxQ15hM)ab@6UG;!ad9SL#lKq)RhH-S$f8}Zdam3bD}U$1rXJG2M_k8y z-)l2f5-`Wp;|Fu4?g-4Q9*M|k-`Ln^;pk-K@IUexECSwm9@*<`c~}>GZQX|M8?$n8 zYK$Zcw(pgXhizj!f24o#$wC_@dk^-q-?`@KjhVpP$x!4ve{xaRx9Zax{|Y~~LM;;f z5B$}B*B6iG2eKz`K7UO^`ATZP$~H6=`ThE< zgbZuTD|V-OC7S~zWHE|?*Yox(`bP0yZ}d=`e(hPkx9IDl@;EK!NPohMO_T7)$*-_? z)83%_dbM|aoVGh&@A+E4f&hoGIq3dZ_^~ey+Y~EF;*CYN^?$iCDSV!*&R9v+^efkw zG)b)CH344x!N9VFwXvctxr}3_xTIM$cn0H-RcYhOn%63h*2XgKoMAyX`N?O*vVo}$ z2KDcXUhWBde-;E=n4%|V!8p+(GBoaJl!i9aW1Sn{`w(E{I^U;BAe|9?O^fE=a*R>j zS6J586Gs4cL4U4kNVM;nH8O1+d`mA|#@YceuC*L;uZvjYb7(QGyNT#sS}T4c)8peu zr*A|-cw3p%I+ol!dWpZiDbgk9n)fkI4E@*Sv5XIBQf*x?&=8}_ee~gxg17wiz@s%Z z{yBcg@o513xFbMf$5%4Ya3+CjO^^%b?6jOn?w1OZ@qgk8v{~&}$M*de?An3ojJ2C4 z6ieq$1O-B`3LPt3LOQN)w-IYi&>mc)i|$+3V}5aR&kF=IxSa)3cmaWsdxG7zUa?c#7n-2g@d_O(B6S(JM&2v=x_<~o$JH#uAkEQ}5LpJ}I-J{gwZ8Oz zpIrMvb=kWtWxZa{jO6V$yu=`M$p9%5}$Dv#K?9;VrJB{Z!Ne7Z-2W;{$WeyZ5=o z%6}gBt5}jwA1*F_yz_=Jq#mCIfr7c|*0seF>zOw1!mkFzV#X-djiH)8U_9s{F^YaR z3jnXyUx$8&LB$$*W;vFN(==0IUMDa-*$S#2BYy4c>+4$5r)PD)gp3M)<5pnGKyC-W!Gd$!rs`e@8xvD-? z^*o4Q9XcOwKs`wwg~DAn#C%~3;@wV)cYZ4-=wHp7j_b!`0;ZQc5Y~*%@THOKTS13S za^4kv44-*I+nlQ-CpBb;Z$4ZK8Dfv2COP0MHvI=R{W<;!$EN}C!;TbL0*T^!0F0Hd9eu`Df9Nt{AMzsLUxA{m z_%vAhh~Rp;oQR&_zaXn~ojR}0A%Di3G$%ti_%5sQ&`eSvJwvzDc%qyu0a5{t`a^r- z{*eyYbDw;kuF4k=Ux@Stg~dRJYom0;lDpGr2_`zQBeALoj(?;A`4v6`#N_jpDyVU0mCO#wGp zymkMWgRZ~jV%QK5QizgP^H#?5DEq$IcA|!c4Lb9<2ml0J+x@jQUt@k9_@_AVr2#=O zovFcu3EnTSTjsKOY(F44V!X(BH^la!Ucr2aYn^cx-rKGhXj5)9=s$pb;PA1qu!0Ac_kSTbxz+qkJ`%g| zSSSA#j8$|0Hs1yfgGC|E@L?hf8#nQbIR=?uxbepCp8Qd+YmUQ4;;Jdqu{%V(aM0!i zpdYd{F0*m9j(K#~!}d7fKDG79745fh)$`s3fd-dTWZQ?|&^CC6+;V>H-4I8kw=vc_ zbWv|~PkY@LziVVyiGPP4I#6@3z{kLztr*(c=lD6trvdQ84*z!YJJ5f8@+|z%ezU+r ziO$#(S_Gywf**tOh|4R9loJjYT+1s!9TN76&oVtJqK=hNCeBOr-}0CV*XF4euzL_W z3hyC5v`XBW&&K&1tJ<;7y}RexJhBRTZv&=(Sf(KhgS zjUvo1EW4~AV&!l%bn87)R)zn~*K8Ps`v-{#Jd&+{swhgWn;ck(_WVo_A{O zD>d5V+qb2VN->Z@WqS*W7b9Ys5!t1;KT6cHfg=ga%3$o7Nl(UCG2A}Kv_nai5;g{Z zw#%|)jwEN?_kV6jLwSWFW)pjY7)xrqX;jmq68wieYn)sD#yrqllNaktIMCTKFt%c9 zTC9ALqZTha(aEm{Ok3khhvps0>+5L)tzQOsxP?AzCrh?=*wjVO9#<>g@zE{!@6TW1 zdFl*2>pIeBDa^+jOya1BdN(I(tZ-KyIAOloO04}W34aHRFX{DbH&CUltrHc8J$C88G-g1^*%m!urj?KukS$Pdbf9@(ozchFf28y`DbG8w^Uy;3}WFOlfN^S&6 zpSC>S9Dl&N=}VMPhrXJ!)aAj8Ip&~E*dj8Oe@NcM{DGB`kNpt*a15PiRGqQ|44(91 zoI2iGug5iG-osC+A`LitaJHA8pUXDLD}4g)ca52@#WIQ19oL35{m3zYD=1+|d&p%5{tj`5x6X zuYWBxZBu1HH9Z?K*QS^tITEgsD9m6tnjLij`CvYpt<8HW(K(U_1xtNVGnHCmv10P;!oNk$=Fvay}B7*1MjSBP=WG?m_ zea2rOG||vWm7A2os@Biar?BeC=9=>RoM;Da_hkf%{YTg4Pw97_fB!%K>-x_*6;&9i?IcL+m8iw&xJ1y49D0Koy(&$f`jctI9VgMtlBI2 zuT0UtuRUJ7BXIcD_8GY9JnYkpthq_<$1Y%h?tQ3nooP5_#?rh8eJU<|gGBNMBN;T8 z@UAyzV%0SA1Raln0~&PR^YoyN{C|jN$)Ium=9RlO#&lC|kc%$ju0F+j%8d8><34O* z&;kqv{~Uv-*mHH9qPz>QhdlE6$*;y8I)Ogk;@S#tW4xZ{tH9ey6Kwt6{Db+PV-C5D z7yz1Al`a3UCCP%hQE@zCCFd&Ggs#P$4>=q%vCjB8<#70g={#wq5Y92gJAdqe4YUVo z*LAswen#83S~PayF9ftOo^b>C!#qc0P()Qvd61{VoTTA%{H){C0Qg~tzwixc;T7hp zSHkwUB_8KtAUKZWDnA&~LhYX5o{8s+$kVmjzkl zKFCTk5$H;4ma7$3ZVYHKj*~^UHKgf+3--fdi?*rHye;s}Sd{_BijIRHR+Gg$MC)A* zlrJI?H)N(s7MpNg&~LP}z?a7i(jFms)QPp^nf~E&97<=n@-%})gj!koHjDLU7`L2)*1oiW}lTX+f zR~#LinRmbzIp25>+6jey%s*}o9PxI`hv!Fp72PDE$DMON;z0p#54vd^hnOCC-@LEK zA0LUA(Y@Zs01la85ZTP+b$f~Ry+9+FK6rCH5soO{_aghg@RZSrTewEP>@k4%2MK;d z9mtRMXyc#-GJm1DE3PqlBI{$PmhL-NC1|7ab3L*niCVo&n7Vv_viqCbvyo;xxcK-+ zAS3)(&lBwCXP@Jz9G?cj4?7qn#+JaExrhq06CHgWA~ElEumU0n09d9@c+eaJM1>YE z$ktAR`f)vD+aqw{Gg0i7iIFVLEzmcMJq7a)v@t&E34d_U&rSjv)Xr^{cYV0|-Z~ju zi)$WdU>QVdnnhXW1dGJ64Y4P$jAY&x+2vKPoIWD>LF5QX^*kuUGn3Iy3ZXyhSOhDK zg#gB+gP~(7h)t7Bz#kD=kF@Mm(#g5#yqQy?=~bvB38sC<_On`eMnsjWAqA_|ls#nT z6(Y;w+<(eEZJ)BIVXsN#V~nwqk6eO9s`Qe-D74q4+oC`9A@S;ib<^)L#{K;mXB0bH zMLdZ0PN(mGUa|44dZ>VCBp~IL@{uH;E3;j>Kynlh5WeO6Iv(ke{)VZ(Y2MV_NyQ}p z8efkGbWPnBnxe1VBR~BATl}BL@Bi{&*YEz--+v?M+fP#%@BtJW#Ih~$`xNaX+u7Y* zxp-Q@9r@U94oI)4OkLQ0)AY4ckhbnm;%bZ$z2EbyxdEqg6CA9>cV~3uiY1AEsj-U#2WdNcxFaUM4QXYwpeb+uYT(2=#u&IK+PQ)XxpF+~I%YiLYKmab zzc3H>qnJj^BgPM#4QfAi zq$|2Y#lCqR*Nj84VdZ|ud%X|SH+^ECG=Ca@mKR-y3DRly;6vV|&lBLpu))w_`Zw3g zS{gS-zROs^!Ph=#dQQyf`0J42_QQA02E|0%gV^p+RQ1lrKgUlwJ`I4Mb{sga!?A}^ zb0drc7VlYaULSa)e{L*zioh19FkvW-&nGmIERamVvD+e3L)&I09~==sXfK%WUCp;5viRltZo?E5lCK>v<@V z5FMlw0dsAlMnD$v;=7-+QAb>>UtOS=)6h0}-nl|&P6X7E1VVPEhYbuRHR5x@UJ>}H zzF`~u40D7}+Is8-PL@RI(ABxs@PABVhq$YrHbckcP`ZYR7G+Kz>dkmaI*?a9uxaS3 zpPw(t;M~e-pXwUPDU1J84i7#D{^YiMKCHUF(P8ecxrJVj60~UB@3GzANxAG*y9v~w zu$}ZE&REOw;1J)>n_q?J|GhtY06*S}r@i~(m;dG8)PJetm%qH53V-^4{D0j|*NPqX z=IKkX@1#;+co>_yos2l(9XnqE*ffh){G_t_e~W(m^w%0XZvQkSzN6q3fVuScCEM8J zt1%&a6^*8Fo1*yB{0mKh&W*&7`!5QfSH=-v0$SPr-C)e>=EU?wkQr`PFyg>a`n(Te z&w5@j+AOb{CtYqVeP2VcMSt@r4s>YS^PKUD1!iKx3WixOx!15l93{;FSD!+x8O0~? z=foMuiB(wvHRz+rc{5KPuZ34v5vL-}&7`AflYPn_AVb@>?V-kb?ZD~%Ic?Ikt|?pT zO^?3>{-PTecDB6(+XnA@vb6<08UchweZ+Cz$ddNX*nBRA*gh=E?SIG6gKd>EnBspQ zlWM)sr+iM1gac5D?Ag6-hefPU|pzP-yN0gWW4%Zxku^O~f_n>PeRUACAn&jt_817vWlLp0Ke-}%M$`78H&>^}G!LOl`*UIIWETNF9^8`;En^XP_r zKi{zs8EV|@@`xW^MXKm}fnL$#;y=KWL^fdJLRNH;w&9qYhgXfH=z9ISiA%!RmM<0L z$5Zg}@Ba%H|9?Eb=lR{g`is3gVF625zC_TJm(t4XXgluLw3lx&Y8OT4E;r~5Fk2of zaHN-om90)W)c{xR2)P>*Tjp*OuAwGkVhnJlQHU|?OLi4Ld8>g~c=i4Ab>jZ9Pv8t% zz{=K#EAnv>DB1>%ka1q#v#Fr{jbizfNf^+8xu>MBT7S70XW0m#?Y761@9Fit*3I=^ zv#{ubtRcI`%I272j(s+3rV#Lf-_I4%qTF@0Xi^;5g1lCU-84YqKIFRZu{}hl54`W$ zG?9frN#!|9;mki zok`@G5w!|)=$LZUYbSNXK6+f|&#F^gUYERf(hlLEN$^mx_1qYD%j=u7&i5YlzQC*9 zlAreUzvhYzA8EK(c-pl6^7sGi6#qJY`G3oQTYvg5|8CW$;nu^g$V;zZS)JytFn^m0 zJJud+rS07;glOuHhpZa*glfP||MUPkX|>W%?_!v)Vd0_qOdzZ+~+| zHKUlkH1k^A>$AlkXBB2=)MkpQ4;9uI;#4&hOh;kohs z;n$1}x|(XC4sf zxK%Us`WG_doxNi9EU+W{;1&-T>)Wpu=yy|1v+5vp-1isw6iAT!7KrExH61-M4ZZ8vzL%c|Eq<=`w-b%762kb1NPL z8GsRikfir10Kc6d_?_px1#+&~QjSBWt?hf2gbJ}_1UT@MDZ%K$gI8uTzM~HH2ryTI zwf1#u59l!}W1APz1UZc@w1<5}UI;ypU^MTg4de!{Y~G(S`88j#huU&yy+EH3X`1_N zSf#5FdOX*fe7FnFWHpML#eXbxMrOIycR_3qyE?|!Ni`|X#Ae76K1e#ck?1bYi?DzZcYZv9B|FO-Gguh}25#L4+ z&h0O-+cx?uVJ=q9M^@c4M`Nq|_qkV+|8IKrGk6{ZKJd-_i|rn5`F}+M+SHC@u)K2l zeg60V;NPB_`mb{Q{_p>r`rW_$i<0vZ%L|WCa8PfOS1E>|VyW7BC1nww3BHBD>f?I==_A?Y!c2 zer|pb#8OrBu6WKt&VPN6eu{Th=CsXxt(r-IFmUs0n_IY1WMk!70uioCbnr25U3b)` z{7D<-Vxf0*=xd397*B6SCw>27b9t=b{V1^t2oSkK0EwM@Cmv$~xQPTs$JXGRqImAu zTH~zm1!hM}d)DS4kVR=;@e#T4!KmBRsPVOJ=)`%=9DbKyZGTg+OxEL`iSRSV+J-29 z1QPpCYmO--n&O;!7;ns_iLDD)AN~T_z5o1_IQe3XLTsBXkH0LmZ!+_Ku5{r*odE|KWGGy~B1t#~=OpGys0s!9dC4LFXDpjXop# z_JLaCd?lGyUVktz6v*oyB^$V`%kSA7;0hz@9YIAny%T`m3C&pba8$f6%yUnoSwTMZ zcxdN#nv=i}mMq5&cu0;4LF>`!=Qvf*ppAQ-Bm!7jwT*z;089Y;dLz@qyk13KGw72p z(|_2@ZxwrzO}=EPBJag(vnr=S=C)IYB5d1~jIgU=tbc}p&J;kuoopx=54oE}ZVk@e zr>&~+o(Wi{d?zRBVI(1ZefY=NCMsUnzMrduy7lmXj(&cl@3|V7=_Ok{DcIb)4SEiH zZ8d4|&GW@;Hj&|Fd4=mCGbXCvFJ7E8%81P$X;**Om3Xv41HU#`$Y$>$11J&uD=QvV zrIo~0g@58kjg(;p$7-H@Z5MU{6<ZTr%n7`o_N*#5t-PiJ5@0e@?SsXdUfyX#rF`uYgbG^TUx7BWpf;%LyB&oAH)XlCqCvu98W znzZ|7ZwE2%JKpu!@p#+eGG7`?baaW<2bCj7nWzHsjM#%#&AF=pLZW^a?xGa22f`yS z$bW9cQcK=}Y4Tqz{G;t2=P~GEQ>R?!r@VgoU*f>@z|d@}HF@V8X)`A+>2mBTjk!-l zO>_i5$ZPoL;O%T6Rq+vs+ji(Z8e{rRXn^d8Z%*9@9cB~cXg6bQ>i)j(^tv8=O#LMu z&R3M^i3OkIXB?jfzz;j@CP;+z`HjgbRDTNB`V9iZ32Q!ZJ;A=taf^Za**PDf1%T9p zP6f>x$&!QYu0#fXN|3OcCNd|y9{freS|M}-F@`pnGXdhNfwy=K0k0uD?o_CpwbIrm zRt3(TTyO=D!84?Cmj#95>zq7BciDCgnsGn7&XUuaaM6UknlXa(X?I90wbHib;(vR^ z&%sA@6M8t4wvEnieRvq`HQw*}&K(`Lr!{3wAM<$H6#^Q$SXG<{vY>1&NAX%o9vR+~ z^niQuBXdKtQX{Ed7(k4*cGgtm5<9_Rm*R zD;Xme4L5y93dYs&#wuz&_a4Jv)PJ`IkFhEGUyZ^)j!8+u|#dz3aX9PKuif;JLx+wzFQLb$_hzf1j7F z9lM#n#5f`Z{ie-J*{9domW2ka$J+9WH5!XPKzEGsCTyNk4faFWH?EIs%8YB+V#u{wcd~ z#HcWB_AI2s<4GUwL`@AK1Y}d-gEH3mn)#{m!nIGWOu32ne$WNHqxB2rxPdC+iU z&q}O@ghq}!(Zge3wCq!-El+w2l-HpAbNt-n(*XEkhqqWIub#Z_zh873$ zBk-33X$s%_#7@>6U;?-XR;=`m^g_?Ja)oi{DH`8&ihyFWP?HwCA6tF5Oq^I9vUqo& zo)uk~&ESUlb1y>J$RfB}pWvpXDZsg3S$AlNY~GntbS0??5nu}Y_{mET{sx&NsGYk4 zGp@WF_HSx%E0zJKP=zpsDom0S(F{H^)n za~APNw*8Ir-E%HK_MoNK@Bdz*V^4FFdX0_7pR~~O-MRWXv81Lve;w=h|M1_}PdtA4 z2miMI^nd?5P88j+xzxXtX6?F?EQ}>;xGvv!-RmxxKe^?vZ{x?K8*`iWJ&CtY%SSBR zecpJmZA9-ESAX31bq3I>H{$`oG0nNBt;fG#*N%rYjuJCxV+0 z$THBlxepj(ze!_xSYm55c>{~a=T3moEVMf?3M2IKIWd|gVlbS%ye~C+@Rl(Lz7Gio z)mc2sch8k}+W`2_7-@#ocqK_pS#*)Q_9klC?HSWz7 zn=tIQne-htuqg2k#=YU~q~KWl-uN=Y>ad=hFEsIOyLY24Ry*ZCbODTb+ST;QG(BgY zkRt!7=SR*9`A*B4ey?UHygV{F6G-c4&)B*@yr*Fh+bH7MH9WamW6sPbn`rM^Avcqg z&+$`^Pk#g8#~msLH+VE*#?c%A46v)fh#^z~dsUs^8k ztq!LL3ILX7Q{$TdE;`&)=%Zjn0uWjQWLZH>vT!Ax3kll3*+4(G3Ll__RTQ(@p@Sgq zm7E@T%-sYbhMo6l1gGF1;N0Vu7y|Z|M8-HE)@^#x!Fr@&r)4PP1Tz&i2-Pa0!jNb^a z=$geBn+Nih8PPpj<%;R=p>_Mq^}Pt?>t_ji7C5t*ey+ul=;$l4On=szS`p2RN~XA#U$h^&e6e>FT9>;con_B@p<5sT<}<8GjrN2fYhfm1aL>5M#vH-;0M`+?Iz`V0Ksooh%ix?x7OO|9k&JwQ;_ZY8)IdfR?DtAbx!6}w zHdG!&MHU_vVe3dnBu-rGCBS1fS_5;O0oiXFDUx{#^>>n+?+C1vxB|c9U4JNk$abD# zRG6t@g2hZY6j-iL`yE6lP@N#o)$&!*+vJmbUxyLdSJ$RFqg5%wvN3^? z_Bnpb^>dvnT4t*3=S6F#MGB|n)?9kZX~Q$AoV+$hB7d@LTH$3k|qVNmzVpx<2o{vZ9j`kQckHvxY4&;QQ# z+QmV(LzL}nXSiw**#_%Q9M1;yeHqt0_mO91HvaBwcNKr{?9sS&?0<@x&T+@7uLKqp zppW0P$9>k?j%jID-K+eZGTt0};A02Z5Z?`@uQV-hXp?oF7!{o00)eT*BRI2^wNR~} ziF`zdFnTBTCx$(dFn+URdS*NjY|ddE!-{c=PtCt@ZpH|6;+05JRi$PS8!yIY5O<6= zR^rd1*E4ikmJOMpPk(Mf`jNST*-u&49&@cpk0pGDFkClIHTjOzU2LxhtdFgE#KzsdJ?f0HHzS#D1jRZSVpaLGh# z&auYMi5hc>SAS&!rw-0=R*=_R<(X+(ioR!J#o5nQjLgbcGv&(XYypU?S?0Y@=H_Q} zwQ1q~2vDZenj5_5e3BBb;9Pe~fSjQtlT!|%c8yn2CHd+xO1*g(UT=eVBz40(o?2kJ ze^LOPKx4m`>!WenLmXWUa82Tko`f-)xt*asuALmvPIL_|fyIA1#;*muk^OEN?PVnu z+L23}7Yuoy+onP~?(5O&YMyN~a5hq1oCCvjKMT?#eJyU|``pH^6@NAkdVk&+BtEa# zq2ZT*^zZ9$((%hb`fdXJ?P_P?TQA=-|ElO@3#Ci3qwZ_9(ysxrJEHukK#d^D23ZPl z_}(@CYd^}gCsTi;c>$NMUohyqaQ}W(K??a zd1~rc5@W}X@4tB5Aii0H#~djU@~Vpdtw+Yv1W=r-J$_HDa#aaBD0|P{kFhLA^CC&0 z2w38o2q2ZL!7sUGLC;3E5hu^|lpa&G7_N^re}S($R@r~6l9WVOLrym_jx8;jp%5A| z!L&?GIZ~im!T2bi8$#tu^@5sxr^z@hMY;#yYekZ#1IlBODd|J^pbgCFk%fk#OK*4-2ceXR=n0Z*~+EXEMyr!sY>y_=KL%7I$yz} z#Mtx{$)bN@QNTqWz$nqQ8>MNgsPTckS`A6WPv=TnSj3|akDpMjg?GTHfzz<%eKBLL zM}#STj-PRS8UR1+xUpq>kN_JXoS#rSfT|cU5#)=`tI`7CbU1kCVu(%AoZ^h$yszp6 zhCxeL0MIlA;S#{-klg;7aSO?K_$KI15EC7i0!Dva04q{LuJ*{@?p5O&9%u2-#Bknp z%6xuyN?D(WgV1kT4og6w9ErsU$AeoYEG)W1U2NsPXklAhDCG>Kw2m1;|Gmz zMs|O-f}oFWp|QQW#&-GJMGtsokc!<|7K9u;@(FE8= z@wJDuJ#z}Z*gC`m$nc!dwHcOWEnFwt<*NMkYY1Oows)`WRRd=yCaW;I=hNdB{TqeR zy1%q=!RO6F^y9ojysd4G<3knOkzrd#wTr|P@7jzn$*~TsS_d{Du4qN{Y-F$qFUNlc zz)DFz%gu)xvHbS`_WU(hG|z47qEE6?@idxNh(D6~~$*okh0C8<8}Dm#e6bv$(s@Go66aV=NYN;PQV}BhbG| ze`-R`llQCyt;+LrM^ZAzdCGz@@QGh@6(X>{4oVT|irUP*q=kPaGf_5&&B}p>@R!_d zy`2)Hj*bxc#&Qy3Q=Ua{C#_t`xPw`WDNCmd!H9M=t%7vW2C`BHN<1%DZIx{(u^DGG zBUpLQ+o|{2ZW}q)I(;zXP{)5+R9g=6b&f?UKu*S7b)4GrO`;X{kc2@>PWpQ4f!4u9 zg`a9w!S-iytI}s$i z_O(jPh-OM^xa!ryNnNAW!3M@=>4c)p+v~+EzWeL{|N0;Qhx(g*d^dkDe)rG*_AMu^ zr0?U#imu0szMfgv4zum>!i+R@@&$}i&e6xK#IHJ5*uLd_SNqpBdsRPp+QWWtbts`< zwux)bS7p_j7$Y-UZ9U&BWLXWo|7`nTw@j3mC%I;fR1s2sKX_UzTg!Li9sEGS1b>=s zXUQ1yEXhybhG365?RnD6A{t?^ru=ytjI5Jm*b9-0 zJ5wT+J;avdO04TWw(w}!L3Qa1bk%qg#svR?88F~{*H1&n2M5XxTpTXP7xRl{S;nCh zl?|x{%hJ#d`t{z;;H~(|H$-VuSMk3YS=QD~58s}PT?gj+Zsva!1-iEmD*o$chiQmi z)Di~igluc(yjl+MH|fjXZF9JP&oCMZnlNF|yjaY(iTLC_XYj~+u+gG1uob(elsre% z_cm#=S&=8bGTLX?Or}kPO0&>kt%y*vfZ3l8z>hmV4S*kZ$OXqLwVk?r7JGaI2Q{*x zV!nkWn;45pxgdX%OV)7s2Z$eZm(S$tFr^}#K`gKt;N3xKO?hx8HV(MLJlg?dYViJ) z({;B19F)^P*SuL51nsy?qzqd-zW=TOL`snZv+F%>l(&&Gp6^XTzsgWQiNHHAGm6zqD zX{;)Ps!?rMg01|Pf!0vgB}aD?M-9JyM6mC;K_4R=<*`3|n%cd&s~PcbQiI zApN4R!NO(tz0OfeKM^=BHokS&>RLV7^ZB#nhWY|HH3q!$_&x6??@ng&W9Yr*u(mk- znUKxN(|&*dBBpK~_q5hFeX@tUW2t7#NOhEXNqcHcxGIhOq?5nt#lMbU{_(%B-~F>c z&%*upv33FOU=tnNMui{FFHy{En1U}+uZkUg#y#m8a@QVzH=N}!9VM?XkGI`AcBDcf za8bmS8I`JBs8?bHcb44Oe!0NB&u0~HG3EnzT)clw;?iVkiF*t2Vr$#Ag&(ZR)?f&< z7$;Pi;>>niKN=wy?>(;w)=L$b4R1S(RTQC(*)37%lpZSi2CWe{v=71Myvwht}zINr4zATF2}G`(|`G?p|5 zc;XQk!F9`uYTB!?3r(wAHjQSG>~uEUJq~!y%D-~RV4_#tW!vzFWf0wX>VeV>TooL! z)nv8Cjm)Hd@%`1H%KpphW%>Tk@w1Lk1K@wh9ZBd@>H-+)oVf1#+Y@ZQkMmoQxhkAu zX(cEZp@=0P(%%Ds-C;Bf1Ro_H90Gu7fL|G2i5QYBhSwTFA+k{-K!6`1X3xV8?b?C4 zoE*JP8O*zi-BpFrQw#~13+HCSvajo|x%HgIQS_rAGrRB^*V=j0z+lkSh)xhk2V#HD zJ zzf5R$G9j!;#pB}S+CpEDDOU7j!Qg+j(;PthbAS83a*2KU8r%0Z|F$6bv>H&J(cj1q z{r1cB2^;QtzyH334CUo`i@DvHh_5Nx>(IMt%Hv4;{$_*VB_r^CfBkF0{NLK~%Wh`; z$v^w^$`?~Af!rvtcWq4TVB)y;e=2kLm+Psy^0nPT%^G3-DmP36n~7VV&!K-!=y4bQ zG7^88->dwnz;IAE=@7Hk2(>|MG#KB^uY1+3+;{J5f)$8K8%su1q|s>?fUuQIc$#7R zQ62|aL(cLs$w<2&)TB4M`5yY%o)@db-WgzF2fysPCCsf-aeR-d=78>@lPTt~*(03W z)-r%}O9pKEXDY?B=hG`vs(%Fqs!SAeO zmHjFHA;LsS+Xx!+GOi~f-V#_Q=>Ae}-4&anuUo8cwxk)7FI>) z2JUgq0~g1piVZvax=h*Qybj~0q`eAbqq($dG<#fESTFTCe%SG80Q|VasZZ(Iv}F%m z0SdZc=iP*8UtD%~clLK+M^Yd^&DOLDAld$uqFKP#8O7jLrbmfH1-Sef=IA712Gqg& zEE<&v-NA_~76}9?1lNDq`g8;8mWdN41#HZ9-6~lraY6~aCXh!}NVdRR3RVQ6NO|EsJNn5X4mW?RXwws1snC!p(eJrjgw!%lK$8+^THLz05Kg%8?c`)t$< zTga{VSg(ymO02rHf}tkg{9SqQwqu@^d~FHce&r-e zxDA`HzxiAK|5Ja*H-A?X;Cd(hw&TE!2^E~)HbpzXKVP*UXb(Qfbceq~qcV8e1w3&n ze#quuyLfdEU|qIcUn_oZiuWk`=|K5wdHAeAii_=6h9T`ZDDY~K+q(hwr2M%z(d(7| zlACUcG#{tJ>Z=QfTIJnj zPCP{8*^15Q{8CZMV`N7NFPg_QxVSIdhtV9qJ@Cv}Ezx1sTmuWybTT0A%{*L_lS>)v1;|)AN6b_gx!M6iBSA`*(et-=L$hPO!GBAR6{--D4FLs(rK}4wuF7tT&TDnp zZ`zV*na{0v-zW80grciztngN@O{mTo+|qp}nksyxqdR!5L;t=tMfg^TcS@+Cu|Gq5 zrM!P_P1hm8aI_IGTb|N^*Qt=mC}B;J;b~@qWj>LVNIq(ypkd%I1rr4f!c$^5RWu&i z4V9s!apCUKp-)543F2XU$)#lc?S(k4#JZtnQLY$iK}WP_Pqif+BP)B{>lMD7uEkt# z{k-rvKHYwGcHENq}+H+0OU-{iT6! zVn~=96L+Gd}va9AEbr;?*uHfN!Z{S@(}BA4~#h+$%Q@si$-;C4|CI`hn`*9qQGQWGB!Fk0UPP}%(p=MZ6mVR0tV|E zVZM-P7L?{yswncMI5TBxMpk7YkF$Sm%7!SpB*r-Y5wcK3u7GJ+u?-?`lhZ6VG9ZX0 z-@FH5V_dw>9UB#Ftjww0#(FNAcl0{+)3AkMt3zCfKEQJGD7A?RW35uqiY%&;8Zf-WMj4hLC zBRvwlVH`V*3q zCr3wus!o9dsmOpllbwSj#&cYc=;(Rv16E&TA!sBgeiTJ3 z=4whP0g#>Vr2HD&4VFd%Ar|z&H)PO5tbUfCcHtCo57gT>Zk{7ACw(st-=1Xc;#||) z&-<0nWHYZ^$fS#Yp~o27x`@49ccFlD166-lnj6=s{E34-*DwF;f2{wWj=%oL|FM4e zSATXD)5-0X;ObWbsxQnLyqybH)q73VZ5w&FzyAKT-aN~=bj*6ER z`H$GkxUo)Z={!Kyxot+p#T>~2j zA8lvptQ7F}GA0*vTEURGk*GU_@j3qJ$EN}C;|_Kn3rog zLpS`wBPJBP;Bi<#P+H>%{~4UP-OCU|?5su{V=;tFDpP+Z5HSER2cHF+_K5d;tVFo1 z?4ukcN@HSufsKkp(yBIz(T*&3WMdjZi$PP_mx7xD!78s(bZI3-jSb0SL7pivS;R#K z6`fKx4F1mH(p`2yP{3GE`GU^?P7 zP1ZDq?dKNeBK@7eS$vcIM1NUDj3lm+cLB~E_gb-pOr6%?nwNEsf+cK6NTuPF3AcQQk93-SG_uk(5w71`t(<=YE0mfW%?ghH-&^sod&t4*Xy2meXXKjJ*2P7vnpNZ%CGRQuE#fC`^N*@dPmjes{m!V+*fb*tY#Rh#1yA6z#MUH;j=- zyuE*O3(&b^-A$%qaX=}wEZ^HZ=6I}?T%&8!QxzKQjTQ&v2^z9B8<|w18)}3YP=^_!*+zXMZDO#fEy-g7Gl`wP3NFf@0QTYI+>{C7QoM83%(R{vr(|` z!Sue(tV(z_FIO1E&}qL5v?NAKK9+Pd0*CaFg8im4iBP^(b>ESLBRnE^2?Wf z&4h*thDVV}i-$fE$}wJ*SIJ}}5>*&>dLk>zN=57+WJBjjWSodt(ixYHIqB|ty@n}A z=hJ><|HFP3lZbp=@Znt_C&_eztN`60Jq?FEQX-utp|CybdfCOx%7uMx*>8Wo)E{8M z_b#b&^WznHQ=gZM()i(@sr@}q= zoqYcHTKwzy>#GUy=M{(EcCo*Bzft^Ozs#V*rSA7v&0P0;<)6~K3K@OLe^v_bxyLxG zZKpEdJf2clk$?N-D;T%#)%$bjW zBUtndLZgxCp-g)fAJr0V<9iAmKL@gTFy$|fRp7#M@Jc9i6gD;IigkZ}a*aiFu$}lM z`JF`^7u?;rD9M4gG{jrkS<$%`&1x-2?|_MOY+Q)Y;JiC z({v+TG1T7yW2w?lU|V+ZjE-Sh!&)w9Bgb%c&ac^xLzS3NRuW(a^4c=Vj?n#{O={d> z`_r(p3GqX_uGo1nVDf+Dn@CPGzljZ3DaQ4jyk zYfIn*p9AQ^n^!OyxCB@xnF$24ha-l$C>n|3euSWQK-PF_bR2)l1C}EmtHE3eJii@# zOCgEuDC&2bA-N&=EX%>sFNK_JWz*~+1in@5=Mji=R(A4n4U$JCg6Ff^3Q4tTPI@>L zICSA8vpHK^h@${6HI7zg7ehyev4Cgr(<#Xw315;29g%}At#fJB^e@k~q*LgtbFMs2 z{BV5XlI?#>uH%2(;qXWnn3#gUTz%7^9TZ$a8sAjBpuO&zcCfC>J{nfh(nVMFPyJnI zv;r2ku1g_juXfZv;a?%7K6=}-Y#cJ$m3QMGed|AjZMj@NtS0M=UoyAnYux8X#w&A4 zUe`bS{+E(++S_;W|9{oz_-+FHhx>7WZy|ZLz5J^H^g(|Ybl=rep!nPJj#I!|o2I$r zM3PZeev3X)cZN;qh9r=0%Fm)e?%I?t>>s-}m_L7yYa4Q7)7)dlCXF=@t!8mz(noEg z5qG#^ox0lg#bd$%2JnK|re%}QS|T}y&K;ST7p#N}!+OZ@=lDU#rvdN-4?l;-tk@?3 zigsuu)0L#@4n*lf+iCZ?fH#Ln0?Dateq(xdR=G zNCAJ7fh81PV6#q)L2zDKf#5Uwx-P3j3>Hc*+A{79(p*#^I`-yi?P!g+@0{z{Cd<9NTnh{1liX zUIm{GRb>-s_#ADM_~J!3X@Hk2(J35b#XzfGvQ7PrpF||P-Pc~f z22j%$yCOqj8tnC&@=EISJipi0UZA9J8$G{$f9<7Fe^K1`tuFonaQ0cr68pBb0BH|G5N_T%`n`qKd z2ABgm#2xQ+#k_J*1>2khC#O_w%dVSk%R0yV8}G!LCmw6-gJ$~n!ANv^jLq*wdfEo{ z0DbCSkAnpypX?e5m-26#!ie?4v)HAYEr$yiEP7~T{IqIyHGE?{YWq2U#PMkW{J3K~ zDWPA$vQ$7Q_*MmE6wLM*4k~{hb+24AVQ2#<%LFH0Ij2*fDT$E)cSN8CS_rxfzPdJZ zddr?xSfDA!T<@AtpfH`t6nf9KvKr#mG7V93= z(RqVk0*JaM9ASd2@Mxf(+OnbHDxX9z|^&7 z;9M9#tD2e+Jnre&h~D>$quw@6xKor=!{_(iP7H28k>HuUZkc#1yY$!l*VvpfmLGwU zoof|dw!j7tc;RjU=|_KG2zT#vT3#idDhd7a0T+BK{-x4k-+HZPSzWZo;$fgBvhMFC z@F$YV_x=3hL0r)i*XvXG|AFI|Et^02tG`wE7xZl%Tspt6iC5h6mT$3Pu18(c#7hhb zh_|uD^&etJZ$;}%)7+F0W?a6nz4y}(w)uKKH33G0$d59V{q%o2w;xxy+~D=9udfx_ zQAD)jwVNY#1Sa|3OcCTH1Gf>^9quae!#@*P;i)&>N5t|FDZJMavqUB~BhxSKZ;6qP z_HT+8H+U{>hWNhZKtIb6@|#nh{N$}J`<$JhJ83v*Ph*3; zrkKxt+dCe+g0kZZJ1^?gg!rODdH#(JeU2YQ~h?HGSKihGn!SnmP?D;NqybpH{- zc2e$@H$X`v$ih$CNUO1*!Nht`tAl*YbR;ecCQ7_k1%7*LLCFQ9U^`2V z_z_(}^-h04V_hs_$1f99R%j`2>v3A%Nb+nMTb62+U@hQ~Q*0r-En>%!T}?fNl zIE!hWNk_l;xVy;+8%X0(x~TordBUo!@QlXaxzvB5s~$^n!kzplq#L zJ}=nBmOZhw;~oX7nV6}di;cFw-=Oz%2(jg|jm|H4%4py7{qj#g#sB}Cu0$&}B?94G%_~p}sfEtr6{i_BW z3T{JMXXqR$Is}pP8F3ZJbG(RrV)%?P!092AcUNX$7ulywYQ8oFxNccqW!z!7mCX7W zZEWB;KY(nWv(rv0cv`=4KoLMhPBkw}$}@k%$3eqyP4n)2;1>D9xJY-snFt?|Q|_Q+ z#2E9N^)$GfjK66Tagga-bD=?2G}{P=wb(|e_cmMW&0R>np8Onqy~|mqy~n2B@^;*l zT;S0fna#DK=V@E-?Jzz^O^pSMLHXzS3CE`a@Y4=C@0x{?6N3&MIKYkAitTG%DOi6A zq&sO>AV3dr2c`Q&wq7X}IJbXInw_iwdN^l3?iq~swG&w009#dY>$PT3aIT&7nMNk! zkLJJ*F60C9KDV@K2))QpzMa6Uf~1`|CW-q)(CN~~V})d=VgtN=-@D{WlPY;-Kv@|_ zcc?fj6tU@GBdOZ_V&`P>Q3XeIvyp!$$QugB{JAH|l-G*fAVE@jNM!BjHb;X*zTIEgqCH0O4ZgKZN&`_z?4Tv*8${f9kTnj=res^_+& z4o&oU%X@#Lz6a5>%LPUX6I3N}^UBCB%DB{```sK-q4t7~w{09vgYwVmv2A~Ik4=o! zxI=b&r|X7p+P@aK#7FPKU&3W`qGOM;Q$xs}=~Mjw=N*6jPj?f*&*UHWCu1F3^U+uv zyR7yhKb4Mz6$`d+{CO2Iue6G7%-J7b#dp4l(w}{=%4<~^O#samyO{|wAt`KhEskG3 z3bBh`G{SCqaAyQy3fPc_p0DaP~PF#2=nGs%A_|uzHR=t@-(0wtIfAvG}?mE9PV;UBAWKNz;0q>48)K>5)Fi zf9>Pb0Qh0YOM&g`X2AgF99n97Gu0GxeY!nF@ml zuf3CpY=^so5j(aFtVn-qGPeo~tt=)mMGneRPWp1q_!*X!r0NF389W$x0&a7w<_tn0 z<9N>oX+PwZZCP)FC>R~IAL4KF4w~-VdK=Z)u6P)rcN_G<|F$M3vkOg>izgdQWR1}! zS#Ad(fz>iXc)|0hTJ^6@-x`Cg!Pk8%a%7UoX3*%4zwt#Uw=I8KrVC=TukY}jVl#UTs zw$gLQOG>4+&)a?)m|%H^2fbTeS+#5V!?*78<%QloP-UC`f7p8$q-k>8IuxiaSlXO4 zaaUnWT7o6-;>LgV-Q2X6;DWo7IKVj|^Xr+=qf0Z%=>ET|OcDe@5HCJT5~R^dQ8<>8 z(?bTO^0xjoo12c?VN+@oOq4z0n+U5EZP;Pp>V-UDrQgXH!VTuG?U- z>TawrI3bZBc~*%YqGL1D9CiKFBe8ZCKz?T)8S~8fUIc&afbv;ye(R$YY$FN}?(E(C zEvk3*UhtvYVJU3FqxaQ@RZz^DLmyE~4t`LxY{8%z37MYRP4k3{Co@21X!ygD#;>4q z#10UD>J!0WMu@(%z08G(eJpk^D2=;s(POuN!+3_N4Vyvhoi(~!Q!mx*v*$Cs6YR;S zHGMbhMh$wP~5SNkbn zRGtLDmlaW{tQO`aE4)R_#Gjx{b8ojzcffeXD4A0)T*gbpyK1A78(Pe#-1Gk&0Jf`1$!#IQredx=?c)Mxy1oh*~ng*>9Q&^9k`Y< zT6Lk0J;zl{XUU0|Q^klDeCHne5ldo>R^`AHf1Q#F3WEd1^>;X(Hx{qY#?QWpl=3us zJQ#n2$oEcgR+lFSSyvqv=iVY4>WUIvn(!P9OasqMe_v;_&&Hmeh~g`f1(*E2TYvP2 zYQvXZ-9O{+?^b8vZP0FzyenYcF`)BML@QVh8E4WprJJID_U{S)|7~R@0sbFjqf!^e zioL@Jvsy8)NYcS?Y+7uh)?=aPTL{93y6W3ygku7uj0da>a5>;aw&ciurD z^6C^gzX?}7V`ini18>%;pX9+7OJn?MPzq7OHHyz$jcxODrNVRQXPM?4I z;pBfMunyAVNEAT!H&TLKg(y+!>RkHd}DbM0AF5e5{6EzeHj4eyH_cC3td#pRfhtg@(n03@%4S4 zol=vJYBBI5r46TTv=g+;TJhFDKL3AqHu@b|YIau?Y8kH?1VNGYDyME6PrNI*+YP~L zlx?n$U}QUZK={^h-K>f?-Ms^#hlo~Y3)czP2rjSG(6~X-i{(1GJgV?(JWgJNo9t-l zfOE;~!S`qoVrg93-i_%bc-9m8r3GFhIB2@Aw==1v9iJe{IK-?@IMx`D4Do+T+T2Ge zj=c0k&_myFZ(P>*x5@{_2H=vAiJd~M3$Ae{9RgD5wsjW#qti7=sNeXDQ6~Z5&H?f+ zYNfUG*C&BM7ZujAjlg%ySf1ozdbpx@-YEtl?>PZhTmGG3{rdNp|MCCXQ~vGcm;e6% z+TZ-IKbWO1$pGt$=F{X{hwGn{i*DFSe!5-Y`7j0p?pt@WchXTYiHUlBvnZIrr-|57hai^c&37ljHZ4-@QBufG;eq z9A*xU0<@t$ID?*UOgVos>H!mi2S+ukA!x7!!D2fotCIE(ow^N|^i%-%vQf z#jRm!+&vUjj6h)o|B=tUzT^ylPxM3nM#3)Wg#^vVAn797(RSOTjEeQc15fb(?_ECp ztR#S?ZTM_Qzb=2_8(u5|B=zq1(WNA%kBf& z3Ghiwy-0TMaF09GLcG zbR){^)iF^`cuHUNig_{N1~p*)AQdxMl0fG0`KKUT=s17WY5hQB#k>i~(cbr6T*UYu z`=q3i*mmDx2)x11N$1bDQ^z3^o^u6(6Pq;nXb1Xc5&-b=0lQ4+e1L41O*!zYckNIg zG(RTK&U0hn<0(~z56w$fON8$Pw(n2@1}!feJ_T#@X7W2H5_<&7p25Fz0_KgQ$n=om zI({{HEI5DA1JPUE>?vPVo&>;`mT4eDp4yLFtEZl$$naDBwKX z95LIWTDt*~bhx88xGm#(#!eKz8ExP9?B~4wycARDcc@q9`y7L-Mi2};@CC+;+t^q+ zm9`<{v%~JEGeHoCS_&Ke_gJd}@1EFba0iS#o=txoyYC5Ash31l8t7hG9;Pj3lg=<_<73RJ!9YbR7a&xDXcppe!!t|)s1*}GJTR|4S;i; zs9!mTWIabu4zg45-wwjiQ&TR-3Vmc9z>%L14=W$O{_X$zLmqvzOIYjYEDNz!g=j&p~$rEKngq29ny#&UU}(_QHn~2M48E!5b2nBY2iF0>rDl8K<$d zAbmhn(+VTu5=KD{=DWA1t>+YUIgc3vh!KBKSa;FGK>bK?2Rv&lmG5xEDo|q;!^2lJ zor0}VHhuOd)Gc^7l|x>qy!J=M*+?u?-pYnV^Q~bw5TT!VS+J?U&BvRct8N@+kbP70 z39rYhU>@ww#Fh5x>^RZfaONRuVQ#vO@zpsH8y1+0w5z7(NfPEnYrgEnm2X6qJkx)3 z_Xa$9q62TOGZL?G<%`HpfX}Tju5pkI%0ccU+nkalB>Zz1LfJt=X!;{h`L6OL0KU3F zW&UKEMhK9z^?V*U!+{{^JbMpiURJi%0xYp~Q6KMCDN&PqX4hovf*#F!-D7{^e(y~C zLDfs2Yy0`ZfF7WRaJYP^11(x_!aRR(!U-i-NCCrMLV1v zJnpNKcjB0>j&zkTVWyKXk4`h~4W>t+6IRKA(Eh}^rr=+m;ZFozUdDkt^^t!M^)j=* zFT~zKaTs-mT{Q2;U6^m#C)Is||Nq$X$Jz;Sx!J#t-{+2pmj=`j6a>2;nR;~+U?mOm z?gxLRomh3RrthquFy)v5bPPMz6d8*%PB@9kyAi6;0^akCf_u^Qm}mKSRc)G&tBjx} zJ4Ud!R`xUqknQ~0>1hXV$XtKv)kW4rF7>h?0vj=r&w2-5t#L3~ZN^V1_EE7Si~}U6 zch=*At9pvvgp<)TMy8S>Jmj-3@lKjU_J+me{z(!R+_5DAV=a9%qe`*13{IN^xXmx> z`!EjbE41u1Ku+K^k5~qFyL9lnw!ZrvcHH#t942O$`*p07K|9oWdvbpzBa=(a7w*V= zB_D8cUlIvW;b=X-OKx0yD-vrwXs^UUpVeZP$Qz`e^heRh?RC6iFR$Z=&btKYIP1;a z&cR6K;PQ3z9g2q=gr|H-c@h9$R^~K;k{9D@KTIV!yv9>l;q-Ug;7%Nt;?yu{=-`3# zdG&Z2qazJrb@9<1eT{$b9<1K2tY7@t?TzTtiDT2OX8Vp`R<#H0gEPT>F-)dGTbvRG zTJsLx98+=T@Q!?qT?Q1J9XADf8n@Zs3Exv2;q%Fx0i>}CQEi8_c7huRM0Q@E<#mqr ziS`qnT|YLGVt$zPjw8e^9VZ8a=Bz8eX3d`%eev!8-EN;PaPog3=Nlh_>dD^IsLsV< zh;&9i)nr8;&S!Mp(MOGU(0l~1ik_%}e)0~#5P@^z$@RE{C@s>+sj|O?!oQ{nky9`6yIERBs=h!H|{d)yI@8rPBg75 zrsCrb=wEaZD-Oa1ye>V#x{BKuN_-S!`~V>6WF0T#Z09Z4S-bUN9tY9k+Gx>!m%L0y z$|@^VQ`J#pB!RA|V!WWsf(yr-1r@cn>?7&r^4?@DYJPtRD?<9MpI~ORYj+Nj0r@Cd z@S<7Ao&>Vyb<4XLcf;&5vGa4cim=Is%r~*(Z1gqSR&zImH#wd(FoI)M?MA|9W*D(_ z^F3-zA^gmD??hn|RSQ;?xNL+l|5s8I@<_Vv>ViC9%DSQcnm2C3#G3SUKM9$7BEp{X zUFAstd|7{CqY{Vbvxt$yXHurKU5qcMIXN@n0)?E9RtU4c;uGWZE$)79|I_CaZA0%> zBXvQv?#$}@O(G)3-&vR+tOyxzxK46D>jv%}-_iuB-8#^6Qn?!+N2QI|lb3^*lMEek zI~6zv_>9N2w0s%6xm~tU>I{E9L)9PbO>o`ev_XF+K%2tZ zbF=Z);{!dPX;(z__gV#twfgS~w^#B)@LWRlZpWzFd2U1igPYM$@c;W2>;}L}_P$~Y z89;v^jfXhmLlyu*d;U|uqBFP4N42mP0&>hfW!J5AyFqrw*4+xMFwZzKfTJpJ({`uZ z(tiEt{eJ&Squ%n@Tb6-a&pSzAoDN@0p>6v`=4sy<#(}}1A66t|d-k>$ooQS6iryOI z%sZp!FDhWJRxk%S0R`Tx#jqirr|2;)U3Py}Bpt;8HU;@jLbj4bC-Y|<8&S3!k{N3( zWdNFYj-*p;bt3s+A%8U8myBN^QsxlI7i(Q*R0atM<{rtM0&K_GaZ#D@8kf`YjZUm7 z!(gkUKy+ukGA>Dl(+WVdjdVuxfU5V-Id7XWSpeKf1=O2OJ>*!KOH#3UX;z7Re1?B) z0si|*XpXk_jCc&A|=v(lOBWZuCCnVr&fQ|F;Dru%98;2 zwn7F;3?IES(jQ0XKI=+GUiJ3+=u-WdCAZl}DWh%&D>~ePGw%2^zOz%1DreVS+Dr@M zIC(-mo#?bdQ5u3=re{dRuKJHj-&dLi%gyT_lSjo6xUlgB>k-#=nwW zISiIbU}22X0Om4YuL7+ZTEJR#02?NKzcuK~Q}I7xqXNk+;|ZI#$% zMYLY=PKvT$(R}0f6@m9qv?}hg=N@9TE!i{|d&EA0Cbn$_{7!tT5gqnXKb2yfV}%DquP9z;c?P+wSxzA_U_;a?6~XC>pwaIWmYtU zy5Kp)`Uus~U&$gawjO`DKIL~WPXgfE%8fm~UX?*6MX7VM6)G78XQjfv#prehD5Z4a zJaOFv(xf7`$xge_wm`KUtW=JYv^^jj6Ul_<^m(>#oXN;BY_fku68kPqbMfh*)WUXH zlP7~FcC_F`Hb1g|>Wf#DfYY`zOn%c$0L_u?ZGl5}V1$QUOkRKR>$abSYdJ{=;+elQ z2uGFcF|9lWUEVhb7Uh2xszep-2{(fDO|NWuzC+!>cme?azG+;-n$MQw{aN|{hyQI)`Tffu z{~_-Mz!KyY1A7M5eMdlD;#Yy)s_QHRuav6yddCheudl8-K<8#Zvj2**Uxqr_5-#}C zkNF+*=vPFevI$*3NaWepmrRoW?*wR6kXSocNCs(KJCc7(7JFU(RqB67xTPJ7TYz~+RE`C_i{iS4Hb z|3n^5!rEO_b56lGokRlp7?_HnvsqD-oTzKqW%mO+*19v`RQd}rXa~#mJCR?44rAYo z{SBe7WHo3UduaG)#h>yWwZ049u-Qy_ZR;YDvNKRJ`q4bF=*310sqAuw;j?LK=Ig^g=F zUz30T%^;xKMzaC)>eLj4sAuF%kPLw}+NW*)V!!t4b2*)4#0#11$s0CsP@_M236kgb zRHCWGxrKopE2b5nD)B(9WB0Si0(3yA=Jwt0IlwrPDc;6MGVx{*ZRO)y#iZaP`4>Ej zZ&SxPg2puezC%PuR^l5SD{trX?7iNXYK(s%JnmW|MG`5=)F10SI+I_He2z18*){&Zet#|55PMv6DPg*mXqU}}66QaYljW~rkPWpJaz;Z zKyT6F+U)|?@B%2Pyra?H&r`mwJPCj=E4t;W=XvYab{=~B+fZU-?&`KX8w!7gJL=}` zUy$FQqTUos@Y^sfyhF_=I3r{9gHQ5#F(^+^=OONr^k}NItPZi2^2qK z*aWtBoi9tgIJwCzor6QB-S_pgZP$c}GufVOd(u>sZC+_=YBHvpaA(`L?YgsVySL~2 zd;f-Wo$Ktq)@SbpcYh7MmykDn-8Vt)v}NA{GneAvB4x`)PXA@3c2YvBjq>}Ab*~_G z6HZqKF#_>z`HuZT2iCK^GMkx-q!&$mJ6b4A_&cgsrHUoLvX|$PX%+sOP4JkM@MMp) z_IHc8G3j;b{$luogAMa7@=foE`ej9-E7U?pvL!OKh|S>DTK;W7A?$CQM$tfH!p70} z&KD+CV|RsDMrdYMu1b~Tl+ShfN}>-Al2PtQv+V3^xZkvC75nBgun;p`jEfvj@*#|EVw_L$`D9`(z1!KP`ZWe2kJvCbPu9s%eCtW-IO)Wq@(%H8Yh}_ z8vTj34TRRdgrM=>neh1gWLF2W)0knbdL3Tk(Hu6nwIKvYyVA5MGGyJvLLe{=0!aYX ziNj+w2I59FJb0(ZB&`#>)x>UU$}5Gp}*2o^4M}RON&%G0d0Uu`}D((tdLz0Ji2usE`;!V zPWi0>nk2B*hF~e>)Ape^oPT9RytucnE$?LCJ$*%N7dF0RG^6=-B@vjmzt6mSu|>-G zNaTgNe{1b|BN6apm>3IY67{Uk>(sQ6agxboaG1`F1=@4A=_^9%^P4VEb!NbIY8z$q zUb!xT^W<**YvN{#!HQnsU?W7;!COcLG-<|6MGo{fIo_@ZxF3yX=`kYEQ%UnPw}K!G zxN>}9AP^;2Nn;hVlB|EzeXQ!QcO9=e(o*fTgxb#%-o+f(#$R*AaVb;QnZ5W0Z zr!h;NVykVosM|YCCOW~U(^djiX>|$jL*f=f{mrxh%W2*!89%=>7cKdVH34gHc)fKR zm!A~GqwgfxTa4)Q{@3tm#H4+heD%vCrfe(yC!4h26@P!Zjfs;_ zc{Ra(PY(O#kmc2VRq1#DalFFpY3&L zH46FAUJ{NocDEL3-+&sh9))l}u|G8R?uLl;DM%!C0?Tbf4j3Z(F=9qeICWKm5wR8Xd`LUValFH4Rs@A)`&g6XE*$+jH)vh)2J_FF2WKnl zmI$HAAvs%a$xAv3#afpyJsVz5czZ7u##|2C=Clw6FY|dui55a))b{PctKDM|ytFLc zbeOe{eV!Ugsqo__>RVn&4^NJvv=soSHbWoAvL%XPV9m^>DIw$_Y(56MdfiO|9@af+ zJD<)@W%QJ4XP3ozsExE+W%u|BT7 z6>yc)=ixhH+)KwsAJn1;QA$V8H>xO0O%xN^79ANS9nz||iCX-8%RFv?D2Z?ak5q?2 zcWj9sG8ou?_JnbQd&LdcyWL-v)Z__l550vA6sM#0F=iHZziQ3GeCXVjKYj;H<`YfbBYT%|m9hc$gs{9nT0ZxJu=DN~6Lwl47 zC5Gjb_?17x4h^fjl~TsC)g0XCP3FIdYQrP4dZ@y6ibC`RBwicHAee|3C`i8+cCmrE zw*BKTV>Qq>arvod*Yj+&LRu}CFjxs*$z<$9$1HvN0yw~b2lz4hFmfO_+PfRtq5CVI zK5>k!O?P5cFowW;0-}-&rDdNvwLI^0LrE;EYQxp!(8?6U;-NGpMl2)TV~U_;8AWzQ zV&}-B6r-^fI4=Ct#@V{F);Jo(U zq1&a1N`h$ND91bW2kIEc-(DP+r`w- z^K=TGZGm-FeXrN1$^e#7n7=hyhdfFWq}|cx^o)m+Z)P8@QsIpW4JoliZh2rd^kz^qn`>CYH5;ARKwak9 zu81IzV@Ew@E>8Wj66cuebW4Y`Za9y*%{3o_wy66%^aPAEZhh~B*i&Mcz;fjz&py3} z!PfNC?g-R}8l_If=j~P09r{5Y%|BRYjAF5dXE5xoDhMZ2#>W;#ohs2W{`mLn{I7^$ zZqnyo&*Ag$|KS0NgvS?Yhw^6T@HHB?-2FQ?ukfLMkc``s5>O7BBFg^lPca)9QNP7h z#4a1Qz5&si8(w*>_3JfVbirPXCiI*)hyw`b5ygV^Id|Vt0tnPe8FNF%7@oB)W*ogjSK;SZr_0THY}lm1`MLV&T6X0Mi*&+>~rTQsf$yNqCY~<=$xwc zn>Q(Hk+H&EUh(43X(0JS?ZK5br|Wd~<04v1(iCuQj`(UiUr6fFx()WkLg7N;<0W81 zhTB%~g&_Y}XtdU(l#z>~Zoi|=vi|9Z%=u4cbe|V-Sl@r0Gxph4lK49@`VVa;p*oVO z>8UQgJ!m|puUis+N>Y$6MvV3pm=u_>8Ckq#joUhJcu#ZC^_W`9=Njgi!~|u%hql!k zT$;eLb*Y02#f{#Z!1C68Ia8QR(M(U8lJ@ zrVDRObSaUXHv|4`teC&C%No=i%zPW7b6l!B^x|^k1@^p;ulw5F$^dG+4N-(7K{WD4 z{N_cL94}-FWJTZ?V^XH=GVu?}_8@jp{{UD^pfC?IIp)fU`VTmv)#+J59+*KBR>)tv zoz#T=z2qN?wS^idss3sYRP3$vvEPVOAz;DY=|ZPg#u-g?~m=g>vAWf5v_ zQwmGp3}VP~lCvpApJEjD|x?6WAqUVMe}BCQND~MeEl&fC0@BU=y_Q;W#j&;^ltY&KFU4Kz7;nT;48RyxmL~W?MU`?O!5G8VCzpI=F z*tOZ#^CuY?A=6i-wp&6b;D8qn(coe+&pYtF3CAUAiQXZ~_^7+$NLZpJz4|gu-s~Zi;ye?efi*zzuGZmnmPm*OG)tGQk29?oEkENR0Y!*R(w@9uK%fs=*xphhb#i|%>j zz-el18j}UXh3LJq%P?)D`5iBgUzTAG2#j7Hil_^e{Uz2p*~$%6430~t&=%+wuu3b$ zZZt|Bm(bbdK4xVA3X$aEG-6bYHxq_d7YcbrQTyJNizBmc7Nv#^U}na4SbrV`C#L`1 z|MDm(hOi)myq6%jyZoO9-2bgho^Uu54C?nm6gtpmEBy(~_fH*=b`HUc2$nwe%H;)YeO_ZI-|Rfll9UIb;v{3Rth~WVq^#B)8|>{N1(?JHj?2Xi=kJ zT8(AzNu-w^9WwL#0$vEJv1puOgKR6PF%}ak-;!7(&unJrg}hmsIrX~8d{K`#&z~S< z|4_h;=X2W`-=YyQ_g zBr4cm#@vV})_j?G`>Z!DXT3k&IMZLO zncl6t2QIP{awRvNU1ww+@WzCRM+TzNlC`=aINORnV28mQ}h!wmy zvOd&5m-gdzMbde$aBgX^2+NhJ+?Mo7ayiY}Xa1xbbLZ-hUxsW4b|z^h=H*88{Y*$F zG8s(u$w$JeES7@p35OiKGi4khb-B}x& z{s8tEx~?h=f#=2|3QQm7UItKY6IIjkYt}!_=g^+{KB6T+Ay$ukqrVkCVGI+!{hjV2 zfUeuU1+gH7+I1mmhx?}1Uh&Zp*fVB?7rFdYoL?E{b}#$nJ#l*b0x%L*R|nR<%KbnK zf!+_r34oEZbm5IDPNu-+Y$a(_$F~!;s5-RisXHK&<-NoQ1+|5${-qLOJBmkvj2Lor z8zIt!*GEuaG~)1Vrffm+PU)k7rLTvXuMW}{8qogy^|t8DpGDW~-bqm$(iv~@BU+9s zPD$LyKGoE~hzWa$2tXO!V&U52Nr^&_inftVNpI#L!Dw>9x}_B75(y?IaqKgY=SMM3 zt>zjNl=$5+?<;p<_#*un!&_}<<^Bipy_PRf;}))^A|ok{$VLhN+Fk1MNT{=5jR z1v}drIXvk6rhNiRa;|B$KF7)qHs|?kaA|{VO_n{srn53>K$=`lPbTkbv*InXOJ`?G zyLkhNcJZ3;V;W9_!nRv)B)kzUj3|wj1F#^1peR)jsv5bYGaXQrlK7 zj@Bk#E-zEexOT%OU5DS%a*Th~wJOL$1nm|zroJ*P0H4R@OU4n@?dy7O92g_Id0E+- zc;aE>-S>UTl^#R>!)?k&Me=Rj?9aE#toMnVWro5H3Wl^5Jmdr(#i~~$4HB+@*nU{$ zy~&cIn3~|w@$#~RE!v1L27SSn^85Qc@RwVv#_XRu_giv?h({=<@oTaIrS8;*KW+Lu z{Ywl20!jMiQR&i%4IDQit+chX^u^K?&65%FNWyg5z7o)0Yd`${ovxpLD~XEA@Ay;T z&D3^S=CgZU@}diW5OjJ-qU#!>(PzCceJj;!qBccMyOHjwXf!^Hbkig_<*ZcDdd6~% zW}GIjef$y;Pc(~^hSbO#RGJ;0!M_($ouT%5f#&Lcodc(U3M-uk!jdzB!;Hl>PV}!N zEEz^pZvr|j9X-DrrmikOyTNFSH=m~qnrOkMZ7SB8y*%@-f%vtQG|u^}oMbR{QF`P#ZB8Xx_Wa*J)`+d##T?GIAfnc!T{L?G zN+l_}7^mFAL36}@0$wNFCmCWrJU4xNKvm|6Ob(wPkC*AX(K+|sex3gu>0KaBPfFK2 z$p|*eRwt?Aw}rcK9+tx+KOF;EB(pSsHI#*zJ(|7mS2zRjo%?QTs-cPYqb|_x=ehsi z%N#*^d}3>16i2qf9hJc=4cGgyLDq&Nv=(XTKACv(aciUZqkJvMR$+w^1Z;D7JwB0) zh;9k#f~7&Ve?-So+0o`?QF9s0D=|R&kE4Vi;3DP`cg*Ld95}_tfuNMcq4g8nV0hwM zUVKaK-ug-vGuklE&Yu`OmAC{P!?b;}(58L0?@sS3hWe7B52}bz-6kZA7Nx&wO>7nm zS?yZHa>mW!>jd6TEZFqh0mp*$*i6e^*n-2MrV%)>F5b~YzXr%twOe&UGmhGQ^Z@gI z&b<7{-u(lVYkbYPNJbZxl_dn3cW&c>k7s>@nm^Kxg1f~jsv8@FBm(rEKL zl7F>g@?1qbg2UJ3TE%x0r#P}4Dy%`?tH7Wmf?ZMsgAYmB&jRKZfcrBuNjkEiC+ z5|d4ETG?VKDf1#=8a_9#f;HzF{iBO6W%HwQ;fY4X$-Qt>gb~zR|8>J@WVAuDm?H?T z?fTO9<%abF;+^L~a(||d62}4#Lq;_5x4F>3zde5c=kdO-JJD!DF^#7DhJ;dUolh;_ z`Gv%uHgZ+%3He6#vq|~PeEqhQY#UP$IPyjBlY z#(MKL){l*@CMcWvYh6(T{R@^3Igy`c`UJ9_Jp*Z%IW+Tk3JVJ=qs!AE;q8x?{e39| zj2<`D8VHww)+aR?t5*5ajM6u1{atRD<#3k*(`TmUw6n1dsq~WGc#3++X1EOv1lm1t zeO^_40^iWzQn6%RAp=bGR1?UDF?TB}Cw7Vfj>4Ft@I{3vr~tC&m5Pj!uY_@j;ki>} z9TJK+Qay*~ynCc!Nj7&HFQv{R=4hHX*V8mia){8t0BrfjCp`BS`mw4^bk~1BHlId> zg_hsmiAI>Uur{1&A)u7G(~smpmFJPyPf1J$Qm>(r&(tLb$t@MKP)uO)?&0|fB&Y0= z89R^9ADNc^d2gzMFeJ|9e#L-WXRANmVF%KUM@d5>nf_kG1a!-ap;5oo4isX;w3c;- z=GG5j@z0f7FAiIW?tZM-Sq`QR?bCPh2}faVe@gvQphsvU`){T@{P4#H4svBuhmC-_1F$` zS`xqyvAi!rXDlP|3B{<+a^e01YwIo5Iy6s!6;r;#so%aH^jGTW+P<;}%1T696zfYH^eo9#|a}!IPC=7hw;SLF(X@)#yHYAdez#q{%0?iX?YIc z?EG+r;#?LDW{?+d>lvmm^SkG&TuCO;d@T&H{{Ez3som9p3#epz>IguA z{Lah4u3cnq^U!vgOVQC_qe#_HbAZhYe;b+5vdEcq->Tn&`i0mo@E2aSu54ZKz^o;# zRx?elCkvt}^Y3Hs`Qz(e`>XcHTx;0Vm_lOBa?{HW&-jT?%=41RE@-yv^U{*mJS1M? zA?6A*cql(oowuD~91GnY4kD(w()@u%&%ue1KfJ0(E7$UYMReC5x9+bBmjo9kCHP$d z(E2#P%}04g7p!-aa$KGx2)+?$8GrPk1V4Pe9_kSo#6Cj4Q|v`aF+T&$>xAKd~|uOviylS(fs< zIuUy=7hb7R$b~GExiJrc+_)>05gacsZecf*VUSLdIYdjqrAxp9v`o+k6mq!w2VR^n7)b!Bz z5mpgOe1(uo$Yg&Y6&!G4M*S}6j?%eC7NuJ~5l~g!nfxFD@)jNRPMhJL42G-1%~Wzx z0RJP&n~S$~AI6|MbBVW&6(kZq_)Qs$VWzKsMOaK*X4#tFp!B#p91lP|R9EZI|NN+4 zKu<%SnwxFsvH>_$APE=}&2O#cmRIwzL0(Ckk&$25PI=YsmIHp#*&dpE@r)w&DNOhs zBfYIemG=K|GWx8Gus&_&&py(7YO0-@;f8RtN)|I-ixQ39@mRF380`?4Q}uaxz>~-A z`@ez6l==$1>0{CkUJ78fK_}zjM_Q|nvLHxP{IjN}r2f9{b+06H`j_W=KT9=i(f#mQ zIVx*tLz8BN5SVAJn77Zx9&fcLH*E;u=hZkd*fl0}+ri7Mv$W2KnWL`eFRwELsV<_q z;Ttegv_Yi~;oYJQXV>oCRbN?ixkT_>tIC%Ds@;CSyT|$3vEc-Wz;G;(zx)#~1)-qS z^|K8y&?_4_(6ChefmKO_dcRG{&w`=jEhs02wR?4LK$f(3ktKAW-xDy$sFZezwU=Zu zuxdYUXs2FP7RBp{D0gz=JhEoWR$9Kn^odAx4=}8)R;9Q?s-tVcg(*4H@yEROqc7>S zFtAr*oC_1%qS6FH8l0fXpIUl|D~-{y2-jX3qU2BTe6N~AL!nt0{MkIIacl@_-%2JP zJm}r2F21)FlI~k_Iu2f!pGU$G}Fb!*3Bbt$PtEKNHKn!zCJ2RQ6ZTPmv87nk$Tm%CIB*7cB zH2XI8}1>!*e# z^2!zM8h&$G&+gn$lL|D+1z8TB#D)&GPT6J0>gVS%bN>oYvvwe+m{Du}!cl(GS#;S! zrjW@jv>bl%EZ&C6a%tB=yL4>(keLh8hWDL1fsV%{VFJyyXMxA?H%GWNnfvb@T%Q>A z+nfj=Uze(`t|Aak^tB(m6>Dv@%>6C9f8^onb!WL@)=n~GQxIwi!>97YD>5Ekp}jrs zKg+oi9i2AgF+MV4PdOIDO%7!mrwUK3LGOv`;b+*e$3c2XE`zzpIu1vq<8fB&h!3SN zfMka}Z@hd`@CjtB&Xesw)Jv)4d4k(gM+gs2LH@SP0cEYAjkl)ZcvMO-!*Bk+Bzu1o z&l5R$pH|~p5+Z?(X4}w^G!|*vh-9T;hW(8r9@yo^ZyW;w@nZ0^M>?BMCOw{o9-}=t zp>f<~;&Em*Q|_}XNU_fW3nAuj*gMfLK(BCy9PJ%;s~?7J$whQqCmatKlhCf*e+pl9 zc2}TPw%?MZEG-Ey?I9h^&kh1ue!5+-KJmIBo!PcecO8h{fIWhLQ_=RjF*@$bdRikF z4hb#&53ckZWPJ;zB|W2RClKCYEzziN(?-*c6$*)obzY2;qPicMq;AlX9gz$mkMZU} zp|~QXH|Xd^vQuRfQCjPC2!rohAm+4H!zsMjiFXq(*YnrAK*fzAxUPofg8vH7K9Gch z1qNi6$T*M=PkS8JBXYYeMbO1Nr8drJ%Xs-z?)Lr-o!c=qF?N40$>}L&m^%&m0H$UM z%~zudg4_Z2%j4~8^uHPx5Bd;bJHqekdWjH%NCkNS`UzZf`c5yLX!r(s4>c+O&S`Y( zL8y8Cs6|se?n*0?d^w>Mr}!bC)J1qhoaB8oeEO)g{I#sK_u!{zW#y+Fgiq+H_-eIgV+M{E|88Eq{pg+ z?!x$Qndzd>D+_EgioaZDElRgTx06RXDt`?;sl=*boO{ z3kKaOD!Rm-sOvAglCJ&=_xgG(5g773h1jslOs~>9Y2BWv*U6Sg*|bVpJ5*)eW?M(b zRqWuh8I<9nP?VV)e>Vs?b!_W8>0fnT$75v31XDnSns=SUYTbcG>#52AaA91B-TYsH zQNcK~SZdBL&>T*O%*}(Y{AkvyxvP0)<54WkmGPpf;l;ak<|1jiVQ9Or$t0SgE=0Vn zMyzR2K0KB}ogbRA_!lNDw&;&n>Kxn{Lzl9w2VJLVi{DiU@WrK`GJR$08Ow!VgEx7` zXkyV33c6-Fk#ZypjZOexB# ziW=TWwplFzU?j%2ADy9bO>5))^C!z0q=NY?gUGD=uSp?>4EeX) zjcgN>kWkmV+FQa^6Mp6y%pfm04_eIgIp%?v1eksxZ{UE!O?k>H3M{agiCr2*#MhSI^mgC zBfGr+Yv#M?+C*X~Ma_i~uhEW}E&gS&y!=e`5B_H)?1!KmrA~XXyV;+6P>PMm~4rM8lJ^k~GXpDZz z@=rC?(tQ^WeU%2iQy zX@P{ks2I5jQy6CPWqF@d|8U1GH}_tj=*7(9Ew~{qXiqP5yXwz36bj;C3$bq~%KN+O zNt>BM@VCzv*8E&_TN}5HR6z!)@gUnCoxj@iGH87SSXeWQbJsQ#PAbk59Pq_ia0S^XPks~RDmhon2&`LD?q^X5F! zAW{`JK?`}L(H#3a9{axHZQh~)(tiRKa z<#gO@i_p(+)_re|G%&K!BxkWYo}m^G0RF-K9Iy_94n07A4TotQW9X>YZ-UYAFbo0ag?D$STV^LgFCS?3sfRc!{Uh*~LiNI+*7gI{ zP==^W(6Vv8k|VZ9taYvLVo3pFw^4R&1P9!Gn$dmNBnkK-d8`eW^Gl-Vx4eaWv`KJb zEqmBxhiS+5Dmtttv!5#xZPd}@6R)w?$A~6m+iwiHtXe`yCChOvYBzsCyD>QTg`iCR z6jzZM=lnO9|2VXrLRaWW0M{S+0Fxs^)Nv5DXU*Y@tQl=4Ob#ch$yW+IgT>PX!pA15 z|FR?~DuJB|ZpYx#wrlx#d6LmbQ^mZCm-!Lha=fhCPlGofW7f_10Z6rIi%W`UZ)j5k zI=TTDerJavJ-CZxDlJ1N@1~d}3Q4HnnlMipP;uB!^LrJD5FYUC_DhmaXIX>j9WOK3 zFT%SM%nOPT)R0FJej&h1jJcs`UCq}*#O0@O_i7449T|wl6VO(?B+t z&-q^S#{5K*kiy4LCmqcBf0{EZ8?>lYhVoqZkClaSb-rcYNpG^GAX}zP4`+1(j ztuS4-p&r=#=9x5QOe?{BrB^Y+a2(jL&YUg&ZA-Y1Y+^3i)&qpnoU&maF|u;k|KJG0 zFlfpj!0OmNj<7d$0*Ybu3uz}F&)lz>k?m7osc!b6P%AIQt}nto`m+79@@%uQn#U!- z<-%9|m2E=a2rBH&WGNV`ZcmHEG36y_=9}d2bTAOeicBKC1<7lqje8&$7ZDYRA)Cr- z0{wfWwe=zd+e3PhInBaO!zr7bgR$ziI(w6wS2?K1c;1-zNzju_%+1Pio%!KJ{EGRf z&8y^8~!zb z6iQ5p|5`)ggGS@orPZcvpVO}gMTE{K1NqaqqoV^#MD=ez0zaA`FFB}c-d;vcY{zmo zyz10qmey}$=a#q#1TRY6h;~S6Z6_WE)t5|FOz)Jw2nm7YuMmYddbX*2DD*ppP=)OE zkc#AaX}*uIbql_A@s$|ejni4ao3o$Ozfb+wU+AR_FU#M$wH+H7|MY7(UszWLdhBs- zSYD13-BV%cI;{C`hF2ssJfJ+QP2+6IAScvWmcy$o?67~avou@8ukLU?8FPRkrALIK zjnbA3&XmRB8+wvmYAoxB6(i22o-TMx`{hOJVH-JB*%8^bO6ytYkS)3X#GdZ_^&p2s z_8GcwopaQqk;31evXb?fQ8Ty&tR5%3`KflW$!`m7;}k}I<|vsP2Q2>*TaaANWM&F# zhT`ZC{^W5E?&9?oG>dWZQTE0b)EtXky*@^tQ!8MRFOl5VFC8=Y$*=gW(dE9OPAx%B zT4<`xk#Qr4fRaid>*~Kf%pcxI#(&D?tFjoE-70|7IPI{pB763&^-5de5!)h zPLB@2QrhoIJ)K<~C99k|@WO<2YJWhk7|Nd}%_-X&-xiMyn-elVCK_{^mtdZTvDfy5 zzrR-)3L5ECf{Ko9ISFbZzjT^;yPHSrxFW5!jIS-RkJXTOwc#`cB9}S!hHVrxfAo~^ zT{X7fm&6BELXshGyJ)9?K2k5Puz&o|cIj#}Y&H*n1?X5#V8EVfY5y=r|CSB0%v>h> zBm+%o+YF2*k7u)I%8L1|dx%;qJFyH`IpBVHa8^Z$Nd_|ajp8Cda9t8EGa;5V0eH_Wav3NDUHn+4XvFR& z3Siz3iLf&~she4-g`vk&zpjTXa=7`fiJ(6XZ@nMnDE>U=v7)ao6&`u2%gZx^n4*Yz z@9bB59elaPymqDPfn%?P_ps53(`I7xnTzL+rC$N(eZJT|-Jz3qh@MK!Ia@1YvDY!7 z>p6sYb)~NO5@11pj5+iCnxgr)o=KW1D4rlIdhav*$@l01m=fnK7nCpAY%IHhXXn_D z!WXdkeDf_S1e;BQ0u7yahwcmbIuNDYQ(8dbcrLB6K+>z=?s^MFN^KO3$H;!7k9D5T z0HlMt5vg9dk0ji(Jd|Gn?t68QD}BK|N$b;R0`0E%7hnkaZBL~LdCe^flwdgankB8X zuR;vIbeK)d9h{1S`jsh_8cRi@%UpV{w=pb`au?uQM8cdIg0ep;98&D+x9r9K?We$+ z1IELPUBq0G4VRK7dcedWT9Yv;88qH?okNBsfq+Y2z$K+$@oVFzdql{J#Vl$DJUk(Y zk=&689_Ximv-T`aJ0v$7W<38+|9pH?)P6K0%dUoyea$=iuhe1oz;znQO!Y?wsdMB+`l09b4JEb{IU4 z)ty!-ASH!db|txatLFm{7W=@g@eqD|7&T|Wi``Ewo5i=*I4tq2+=_JiD}s>Nr3wDG z{`*H*fxF(YBprqnEY8{)IAopi3GDq-%I5yp0}Pha8CHnZ7harQ?|nquHb`f0$DemX zQNAD#Q8qUxj?_Anb|hgF>jDmxr;8M5>;A~MD;3aKisL^*=Uu>UaGZ7f^2~gfU#1fP zfjsrjQls%DW`4{o`UbYOLp2b-AP*x+t?fSu|97Io)i-SrpumlA+q`?ECY_D~WafQ+ z5;Jc>cPN+}u6vSILqS<>-t}@SSo>ZKmIQr`1XOUfYYIh4{>!UqjPy(yGdkP@2s*-q z%L6$)WU6IjPcbC3z6RMR_E{Fe54c=HZ$xcP7aBBhJ>c`(n~h`?9GDOrdiL1c7MyY0 zIxMpB8wqT(O&Uldv>5Lw&4K+`GDkd(k!-p0eHjVV|1e65DQ~*T`_Rs-2wh=|D?gOT z+_O)IZ({A=tOnPrFjEMSDP|;XdxExeg+3+Ep5G8_-*LUUy;AWuAUuzE18NQ(kZsNm z8CR(P-Bgp55UgE{mg2oR$s@)QWBi|0bC>=c~Fn?WmPosP-Jt;4}$?GQ9S`!r^Gu`)bU(5VgBuWXYWtiq6`k04%qMU!b!JzfVSZbl$w#iLm^@ zkzgCsq%hq^8UK8I=E7i1T1mJse_7_NHT?hyrr8#?qNGa}OD?o-*#B85LSoU%mwX`$C&$5zd7Jdj^SOv*ko zr}bUDNn(PDZ)Eet9wRkg?fPA&Hk`C_+I-T7$OiPq_4?Q|UaW{eNIt6{PMaU>9+w0i z-pN&}Xq5sg)C1^zYcg)2&#gRia)9IKpCw@cnl9-a=n2=vOo4jo8yLHEtbYxbxwI3# zAF1+9oo^qR_Kh@-=J{bCD(Z&+f+ro>%#(m8>~tMIr`ObS7MO)`Iam{<#N zxMM$nrWokWO^Zecdh!@PH~0@C#=EPkU<*q2aZ?}7jo?~E(w}%zKw%^d3R>GZw=$jG zv*$rH(3i5Io$)LNRA+0*@5~lidCZtCpI3kG1czAUcpjN-`As`-+~=B43nM?{>*+a_ z`fUvj$pmlyyZI->MS3rEAv=lZ0RozZz<-YZIJ6(SLz%|aD4d42^& zA4y**HQYr~L%1yrPW&CJ2a4aV+xDwF3SP)ylc4|F?earf7)ToI=pZG{75R@GvoK1tFn7o(f}`ZoG7vNE zyPKshYJraStxw}YMe?vkbwSlGm>oZTVaWpk^IvPEk#w814^dvULHmpCN*tAKAii`@ zqvq5gX;P0gA@kIL?KXhz5a5Z}tkjQCzPz#+Xu|yDKwSGi`!0HRWY0lvo@ZP4>TjZq zZ8%1qxQdBrx?{1>j%1y zE+LB;SMgNZMIY##KA7d_qRgFC6deeD*2{Z&fbp<4JsHJz(q016cuti`&@{U~Nl}x+ zO;w3*l#E4Q@m(f5n)z^Zgv7>Gje)df7pxAaf>hG`y@4dg#d=~msTiT0eJ4Z!AFrc?Kio~!`!gn3GgW-Fn z@Fq2|cWt|JG-eK*|Eic8J3iOJJdg-^rT78CGp3|_DV{#~)a4o+&>IxS7zd|)xzn|i zI79mYd?4;ZSF|z^Q=*)QWzeR?TtuOFDjmiY{dvV$A6+?J zHR-L`7yAvP*_t}JLW?y=CX^DKumVwuCVXjq6z>RcVGDrSDdK5);agFNbn>cqGIozGy;UD4yHE)_gRy+o-3f`LIl+0TH6}`Tbq& z-n9k-d#y^1fYTiO(JQEKo1U_9VFp>fAAU=IS*awcO=?EgAU*7X;kNRAld=HRs?_p? zNoQh~-{iz(-ybzotoa?YKR+B&3?g0OsH*vGDgl{6#L$>OTZgf0mmCxL&jvoP&%5jB zS9Jl0-k*3Cc`@2U5#0zX3aj{dkV#gsmi`DUI$l}&Xzz6fSu}=CF6mB8d?xrog2l9D zGrdm9ZSj(`-gX%E=bw8}z(;sA!^3{F(B7F-&-(++yV7G|H7#T&G>10gdG1+z8&81B zbSE&K+;Ft)8)Q>(vMxBRfo52w?B53vBLvPr8Si-sO3-$jYW`$bKu&>+g@*dR*S^i z32-5;8zp30`4*Z=edrGisYM+Y$c~njPlR~B?vg?kUeEVxE7jUyzw#*F_`@9;KzTU5 zRJH&uE71-iKph{GPtFbe6itUgC2;h933>y(ht=BiN~t^7%a|u4$*X*KgZLzIN7h48 zH%lo=ZZ^+>;eWd4^;#L73*t3PZ-({5y^531`OTQ8edZU<<$Yr+0OP^DTokERPp;4|%7wgaIGLh)R_l3+m>3c&Kzf=C*Owj`@Nepc#tjAOebCLltx@n zxkG%Xl{!)+Yg)4uK-ZUFNs*e)KuoFjg$6MyyvaXSxEnV#A_I1_%tp=*Es zyz26r zeuB|EQbZ1SMxc}2Pn^r31@h@R{{>bt8|!DBPhqpF@zftfnL?3Y7u!2QA9-R0=R4Ro zj9|5ib#U|J?WFN#yyMw|ke&ZLLHznAtQL{)xJ0_`K6y0qb@X~&opy}o#6KwHkkOVi+*elWt9R&l1 zC$)e4arV{kH7^)F_eO3}q8Y^k)iP3+Lrf+XIG;~^Fy#5i<9Caj;0?^D3vkHc<*DNc zFw}kj#QFOhYcTgOpv%Ir=m_6S@!a!^&w~&G2QMUwU!Z%cqdJ*Bn^mal(YoHAjvunp zQ#mtY^s2#j`=7`+a47gJbk>7-%2ULkKgp=ZCX(+gK9e(wVVMK%T1Ci_5c-&Ru-<35 z9UtokUqSn05O0Uv=8F7EWk7cSdsUzekdl4CUGC3AX8K(iq z=GTHp_7F3`3hJTffm2AGR~9gte~fgiM;Qi-)Lb>^n6%Tv(!QcoF?THlduK;F?ganx zV6Kmbd|f4}=5IzjuyHl-aGwB1E_v%fw`HUvvzsXVJG|f^5!Lb>B@9mlkNurKQ&=6cVN6ydQ*<^ z7T(RvDVWA#qyx4Gl^^bdS*Cwa9F{V8mWCLE))noDgIFjQNZTF!Wef8d^PW_{ecB@F zP@xU*J%X;z%+GHP)W1ei0BuGsW8w`nzA(kKQ~2N)Oc)2I*(3Ja=s#bn85HYn7aEQY z*Gpt(W6>{?fMS)4y}gL{U_l=U8IQ>pLK{ek>l}jaUpFqc>w60`AqobP?Z1Rz$qpu; zeW_g*iNuu8NcBb-c2~4OxQ~R~DXD){E4JX|tEDCW(1OI#~y#CGp{sbS4 z{qe6KfL5yRZEct9UAW(=UETcLfbMKgY*}4p>%2^qeJ=xN^?&` zAgk(vtT0s++&%u!u^(o`WhNx+$&I=^Q=}L5{C_N+14Ez>)Ah4$WAkR)o4sweZSxA7 zZQFKjw%f4Tw(WZR-_QFQF3imNojEfpaAi&1VdQ1$bQW?giZ0mE-M={0-tPD)uaZn` zv14m%|MmU7BifBoKY<7)z58=oA6>%nG7Uet`4E7r5OTzL2{zF1a;^ChUj)nEUd=wq zr*2pa;{6j0GAr>MVC0a+**q5rnI+i1<{$NcL)zGaT|stFDUgpI7!Wl14iWvRuBd0T z+0T|cjO95ub!n%@QS5}_0u4$U(R_AfuW#E5PXgGtfPg6A>?Mvgf5t|^bnZ+USN7~L zKYY!4;rmYHxeU+)Y4-}F`s=!B?iC(eMc-d1KCO`Xsvk@7jpPs4D*cde8L%pUazCXB zdA2}ysT(|Y5cxUxnx;!~Ca)j8Wa6AzOks(_i{!xM1^ucM(AP3p(oSJVS67*W*nZ#X0#6 ztC(ls79T5h1^4tag0)`7TaXF{*f3AABLU@9aRaO=y!=d1frq1lprR6f$g!$B-YX6`H+gGYokU@EEn{Ok} zBPkgwfci7=<-K`ZqKnZQ^|vuLj-b5k!mSHUnQGSnt#a?kIk+12z! zQ^cXBmn{5zrHkSw%eG<|;br-udEn^(nPF$j!tNe{rp?F+`o{Y*HofOI1|)m~?L|NG zpt+LiRD8m&W#h;C%3h(mJsf*6?K@iTAW`3tc+?p{uLaRT%#=dY3-l=l(u~7C*19!N6wQwugr@QLq7_oio#NE&@Uf(y0N;B{$QKd zb=w}lh@?g9L`WDt-o-aL)W7#0ZLkXi-+WEIvk`#nZ^3}vLVV(Wq|A5NT9oB5ynt^= zR9)W}YW&AH=cSl^BeyRFe9a#IKU2})m7_IdPoAEO#;PC@T}SFUn0Y;rzh$kk7U&8UJd-f06dET#;H8xtS5X^)@72~ zz!yp~x08yezvAItIcN+l;WAQt)JNGZcO#(lz{>LB6# zz?Pke0$gsn09VvVJs6lR`~mniO#PpX>Cero?>OD+f}~HU{eX|}!6gj#eI~~^)Ji>f1c)v7@jsClBd~yD=h`GD{Ivt(M?;u+ml`VnhH2XN4XYP3 zx_d@*)aJ|*r>i|YLl=sYgZOEog`(Jnjid4c5EMw6o; z6V1-K!Q2P_qhhH1EM~m4_Fu?J`W$v>y@87_=6VGAKDZ9O_ALmJRM)M&T8gv4af{u- z5WEv}Q;OCIxU7?!)zZ?uwh?etnAngBQ%6}&vC+h1p927w_z{J4VHVGz$$ zC|mpD@a~zndbZ!Q%Sq27HyTKEyx8(K3!Bk1!%y-?p903WT6%1tnvR;m8n`xGx?M7e?ysG=V_!guPRsoL|6N4QNZIhD-`)lyD4csr@KN$>~V7?&jkS&pI6Ls3aLQ2ur$;wP%Xg**y6Ky1bx(+dDO-P5S3D?3{ zNF$>9szrp;l(SIX4KCY4*_BAD9}%>;T$1yY>in!YgkA2$N=$qBd-z>PPmQ11eYUh= zp86)EbE9gtNiJO?&}E_>xCRfxsc7gB=MiJ* zIl3W~&n4)r>RsHXbJlUyKS&d)90)bJe100T^w7{b*#PcEH#;qrcR3`JjOY6bJmbwf z94Z&oRp@d|xDYs0v1%mFU>s^EdjWO3cdF&m0bv9lH0*SAdQU_ETCn6HvE+>+33xB* zz(E;({h3tA%2Xrx*&#U|3&%X6&>Rzdd;LVyt-#L{>{R6*QveFKd%H=icIbqJzm5yS zAM1wZUa7}Ituyi>6)FCyw4QRC<@!w>az?&qa z#)F>ttdjGpU4AW5mUFMVKJc4c|9%`4s=KaY^gF^Kt8WGV>=uCERi73HPGcFKB3z<* zoCRQ1E}Ct8MKn~oIH&9j59QpnC;x9fM9-e0f45O{a=Gc(WOcf2Zz;XRM(u$s_vD8h zE%o85r1H(!edDX~pUipbD$3OFKCpZqGD)1G2d+CmOBbRMpq-!~n@-N9V2a1_h(2n2 zE2>u&vjK+NZOa>>m%cwV1@{}Ec(g`sBOWNe4N!vDnBI8Zf3;aqD2Fsv`&RR)0q~*F zCu;1CP`*Db!5%U;V}4Y+>9V+!@;5)#Vte#z{Wf5cHn3OZz`x^KZ4JLQ*h+|BenrDB zf@pEXq&P?EcbJEs1-AI(O*##gj~_*oue`{tUI2la@VSb#pQYf1YM(ZL{FR9VdyVAy%+)bfEO++*mwH}}OPFGWnw&8962hme>1a3NA!KMjnxaE$I)h1oO@>onohLOD9 z(kgQFPHb3 z0R{fl7i=W$q!L(`ChYMc1b2INzh^>hQQ(_68OVflmO?_CnZ-Hs3mCVp-c1A~r-yT@ zJYwORhkP2$%q2Kd_rX^uY5kclqb*kb15F~DviPPUgg?)f$OQv@isB%WHw7H2wDW^E zN-dtz`4)l_!m6x4$u*13eJ2JXHA-`t0Y8YcE6V_4*yQ!OnEC{Ot6M?LZr;|sz6TgPwiLx*L}Y<%c? zPZ6}$r0;&wFvw#F_|r;JO8LaZz&6r!(gUQ&Ad*5> z@*0V?!hY<(r*1J;90}(_u-zjgpA`0p;s4~Hwtpuj=m1W{ZJ|v=dSO+YNUid?e(WaYyYXqXNHm->*muK6U9t6bkMpo6fU^RTj=2aEH&~DB(gS}bo z*KmJ=4-YL z-$U*G$=Yl*9C=)4dH}b|KfZscsF1z+87^D0K2T8DGp>y4m6DHfJ<#CT=XXC(z0qh` zmd|33J?IOMnvQ`-iSEJy(Jv-BEtaf0)y@>zCk2yb#J9c5UAh1BVJe01q}O(Qp9nUr zG+%5s<9kgk-ruNBUh^tAI~=hZ-$l z9*k~gIp?DNmqbdQ?e5AWf10fgBI-naGAAb`?%NXip5lb}=Ks!LoO5Fh`u&*;iD!+P&$|FJ#{KzNTSP_=mXEBN1kon*}% z{YU2R)OY#yirIhlXx})6>_*7!E=zihAyHuy+(@(~h|e_cfiXRk89f+tEyeaQ-PBw0 zW+ujWud3%W?wWTo&kJdyo|(&>`BT>RoR6DB$S>0@KvvNjgE_|DqT#mGCP?B&SB1Md zx|RJD=?<8&Z+fPlF>n1PjLre#sr>Z1tzkYvg%KEu=BlZ`?(Lp57A)|k1i>G~^r%18 zb=fQ$pPY2%=|z{=z%=U8YX-k7u4niYoXt77@Y+CBTs~I@8!T1c!CNBsFA?K`#54=4 z?IZF5d}lr8Sl?tp33 z>Rq?z3a)Q8W8v$z^Hwnc)h8aeABad10BDk4{!T)#*?=%|2;8quFo{T6d~{RR?7DCx(sn=MTtEH^}_Q+xYH5}O4=p+mU#tEHgdrMd0g^4|4aucuy$)IAVgUD zD=xfyucOZ%wbV=5v3(Kl^QV9khH$3};)!hvj@q4V$dD3Wow79|o{ZTsqvUr;R;bl& z1)q(_IX}b9W#kpyJ~S3cz!P1NH}d+t;n?e2Pc1KL4@VZd2pf`eNA^w9|0q`;?8Tc7 zCIzK7Evo`#uGZl5BOq>N0%GrU;7F;6`Q3BpmhU)JyPO34(Mt@GUTY$> zO%Sy8gygflMB#%s^M~v(mqMy{?3z;3@wEs^wIDC&i{vhh17LMC{AZC%EJ~_>oBkbT zk{Xx2Qd+LSb%_$&o&>4GkW*4kUBGUGy>E4&PyZ)(Vqo=_M?STN1M!4(bFE!K>xTxR z+fLNI*&gyhSyfUE1fFWe`MJ9HH5~B!~qKto6AAg^pxgqMPxV#RGpC;Ogqgga!zni=rF$= zE=M@uK$obU^t!oew?hf&->~$2@jY+oBgHpqk~_*>17UcWJx-8JjpKZwpWskQSfV`Y ztM~G&UB2|NHuAx0j&l_h(3cJT(FDni%yNlGjyI?yfZ{Dz*gDPXglqU%qrxsu>Jymp z?cbxd?xoh|_UC5n5xh1OA~>Wb6efrI-N1O%138p2;XnKCk~`npcCMt2*Mgc2+h5=* zV#w|H15-BttuqkCDyYbn+`8uS@sW;)vR%_ghe ze}H5-02@PjPsZO<6rRKX!!nH%GOm_}$JQMGCQh5I0jekyosw))j*6;HZ0@jjohc0zde#|)GvNdF*lvb zmkQtytNPhkdyPy#+M_Lvj6T&}TlVWt>RD(5jC^C(38JmKVlM2R@H*VM-qg?)-HXyN zL#2<<&D)^Sjhg6Te%e=|q#anZHv^4J&);)4mDf?BX=`!4eN?XJR&&?_c>% zecuGR_C-f1raz$2w9|P9n;P#hBXrHQ{4eg7CnC0XbA76b5ctP7bt+1U6c&KjnA`*e z!23?x^v~D>&%pEL@>&-=uSj1VKtj5rCJ=L(4EOz4GP_PxNxhz9Sq7sF(b-O@pm zNw)Q&3d(!2yiYg1E@OROHf-0K;3W=IaCatLLJzLZ#1FuZ`w>~5F@Rm}W{%Z-l6H^P z<77)~b+0~bdR@`1qZI62{0c+oNDwgpxe&(|-T%hb$=EQ}L59w^l)&z(b{P5Sp(aKg zrZ4ayFJR{f-kZ!?XEO8%lFP7~M?c8F#q*55!o9TK6<-$PjHomBNcMJeD1?qZLcUs3 zb*=r}Qe{V;Ij76X)LW;G-Dc#!ItMl`4!#HV2!9?!Ng=gwu7ob-eOJw-Y_1Ydz;6fXk zUxyOnxT?Z*YjST6XHQ`V;{ZrVl-sfPLgU_&)To{F)pQw_mNgtGpoXEb$1A4lNI6)9 zTrDUUEDSEAxVRNq_F&^Qp6HS3@*NSR^q$NJd?vlbSQX9E)31)^J%_<6=HfA8_o%R; zha<1+IR`lf2{QRSxH?@4_Obvq){5exjA%%#c_pqhZm&=m2FqtHa3GVq#nn zqN%Y@hCGdHfyiMsu#2Jp0dNVI%Zl)Ns@iBmi0%k+8^3c zBVyw=8ok382@jVN`tv}HDf|avHUf{aT;6)+QV=%?4?P zO)yDXHI3i<HhEX;HK(7#isZZ*iJ~R{ry{~dRex(d501e2&Ykk>PP4%)t4QD z!sHuVtu#Y#JGp&JkRNJZrsW~=>AgT4aE$H;VeCy=-aIPt%D3bErg&nyXAoJeGM5`Q zWj9pYeA0ghuhL~{Um!(L(Pw6avA;UP4DU)phH*R^Y~XFF-P66R`t#c$w8GFy=Ln^7 z>b`&pJsLKFhQBD7L%acK)qD<50!+Qeha<-?y>@GH|MO-eZRSmZPyKy_r|xAK!14Wq zU{sH2ljBTzsDN;kbAw9t>8-fS@=Ww8LdC}+(vix41T|tjeZ(I`fG)4150U-#pK@{mwAxJ@&5r%Vc{B`4~6MQRY;aZOPh1(ZLAh}j_)gd_l zN3(YuYmR%JiK^i3>+j{9-r%DGKB^}$iQ@5X-``rT;NCYW$Xp+xjNZ*a&I#YX)qm`+ zjRmpXCDOo*BAV5_ejZ25UCAutj#N0_6jEY+#nsxYl28=)`lM3~Is(&ePQ?u0=e;Q_ z%G2MyDHU|^oYFr|Xd80{DZmv7<>uYw=s36L$U#IP%m`37@=$HF>_Bqi^N?D7!!7P0 zQ-!4&zKz>EHd)m&at2zy>#qMDOJ`FTJ(9RNINv98d)Z|OmQ1_clC zIFO?VJrvCQ;yQXMJc>(~;cMxe!c9 zoNgiAm}&T2z0>-cw9fb?Q2Pyf0-Bw#J!W=R!=C7qXrZ|MDi8-GNToe|FQ)TITB*s5STmQ&aMwO!GwrHEa-f{2Xq#SUG{#Fh4_hsJL#@ ziiut}hh9Q%fMu`M#$|_9O^iyKr9hdSI0CBf-L<&Py~!&6-?VGVq4%JY?dO>T$My6A z>#tSu)My|ybRZBKG4(IKd#6S(`g-d)nk_L3vZ1OiZotNu@fz{#5Ysh(>jlR4YV{l+ z=pTP%>16^|%czU3iPQXk3{Z?1Zq|<{2wrIB`dCY3>C&>SWr(s=VkI@CzrXY}2sfNF zQ42ARAmAKT+0qvR`>`hH)y!}}vom|x}} z>r4e%Pk`0!j)6dxE8*gg&Aoz0*42jRcH5M5RES*XxVQbYQ`@_w(qV#n49SUJVF!)? z)zgamSCqz^eqXknTL;GXdA0zskd?81^E=;Fw}ORLW1Uy+7M#p2dbba?QA&Kon%mFh zmbc9mTKuiekHrO@ugE99c1XPH4zOceaB{At3!uTZgqa}mLn?0CSv(sG04G*dK&E|f;L52U=scI8`a6ZycDi3{+CO0Ytt(7_XLN!$ z=dJCZ>x-=`H+)R<^i= z51@-|*ivG5{&c5tEt(HG{vjU~J-zU!gd6Qqs6T57KSqJv!kT?awhz~78M2pd<#J;dWUCxaIJYdhj60l$Q?20zV@YWF_1Y3l z4C{Mj^!6=a60USyc1o?5wnRCGIpbXLmzIlrwy)KrdGI*>k=vY`(+BtB(3{f+Kk#*W z=~KN|VdGcE`txCkIpY3@xAfjy)NM=0KK*CY%`NeXHV8o^bjWANsBA%`gv7@{$8GCW z_yIvmiNDXwEAu0trB$5Wtdkvy+^q_VUr4;C23DrTqtm=#K6lubm09ySN2x&^hx#CVW;M+p(bU=D%^K@%qP1V0OeO#<(oV~nRp6{Nd*EgQCqNZaNyqY}T<*!+^ z?maTu-T&^y=A0QbOy7J}4^>EGNT)9Br&7ttnb~yv94~%-U2r{4jrCrO1A1?bJv#SW z=duY!gC!6f8sg?y-zjsJPJ=8YT{2JMdS!5Z@)r(Dw&%n6W$Lm-c z>=o~uEJ^Jf0>};3lQcYc@yqu@ljF=@5Tfan;%yrX+{s6gcP8jzfWY0-_3bX#;-4!5 zYBei;&c*=4v}na07XT^*L(*+Jd#r_LOESZP7|vL+Qr@0Q(xUEoRHge`9)i$V559B~ zO`*eRteCqD+2KNzj~SC}pFb{c1(Zi46_%rmRA`>kd_gxmxEN_4p?7qCP?bv-K_CbMk)$)B8_i9}U z-ziXFWgLswJK83NY`uT%Z|{DXc<;(_UR|-BoL=L6I6HC$AbC{x(WM(_uTrj9)UJVd z?$ayA@1qaCCCIsbZ8?95i~ zA;;zw5})(h;oceF<-M(nxX?~-SJo~=_K*j0X~J%WonWZ&Z2v-LrPcU~6Lj`@;fkNb z$sJuL>U1{1uIY_0*$#%9`mWOxJ5C`3H?&f*fw9MIV^6~%Z0h27Xj0o-_ z^IV&~tbpeaU`DxIFC##jncrByzBEFa0mHjcUoQj<)R>Xqe%`HeYE)(oI>eM&i?9E% zA5OYcg*34)MK<==SMkvR2+Tgk-~>bQ4&mn5HyuGE+p|!&6T$+`ymi)hbeMTa^`P3` z2;m}h&dqvXJwv}aXPk8X4cdJ&$EjjoFd_9^^|pFkH|ga~>!Y~jY3aAf)KXn}))bcs z_y_@7kN0jU!J}he!#@j^UXwrb{(FEOii=mTOS`YMmr0qC8kfDO&$oZqSH$1-yi707 zv$-|^)gx#&K2W~UCs4iUwnu)2n0faIxXWI$4w`E!Pe5^kK{2O4`MGH*TgVIQ8>OJa z?0|9)e^8vz&C^89?f(1Y>9cxF@D}pP*Ze!vykJsu__lV;=)2fY;QcLgvEJv7jho+f zMDi;7@J}@6%cxy@+6!E0w|foxd(&m(_eO5rhR2R%3nNdx=k5<8$_!jdE-2DJ&6S8` zPc9#uH_6?)+pZwrZ68sz^OF13SD|n)a7sx&_2+4AD?AqYxwwmz-*k^5OmAk;d4QTM zo@>#z;~w*FzdP)dhy7)1tOqkf@1?A)lG)D;Cug0dZvE*6@9|zpseRQMR57fD_a2ec zl9xZ+g5nXpb?3FK_?zt)efn2=_!Sf-wkrq-N0rwEnX?X({+YH$)!F{&yi(*k!H7tp zJ;{T95r1Wf6NBudPuw}iEE|m&7JxNvI3)E6>R4vSVLM4OvBiYE5G&I+@)Zh@Q{gE- z4P=(aYMc7sPY1k4E}A{N{>?#KBg!ZvEXalv8aIZG$h#plZ^km0S(7NBQdkIkIrGLL z9NscNHmK&bx(ffRj&zDQ)zqr(8pJ^EtRir9=|w!%V(aq8nv)T}7bac;us-9-;MUl_JV#Pbb#!xx)kuxAclJts3g49UI`{MDosn?(&)7d zNM{gNCDMojQ7an>E#bF-s7HV3>!j;Ts4^9n>6EzK_mA?!BY+3qCi0mTP+g=Nl{#8> zfP~OJ{G_*gK25RW?dhI(1tIED>jqDKa`CI4!On^eZQjg&DJQs9@p{SYo=6f!piqNCa? zK994Q+gJY>hI>rqpVz*lSLwIk@S8n=pmqYOcZi!UJqIe@A+?rspfycqj&(weTOyx` zi9?sJ6*vb3iN*j9=ri04i&6+@iZ2U4e9Y*9;A@!h#hCwwle zIaa#jzY{0)S&%iamN%_W26`2%&KsX%3qN<{G$mMP_v!VNHb8o?v5rLEY@(;W?;9yK zKO3IAA)nNDhg3y_mm569n74s{aW`K4KH`4hS0zl( ze{`7MX0$oWgt(kEzvjOq=q!L=DmYPw;q1}?<4;#yD1SoV+Cz?YHyxworIX?^*BDB`npy?x>)Ay#=l4~DP!i%VCKOy z^n{7W{m>pEGw;KrYC_2Kr$%^Gg?B%)1^jW+3*ai9j*2&ehFU47xr+hGZ|0#l0k0IE znz!SYk?gE_eG*?E7qaJG=)r;dmb}f$$GLkA118q891h*Sz?Aa_7h9Y z4Fpyws9rEzRZ~Q?*1AGs6P6hv%0ehoWd~}wQHfWaR!e^+H@&2fzft3klp1}=NQ0Az z4Ose1AB8?tbihZj(!4(RC8+sTy2^ah&QEjI3>Wwp?m*})^-_KUirRu4Z&!0RPr-fv z$Tf0FKU=UIkcz#fraT!!NdC;lkz-)v%SPd|vEsfm=R5wG$O&>aIH=<4MqSK;rFh&% zka(!#y2=ST$g8X9HN{I`Txr(2xV{Cx1!Nbxr?2UZUihMo4F~;mXSBUEw0L{$RBD&2 z;k5v4%`(m5)<2lADxn8qaASW35%bwt(&`r2TqSXCG=1ysHxat}#&+WWadkl~9`KiR zC*!t7cEO2`W$y@YWcM(qjle$(i@c8G(YrR0bJecIc2x#ccs2KlzACfuao>rQ8Svy- zpywrFYPzrJmKclv^cx>tRw)LF(m7p#7hImsY%z;r)Gw7HQ%~_T%tvfdtfLW zNNN|wh4I9xU#{0KJeHO59oO2p5!9+?1^vj$Y3!3*w|ObQJ1xrlPM9tK)^wzYG?OH! zc==YOC&1f#$lAYKcW*x?Y&!Jw7|`X$u*c#PTh4IgKR8b$YF|mNA2=b)^2)Z0tvCBk z-VW`QzvkiC^KEYegK;qi^?Yn7Qr!^qF?2ZIt4_lvY;LodmYsX`v( z=x^FfLXbW+cIS_P(c+_(TM;y7CG5RKoe~3dUv6i%QabL`^Ceauks)F6JK(%P#+vPw zDRESU2d>J%jI_N^Q#8v~W?bH;SqNen&J~8@a%hP~V(IA4;gqGt<4dK-S#!&fz06&{ z)1Ng7j9_CifoD^;SRtSnQh8tMNRleOY5aQNp8m%hK1|lu`*Vt0$2pq0(VC3nwrv5)hn$OY^coo(HUw9j zW=FGjM3qwi_clmx1(Ai!HK-B1jpu?NE}dG{nsZ0==hthonw<0b*sTXVwt^I?Sp|Kr zSR!|BRXA4nEBp620s9}0Z^=dYUgh}CkoQj9YqYXzy!yJx7df>2pZz!8+>}~sr}{nX zA$CSE$K?t>4#Nj;x2O+FybRL^(BoO26_XJ5_%J-{vLq*lT>YTNi69UvP?Dt3u|{#G zUP*MQ6MlIOXQVTfK9Rm}2vA2>^xo>pdQQ!iZo{eDe@<3@0(!x)L<4#Yx)R>o?M%{7 zWZbR$6k}#6g@0_9A#rkl^mrBjA=96Y1pii)ZZC_z*gRdgdhnKfWyt;#J~lk>%D!Je zlnk=WshSqUXz&m(munp0kSr29w3mtC1^w@gVKe(%c6=4qWo0K`)Vp=1OM+qBTB^ps zk~OWag8$kBfHnvgvGUPHt1btQLUy~(zg+rI@I1&a7USm{l-0b8GTIG&dcg6d-ER!m zY)ImYS=&k!j72gR&~p4_fAQPtvWuWU2LzC3;KdC5r{sPkEOgS~R%-3vqGQPtm3lfQ zP$Nmn==jw0d8E@S!L!6Y({J(KXO_0uY?*6l+epw^0P*sI%lGd@8C!#ki1Lf??FXq* zoP*omE@a>xG>G>VUa%_$ggA@iz+4!X>M7T z+S^A}sm%#3zopu7Uu!js1BWT9bC1lV)V>0rjWm=xF@`+K?|WdNz*$7R@(fgq2<~ca zK>ZZ@haOfBdjgZ=w{kHOk<}9C;|$`7dZo`kfOO}jSeW4C>EWGi zwCJNvskiF8@()9`2`q%OxZJc(3U`mI{J9hO^q*`h( zZ+~|nvQ(&SN|}c{bVBJswd~oR6|phJbXf3~@!}0ot~@=VgjQxBY?4kYUG6%cv>wVB zVUd1bLLf||PfLCD5>2Lx&L z`~wK-g=$GBdRkBZDF$C%W8Zv5wNUP#zIE@@Z>sqYO+oCa@i0K%It1!xqAn5A6}|Oy zs}I0)EzI$+siF{$7&y&^cm4~?bK6G1eagD8A%U30r11*C1uq(AB=nq4TAi|LPd1vN z2;i{-c^Uie(qbo~Xtor=UU&6@LO(wKEM-(9nCDrxoS ztZjhwjQq^Jq1JBE_Y&gZ^w#P7c|Y;swph#l6O#@lxLK>ZUo)}JQk9Zq1HkCOw)}Os z;DSBEVWg`3wVfsgY%7e%eMTJ;^n6D3f*udXbY|oI5udDU{iKW}4JBwQA zGkUXEvirq<6wR{DSMG}w!@A3ycTo17W6R*d%5xoCXAEp^Fy=bgDeEQ2EIXueL~}T@ zjAz_#NJ#IgYl?(;{nQ090JYP80^J7_=n*={*H|zplpv8IKOP}mBriP~wg%Mihhhk4 zqOBK0m@7885c4(uV(_LJ2=CIwMEF{Vth{z$&Jg@qRJBJ-B3oc62-FKos=q0?ALjk7 zDBuEHA_sVF##i~G(P$1J4iZlYY3h?SpP3Ytg+U=mAr9Dylvb670E6I{*6*rwOGGT> zT+1_hO~+b9b3eF0L(-7!LEPPQCn0+B{Ixh*E%w$njUIUZlL;P^Z{OFtQEI#O1c%)S zk#N9%a{Ud)ZzM)q>!DwVZzJv%YWNqbb7^LWzS=*@I8EbV?!x!I9hMg~6gJ{za(?(@C}8`xx$7e}D;g0mjkwiDKZ zI9o2?BFE+e&Y_WN11p(c9zq9+ zTE?OMAfM2g#o>xKu0@ZC=E07xY{YssiY`YxXy$nev2*!sGNrKgZbEio zK1})Ax~jxVCKsD*cN(!?*L6dk9K`u?W=oknv?4~9L*sb$26G$d(BR4wKYvPUB;RT* zu3-J9NdO^!pgWNxi|o^lSNki`shpU+r_}eSdOPtDXx4Q4aJuT;eN8B8{ar#ZNhPoqLmc~ec8F3EUP8r~{m1G1uDWhXKt;^|^uDg{%x)BW z6EI_H7!U6&Ly1&dcx%>|r~7(Vd6TQp!G$ClB)k4bBQw^l@$=W%-ajWwf(BZk_gBIt z@W;T|uj3{9o}QvAC_w)NqttXv3Yr)T0cOj@b4b|Li)ygpLRUr5&&z`3nXrAHp}4OSW0s7ec}PJ7P+)M#z7;^bZ!QbWM%Y z5Z83<$vHdz*lQC={B2LAUt2*BpSw8}!7%VcO*kQnpGDSuvkX};;jofjWAe;@L4lQW z5Zkz*)vV%DM!`*}CLPQD_`@T|Mqm;}UJt=MY1L#|_(OMc7R{H**3@Wul{&lcJvKw) zCYh1?KOq-RMT&-y2kYYP`rWCq93Q@_H2Q&bl-*3_N&JbRIFn)BDBJ+ihDEgqToR6_ z52L9k9`$}yW@Ud)?8&;atuS|~npv32qL)S&%Q{)ai2^Ec7}HvYMk^v1WW}O8L3V?q z4pBd2rz3E^T4{`Eiif_D;3DN&8H^qv^;(Su|8_v+Q4Kpgnd6sGlebQc%-^sKo#0kW zwU*U#*60(n*5ZeMq{Xi@&B|~hvI}|q>Gid@Hbv%K@5)Kfpo>h_0y&-7n|FNP8{&B? zgOm|nP<)8G!V%|f#@#$W^}nJ3@a`W9n)8AzM*=rM15?^Q2bzswI8QK_D-Et%imsuMTj!l#K>AUgzxWjOyYW=HT>fK z^e%)?LkJjKV6d@X{rN)H1HgpaAXgiv;Ft}LgWmjPP@hNmGmGl$M#p?6gNX^3t-}Ua z7w8Rov$9MkwW^Z_?8T%c4+CE2cawW{L`!E!h#7pr{;PuxY zdV^3=K>9J{Ky2UvD2qsOsG;zo5^y^<4SXGfu6d;*I*gb*OKp&JyatoI)@NbS;%w!@ z4OP1*I68P$3p$e}b9X8(e>dB@y2mnn(KNg-=0TAb+*7lbVJE~D zFIM;iWz2`9KYW)q4IKMVG$nNx10|wFR+bjKHF^Wj;R$vC(5Y`Dj^=~#x7!N;hu;1s z5kfpkdA|Q58qT*hYqK>F0EY;+8{@knu^pM_d?&bf*d<~^MwP1=Dhj;e<3r(q)4%Y{ z)TCW#Vg&KLE6w@Pn%k6QEe35ULxMV%0e=|95jjv25YMzy9bp`v3Ey1diLOiEHVm=v(m( zKrd%6Gi1CC?GGIFe_KZ^7rj`@%^+}``R>@e+LnZ8c?|!M>cY?COvg{`-;#cf)~*zT z{=}HO|BCAZ&s_0z844jJ`S zS+uXDu)F9TT-%KSrQ^BBuwF^*+xA*)0YnX>_Xx_heA=K9io2lWZ{N7wb)3pJnBRW( z<}rJy{ZE`;|AKlSS*xJUlal?WM{cV%2(2EydPSR zzI(YC&E=Pax3b^kM|&QN9%^jBF7}c|v2qV%89Lw^jpG@vX}t%rDvt+x4nTq8p0G6= zki)ZVqX#Ab=h*&1Oo#7oEf;M@2We>a?PCHN%@G<9JKUOHlW`&x^R%pt)2b^}!^-?Y zz9v&9J(H~AQ6f#Sv>-OE6l0aK;tp%79r#1|YKb~0tqi2Z&s3v72p7LBGFCnA_8%OF zj|+nlH+n3MP2Yz3rPkYBblCw)HzZ@s{Pp?lap7Z~Y|Dzx$4mlF@fSL|?#JYs|CI)5 ztgCwjYh~}Id?d&(U-IvZ1M6a41$UhHS~QtgxY@#Gqv7gb;3OtQ7)bwmrAv9$?yTsK zYAf(_bGuoj!G=WmtyJ3K#8$BW^)R$0ALltb@<&DcVynU>yTeVN0Foybnxe1`e96vUsMD21&HxPtQ>xJp~4VlnItv-SH31)#8)c#-Z~ zf|$t-rj`s}i54qA0XF%z7`5qY4Ly2yj8&9t?#8I?e&eKXkkNt%SI zc^{09@x^VwZ4D1XgqDU!*dlnJHbh5EIuHU(cb(s>KKLYR8K3+S;||F7T9b)88xomX zV4f(rT)|s|a9OQrJN-yZznzLXCSYlVoZ-u>p8f?h`@(hu2R}F>gJn1f{vOLNNi(!b1V_Qd~Tcn-(!(>d>@I=f)+9I41v_)4x-RG zNp#O}NrID9{SjN;nW4&8b8!LKxNItTm!L(!yxqx9Py4aPcZw|$BMHbj$4;f*7mo1J zkZpbav4J zd#SEcAk?hzp~1u$&p7_@|9J4nSk4(X*d)fCj28PE_<m4FKSzA`UO6p$&5?IN78Z!IsuzLKZa71j7|lm_8LknQAKW$ZtUYC+Wv zj^Rw}e$)d_A46j$FCcgr(VCk`fbKds@zM$k)394X3%@V~j6TZKr9A5%EKSf; zbL>v3p{^=dGZt5^1XB?oaZ?#2Zm&FNu^}c^+yVc^-vTbvDwd`fvIJuT< z*>2f(E!(#3cdn<;e&6SBxX*p=>w1yRycwPpMMw8bojOHi=v4APJJ9)SY23A?>FI~} zh}wV4fpL&DDvGv_&iRjm9|-AJXZq#AlpVP%t1(J66%P;Fl+`r1^LXlM!85}hya|88 zJ$jG+@NiDTgR>?43ca{BN@OiPsc1siIM5mFadP5arIe-$h+g4TD6;j$A_>7OhsI4E z#Vq%=gl&#k*PH~41+M%ccuvwTt_IjAF3s-uhl7$}=o*&xQDQ3EIJ)vhZX^(MpoP|}^f-5Z1O6i)H~jVB)bA`Q=<&N= zTce!}wQ_75f~eEHYjjWt^@gkc!S2W)v^E|}8kcvl*=*Wb6cA99OF!p0szCJnV^ifD zG>+R8j=Z@qD7fpcrD(r&+}T}q$#xs@YB98mE(<3iaaFv6V}{E! zn`ka&{H8CM8_U{SMiu~@XK!#%tx&qaMouyJ_Zxj=T3GNvT&b>?t${CKD}`N3&!sai zYbKzQA^XwK3{WZGqPX=Ft=M>Fm4!^8th%omZ=;TZSc;hsTO-r_rB+ADfAAtLn5u-@ z1Oz2YSLtx|=-@(F^^fdJc4)eW<+4qo)ZT4I+PZEG>*53mYH(NZu``w;Zp{pMDwwC; z!35jOZ(CTI-#Z;LBfL1^eU9F~`)E1R|32`YVN9M*i3E-H_6KX(ej z9cBY$yV2n)8#Ov{ev&W|sxiJYE^jodQN0I$k(ruN95RdN*7JN@3d3X-Z9&>kC$DOt zr!`>x0hTwHlsZNbEl`wn_ZzB=KlF*;@Txw@ODw58+&=$Im}_3}UE7&i_00!=n@7Fy zBYudXrtxTnohggDb#gWEw&fS`->jo^TP<2ir)~{mfJ-`v=wzD?*m`fF<`mB zK2FiDWmv}%W9)Z8`EXy?GuFA&FvN7|1d#>Vua#H16tMaQJzXt74ohbI1lAf%51osY z`5U%xcQW>fKTb>#HhK+r-`IL?zT%qM+rVLLWv;$^Wh!8U*tysG4@&GwqHSH4%&(`ua=?CC zKDHD4-r4T!z=TGAyP$X8I`h*bX$7+7EcwcQ!4tDb`dtGhWv%jmS*Q{e`-9y3G7?!liQUle~#^up=*={*=B7nJ(smQX7 z$t0e?#==6OOtZ2@&dl8U#|n8P)X&2EthQk1#CDA6&A#tIIsb4vqcu}@_W6TrG~)3# zPX`f5Iq?5ReX@is;DeqnuthHVgZ{^6^qho;8^CDa%(MW$keQTc?XQ9kZ&DoX&IJ>Wf_jT?kV;Q;}{8Y#foZ zwez8>=+1BBsUh1aK4Zn2=RY04MC%sjRv}G&ZnwQ(WGFw{^n}1LSEueetFYXJa*C2? zWEf}`B^tj_EhQGfSz&fOJDOiF-G!{hHQ+IlHGOLuT3nuv2Ql~1k2t8i%E0B*Fk!4p zZ;!jxF5vK0+cWVzFo#pXL>pB%&6TR$?k2{!wvn~)k-7B;8l&n99JSGn(T}}S5QBuC zyGJSiey#AN04U?i%pVgO|EK2CK;?nt?=iD2=H5MDm5|+=R6)$!;|w}I8;muwq&7|w zC0WBdttm3LfP=cAk((gDvedBF@5Y3a`k8Y8PFI*{S|!5vI+)dD&jgXmx#g;~r3-VT81eVFj5Ese~mRgUsuEPB( z##s1yi14vM%T0|9U~2T9D%*w69Ags^rO(bOVF+yW`sNM^rl!lFW~FAjWc+wdYG0HOn=@lwbr`l8i6P>ZhEurQB-P#$dxp)+_~# z=XfP-W)qH+z1jMH(j@wa)Rxgx$JAPLtlrD#j~{6YBW2ev9)jyMs!_EC!E1BYS5>!T zC-t(>4rYgJX4d1KxD>hQUBHU*S^A^49WIpe7SdD(EK1tgOMVJYdgo1fl@)e+^du|X zW)so9FKo{m6HYTyK6mR0;dQ$Kmn13Kl!Snp;>gm%!&4=FjOoNzuIcs5+Os?XE$Ip? z_;Bo-rqKS5HcA+OGTGzJW5@VO+Jmf+247-K5_%ctsoCFoT~7ex=p`6 z8=@tsgN2p~dgo5BHzP-?rVCu*#rgmQF)A%%Y#x)zX5;g_IGefNoEsFYgmx~7?=g^= zn^6`?Fp^b{6;`lSyS>ChsvGo*_C7qT&BrX`9-)Gtt>o9$W4^%rYTUs^{(>Ym9e&{Z z&3a&fYOJA|J7NhqB-VJ4m%1}1jfj0kHtIE|%*V47WVALU23f9J)vr-7wANL&*5fIe z2y>(`Aa1v2SnP(Zc$k&K7MM}`p~%ZziKT&ah{x6%K^5;vEq~U~faDu6ga%!~g~n*%VOe~pEnj+4Y-xbzTdeqG z{~Hs91mb{txy|~lI6#>66Di*V&Ba&mBx!<8&|gqUND@ufr;PhJ%g$-|0YIl9iEQZWpxCxncBU7?R(=!(abc+-czK zEW&7gLW#Fsm>M9rWZaD`4w8`!{X z<@z|+h&CJFBl}`W=D`l|+%P!JbkJNqzgZh+dsBDJS2gnpxDN0_JS;h)wkxOqRp8?U zyvTyf`&4WfKaHkZf}&5+p)-xN27l<($l*0_2m7HYBB!C;U>aVWs)G&DQ>18=W=^bg zuGq;C$_wn{^*34(yRP#0gd^NNwj?= z9(<65J=0DPlgHnB`NG^Q1GP(LWh}UxFk5rpEasbCmWFh3l8~( zMPEMRHKRZ+m_#9DZ^Yf_mklE5Q-9UDBVXiHkxjhN%QX95Uf2)?TRDfQ=|`6xdh7M7 zgQr0L_wRf~xL@nU*eIKYB-i!XD3pJi|IkOl)d4&*-v9g4t5gto5djEXMTk$hA$g?K zU{Ov-aa~)UihZ;^E(aZM6}y0`AExuPq{o*|7f9GigIkLmU&88#B#^JX-O61x=>_dz z5V~4x7I}M%>P)oKTvf`h75mM;BH&9upwc+u%RY8ReqO#W+YDdG5b z>Gfq#r3T;?|HRl%I|)SO)Zc!{0{O}G`{6rA(sa=?_Y;I#$t8a!{YmZ$GRpbE2KCur zLbwP$0~?IKh_c|cuZ8-6<&#Mo=8fMj6ty7)6{+{i;lXelq}RN2RGukPd|6_o|3URy zznrudcovHU6ZXDAi7qGCC!FC+J@3QfH<&Jh-pyguT{g8%ZahHkHE(&26^{rX;CW>_ zWjSqdYZjn5UBDg{X@DkF#NU&+A5USnzLqy@1lJQ^|?AdvDUs{Y^YFR6?6yq`Z%~4MJbL>4z+2n|0Ax;gJ z&sxSPn)PltuzbI}n3qCnjT!G@02eqITw8 zSRR5#Ny?7R%?bCgm({{e7tCclt-7@OBjs9Vz5zIEBmRX$9f}a2rG9=}2Z-0PeRHOTM9tp_SzihU>)xk9bM9`GGYbyO%S{lPB|=0!Td2K)o>i59{44YZ`HxK@5FN+r;53-P?$A(t2lUBLx(+em!Y5GP zpJRJ@ZO2yC4#C3|{2)Bteo~5;9XrXcg`YgH++}Tn%ro%7*rAs9go0En!P}ElQ zn6D#elE0-A2w9FKtH-!9r~$;L=Uo*Mf#)!`SImA zOBa}Z@lHCkfxrdCWF}mG#1St>Uz9??vGh$6*kqWZ;R(__pr1BXXoRKsP0Ov1s8XwU zE6pPvGVMbd!O{$F&?3htckP4i(%vCgs$QW;;ueYWay@Sdn9C9e*Mt}$E3FMn5iLT} zf{yQ>k}2?^=-c#MP*VA2`a|zM;M57srSMlmQO1#`FL{9f7<;X^>1#)5@LlG330z^{ zQm+{3AlWt*>gNMFI^p;)f&CrnBQ^Evm*$ zXv&T!gQa={J=+^+6?s*S1tXGdur?aOVl%yVF%f(Xok1dx>PfjPRy?|*gagaQ$bq-O zayeYDGJsrK)%z>YyB<$&9qX()Jp~b$FJ#DGk*@LJSAqG<=6c*{>gv8}5_GEUYr$kq zbddk4D`pw@Szet?KWe&_59~W~ZyxMdS%!|WujTS5AsmXG^3MZARb~he7B#qXvJ_Y2 z!~LE%8-=6g}xfr?uNuXMc|$v;08X7M{q zWx-M}AasrfJ|&(j-}7zfB7N1_9Nyp-_1pj4j>J8VEn<%7{rNc2~*EGR~4$M(rAev zBL$!AKQEaWaG7#sdnd5kIB~ZQd312)Rb#*5{A`8a`jXw8gS4EyyE^_erj>sVaCg9~ z?99`Xp>US4vCa`%cdXX}1x~fLXy5D5HAPhTp1oNK#LckMcl91CMSUL-Upr-6r97+p zJT}h$h}0lM@tiwBMptNFrmAx>A5#gspsYFVJ)Q_ayGpeE??IM9Tu-Z5RqI-^w*5^@ zqdQ#THHy1qz~k24jF1kI9C{ASYT}QWS;Wr!UVq~Ts{edyYB}06jbN`2&(&!d zoFkK{p}f1e$4vZzZbBivSSD0hgF?*Nw~DQ9qSkZI6<>5tG;Nk~KDcZE-on>t!itGI zbu|e-(WMx=jmdNv#n z_a9jZIc86=;_LypqhyVkIIWJ5*Y>>+BS0tPfs60P>s8UD!iGDACiRxGnh#50vq@fj zEx>Otc4)`NYSWXx?>qru2xVh=zPZ-&D%w%MAW&%YJgEQWbfYM}ZLGmJrt8`&aJ*>p zVTFm)K>X9v*oBLNMYycmII0ovH)$8?n)EjQ)_WWoKV*WqPmGV&m^<{aABK)lerAy@ z9MdJzyWNCtiWq)d+tQ0&8%}S$8Ysj&6$9*=yt6Ta}*D5Q)p@*iv1A(wN3!gsz+OZm- zy%dBCckI4T{^XWEZTl!U@-cZgh!ly1{GF8SE-CfP=lyLB?e-{aOF~J$8!ANhouud( zT-~dWO=~a2rLqO!j!$6EGytR5P4W~6oBYA#KRlV5rh$AuvBfrDm)`{vxcJK05$+x$W1u6$z(6s)IA`N=ZY7c zDevaL1aa})w8D)}fU~m(_H1zxLszvSXxeEitXa(X(VKNzb(*Fp(D`9fPW%|VJ2l6N zw=dow6uwKog~)GlLWe0o`6Uo--IrjwA77R?Re<)(SPXr7fw( zM2?vexJm!>lL-aW2^qw~Tt-X$h2|csO?yYHc2qT%3hUGvQ<_x*9MIXgS$xm9*DeVq zaE69?xt6Y5d9a;p4~{fwv;wA6$GPILHwe<+-oyUogk>G$c7UCQfV5eebOARk9nnykgSP_0AGlmp zEAOndyemSMf1(!fc5%wy`dE8iB^aRwevSORlh7!M-B+IFw~6FpwQfs09d~I%=tydf zkFazRoaA~U4D(Jcy(G~6JZ86xvy|StxL~zbx@{MDp+)+){xp7EP1AE5z%?aZzbK!t z!Jd8k^Gu4oVexyz+4*txUKa~^2(_n_M&UHsxMu(FG|kPaH-88%5oW=4EW#ux@XU5G zrS2>{)zdmCn^bUa5myvid88>E3DB!oZ8viX32&8E{8`nwMFJmrdfrNb9Rhf~MI&9v z1s~E;$NSKTDouW>>liMCwiJcs$iWDXE;4D+&H4*X=DkC8gEwF*f`DIebK_{ll>w+L z(M?^?qABC=a#0L|2kjM=r`^Ow&XrKB_lLDv7@H6zJ{K<`&->*axEi_CkA&|ru;ZLN zQ{~VnWcJZ7CcALCp(u9=b5V_`Pb!T6+*lum$%2=c5MW~k+~&OZ(fs{wO@yKgS}4RI zf!nBnHibfuwxI(^B3kUsSZUv*nUM8`Gr?I;1gineX{QZ9h*?ZOhmzSN3TvhcPyC zPGb2`Qm@zIQ_3p~Q&jQm7d3rf%oy84jhwgINvp?-4ZsJMkQOCM?9Ef)vNxNa%Mc0E&HPfc?v~oE4Qf}ea>FR*YujLL$4y~nBkS+*#;T*u zLy%8{+u0$K`*#N-XZ9@w{*L*J1}g0%P%&SefR;75N&OPhHvH6pkO+hk?Mt0>?30BZ#C zcc<=Ys>@ohLY1zd>}+4!DUF!6=p=^DrnWa8|MKYUzyJ|#au@- zb$@6Z@jGH{nOW3t%${EcOpaTv_;I)CylVvq&J0on*?Z6N`j6kDVvWq5ODUHH>tJs; zT0Fh6ll5C=Pzc;D+#|*XgWT6pr0nk>a!qlwO>djKuD~u>5>2uKU9L$1$Zto#6Lkzk z%x{;nPd_;YIJ3?(jheBRPO$H`Tcc&6wus)4&vf>o9kGK#aFuR4ChAAvZQC-(-_e=+ z*)D21CmWwiailSRHY5C`C8WIIkesqgv`g7f>OOdgpt%^wu2#AD^!@(^pEzyP4!Z~xHlPWPAG^R!mX}# z9jB?UDBPO+`QMR+OjfTIIBpPS?WEmwmi=Z6)1o-({mo_u^cZ8(SIuAx21Ajprm&CN zI-DwjL>s2`A{62?J2@zn@A&s}JC?(|(vir==La9j9t(q{80gZfRe) zw9D8&R{VE>b+>99P>DGU*WZ5i_^oDXiCQIDOpulbM>_b=WECrb@fR`Z`2CuHy%Of- z^f{}{4+luH-{1(a)2_&#k3Pyi-2Vz!VEJ7IV=Hep%o z`xZUc-2{VV(DF7&r*Da4nBV%kE1C7?QO)It$j*dM_pD%~@kiF=C;q@WW_sdf^Hqd zk~^+Z9~qJkvWY~@1ntfIg8qju3+jL-px(Z|euk^d?Dj>4Ogr%N?W)N5Qa(z)z4MEf zYwUg6d4SR9rHB!M?r8AV`@ocXwYfxv2Fw3&1)MRwczWw|hJ87T7D6Jol&58{3Arag zq3L*-aAn8oh>(KrJ5Z0&L&JCQ2nRlfqG^MzI~XKtO^;!(%&=^w*@rjdZeA?u#YD!y&p6D5n2evV_9^puk^jwM>sv068!r2%3*{I z{vDpzL9WB-dG&OgSs>p7rE_Y@W=b0n(TiEK+nBMMgZ4Sq2@|mRLKWtr$7IWg*4sB^ zd|e@YBc9#((P#4?iPXTVUfPAOL%67Qn=KFVT?qzUeF0oZ%?4fi#&ESe9Cp79XJ0@Q^I|&ShGYQIrlE8PI;7->A?-5l}1XuE3Q%HH9w24dMJEFhH5rh2zjV zPzP9(zx7zrkx~Fi^43+?|A5-T{5%C5& z-cQ31immk_yw2KZ8annRsUZxv$oT%Ex2(a%U&RAmhihYOfWcB!(F-joK2u~S6oN%C zm?&HYnyATK;5)1;^0LSPh}P1Yp&@aHwg$I5 zA&(`GVh~tE=jkBgBTyhM%pA5<5-DUF3A!VeR934gN=_#~#%)T)d`mOJVyKk=j%^zg zW-1`Cq?U|7w$G$oVx3ozZl#MCwA3Mqnm)^wr(o2S?eC+B;aqPgIqqN}qFyO5E}-`} zn&qpJF^E96w%V%{C>`T8QM@Mq0al@9W&2q8-z_e)5=u2UnwmL>cTx&ELeA%hHJ;P$ zJSV+YcG+V_JVYy_n`2L%H4U83O(AAiQOdIl3NV2d@e*Il1U=NJQ!AG+%uLeIWLe|) z6>s-wFTZ_gk2a%$BGD2oB;Nx zEgL<{pVWe|knb*)gBm)N$Sc*m4+4Z3p2IuX--sMCVHYarYK_)eCbA0VwmuJ#3;QMSCXMiB{t{P#veA|PVYTLp$T zT~{B`)N+~0E(mKX2R@yd4vcI8ejgrV_F{$79T=etB8TSajEMkqu`ZOSDXED~;Ur4m zx_isx&iZX_;W|PgLjnq@zYLVFK;7|lkNJD!n*$E{k^xb1Y)qC+gEb-hw{tpAMC>bW zt|Ny_YQ4g}lT3enHsyO$)>Pu(U5<6cbOV1g-n|r_{%tAzd$W?A?+aO^fW6NMka*)+ z-U7fO94KtjZ%|Yb2ydY!V2V&0S3c;;p~;UUNE$?Fpe{`vYQ9z`d<=}&Vlq7TSFMG8k*C8U~3{6*$kZcT}* zbNIViRq$YdYVxiw(J$tvX*F`Gn{bb5$v2}kz+0aAS`9U5g7tNehrWt;FI;r`WH>YO z*tA^y3tOVi_b!{GC}v=vl-$%s9#77z=lT@-N&~#S4Ozw)7C)~eH*<^j-V5bM5n~+~ zfiZ_Q|H-4>=EuF{twq43R6@Ejf|s&OW+r9o5y;~A#OFEE_#Zy(+{cDYm|W}z?A|(4 zT8T%fRnRIk!sN^ss`|FB?040cWf4r|DOl15ZxgUN4QI$40XV;By4+w@84~s4YWOm1s99JQsb?gPDy2f3z`J76!rq)+jGB!MbM2|qz4{WW8jbq@v ziIpqf00yjmLDf>PXWe5cV2O&|CWL=MVr-w>?EL09AJX$P%)O8uo-grtTqsgpKfk`s zPtSw9$LO`FfNu)*&M&Y?5E|T7lK%oIpcF~EKI!V_pO3@#vF7@w^TqS!E&9Dq`Own- z3ks~#Iit7x*}b0Z#JY#gyNEBZu;$o?Fqjp2_Dm#{uX5|WOXaIq4$ei0FGl9D$UOLE zKQjWs90w%fmme>uWdRw;ilr|jRs=RcOdk1P&SxO|@=8SJh5?9|W*oQ=b(xoUSK9=m zZBs+!sy+Ca<eTh|wpDc{)~TNr&s!k~KOl zOAUZuW~xOZFAna=eX3qm~c}pJAnq0Ai||TZX=)n zsW$uWA-0Sun}n_|pBXCDORxe0TYFE=ToxJxvp}DTi4i=knKwgC`Qa`i)nMVA^h@Wt ze%MNZ3&eIfS2@{yiuBr7p}n&~YVsOO0bpu`_A`0dC3``W)*pnEF5qYI zMxG|9CVIJMpm=FVnypcEKqkpJ-_L1;RL)fw86OeK6{%0HCgjoz@uvc9QnKn$4R0l_ zTcZCGqKNonDE21}uT`e%h;NO|R0>lv&(%vmB@nyk&J=5pypTkeAn4)1czqoOxW{Ro zlE2SlP~X~**aruv8~z$9Nl14e`@)D1 z`$`nNEak%bMaKgP(`QvyKgtEL<>sR%FhqwEi0C*Vcf@rJWi`=?Bhsv!#vaZjo+(6S z&JIcb6jjHZ&g!y(X-r8f*#-(`?CRyD=BbW`Ez3LXGO z9lqe${UC)aN)Q0iZRmSqKRIbId~!D-ymK6eoa}d1_}U5lhZchztYIH^6g2&ue?t>5 z6HxS4nsxLsIDry6(%Yx>6-g@P9+=ph!iI%jv9!xYAC6H2-jQXJV$FrYrZvC=hAs3@ zNr&x?Re~o2P>hUS4cPB$kOhPzDCBJB*;+@e!q*HR%6-QH%(;2rO>k+{SX}P3dpc3 z?FTO7Ia4G>kqmUM9o5tLC%*Qou@Bxq5|*xsWrIF>iuNP+E9UkdB9^V4Ng%v!-&d&+ z8P$G0*wqaj5K`g(0I$Bg_8y0*ct};sr--;du|hNW zg9o5M!%IcMS9+Wf84z1C0eIb>i*c-n=ivu7PM_L+EG|pD2#1UnPh4 zhoaH~!|9MTd5JwiWEV8JU!&&i<*ORNK|K4;XRmNJoFvw%$)VX$%2V}aRV!;X0jwxR z(Hb!OF&qP*u1jxlcN2zw&G)!YNw8SowLR^*faCqX1eM7x%Kz1F1X#mtr*W(t8N7D7 z`Zl>-o!gS-TMrCIGe!x}B0WKXTLmQI2{%Wn+;(eUsz{2tRHQ_(Z zSi|e_cAq7Z0SVx>&(O>*;-+s%+WV73|7Yt+q=#B5eqmv)U^RO;wgr}QEQ80q!bogN zWgCo$E8;KKg616BZ96~Nz3qbEOnjs*EYs{^=~9GUYVP*28@~*p<&Kyk3B9_ZH2(1S zHpFE2F}t4HFK{fI(|j6Y&fX+}Z$=;Z&ev=&YRRBqC((c}4>}=Sfw!=PoCloJgEsTz z=Xc`XNlGK6sVb^~{Y0Jb$hM{}P>x0qZynxaZmeMW0hvsgprL1NbUVAe8vxH+YGYSy zX;Q8924UNbPviB)GakvD$}BU7UwUMkruMj_^z9$Rt2*+?>SxN~%d4H_D9;GPp3{3j z0p+jXf5J^tg&eUHAAdVE9EXbU>ecgvpZ%APIr9}W-0KK%}p-&dyu=?ba2Q^;)yH8m$3 zRTEo7dPY9uq|sZH_xo%s2rCm?0Yw{?;km1t>R2`ATq;bu?z50Bh`LE}ufb>X3Qw4V z8BSslhm}_3RRV_!BNQ1qgC3D3y%Zo&^Y&MvnRJXS?oaarS46$kPJUjZ@;9g+9*3ZR z_MAZ3T<3u>G_IJH<|CbtABrV_g)-vm;nPR!wJaqJY3~g=3~-!C9LFk6%x#g}Tf6u$ zPqppYwx@fX4nu)ST#l+~3G;Q5_R=@9c3y2^I^leXF=!!RC&-oS=TYE*cz|71*K;dd zgVowNUU$>x=8tdBag)Q=nRAT6(MdFPZe>H2^T;XgegCj(i@;5uTRJIkV5}Iu0T4Yhi^LF`iyW;28P9RGs)cG@;2#jF>(Dj$WjJ|rz&qHcfZzFLX5-)w@y^raw%=e$Owpvp#dWpIYlz_DA+nzjRE$)uY zkq+tbxka-sEN8~00s>E{FTuIYS5iZe>Ji%>4cSV39)y@0Bz_T53}D z%L@eI?8NN+JDn@-5rJ6?jV};#S+&>qmi3e(62$ygZ`G1AZ%=mu_@d>$mvWjK#GQYi zzwLp8N%V&}2)ajg8LSc!3YpImHYw5*VMB3SWWG&bOaN~Gr@;e=_J*Mz8sD)l!OcC9 z20}QX(_LG3kE zHx!Hz<3->l>h1JQ!0I&Kme7#T@K*&Vr$}PK-SgtA2_{Dq@k8oGTASkJn`1AynaDG+bD ziH?w_pJ*@;Y|1)Bp_x^pKf2UN;Y%j6Ek316#R9~dcz;>yVS~UY_Y9ZPn1e*`q_+LN z%{P8Xazdy`yU*mX)_*z09M@5Fq~|jfjzC(mG%alZ-9lg1pftw4 z$r96Z&%EVUxa&C;QOC~~;?sPrE1gCQC*xgVX9H1607jA(9RoE%#{>!1k8li`-}ssc zWeQw|oTM_Fc7`DF;UG3xd;yJLnu0bX0!YMKEYXs`LzEuS+^tMu6M)e#lwfM|W&lK? zwUPvI2}2xB*Lwje{ggGL(f?nF1$?;fU$P$7I^UF`WfUmeR$;8jS}n{~+}@Eka$i5X z<<)v6mKj0}##K0*==DYEYnCkPfeyRGB{kS~2FK$PSX8B~cORNR+FCG8J?>WG9rv=Z zD?8o3#*Le@zKIJ*wCK39u(r5?!Nyi^FF!TF7deSbA(||?B4Ebf1*aaYO<=25%8`3o ztfWF=aKXkf{AV;kag~#vTi7tSp_Tmt1;(_hJ$hHT@g-KeCS%x~(us$<9rNmxkc)oEf2j}-~aDBWtTZ0wEY32+lzIimD0bJp#(kbq#a zXjnz$+vF;o5$<2DjKzk>OJ_fnSptsmATBPdzAhT3G`@1( z!!|mY;yA^A5J{{t)hBu;8a6JN@o;_+*tbaD$j@VPQ7$^$7wC>3{od)8UX>iEbQhL| zaEefG+L4r-)IK_4Lc!DW{(X;XXddZZt$CZlbNrLIkXD1qkEHMB3VEeDLR&q37UMr`Fwp2MC- zoD`JMD5)9Zi-3ye^vnmD%q*bpIeA_f{Hssdz0V9Z~8iS3_MlXIt!{WlltlQvDf4d z*P(t>j{eH>sX5jlMaU$=AoFg?=atV2=85QGPt~7a#J1aaK4xLYt5uPgF(7TBQ|W z;1FGBe_l_X-kg20)`XEvzLPkDEm?Oc3MC;vIDS2KPY(rOg_g}B0bon;E))dI}) zTQy`8vSqv=^A8BD_=0)@co8EkT~Lyd?@A^1(!<#evX-JpqyF|9)2^l~EmJI+Ice4@ zMV%yecL`jUS*g`ll>m1nj9RpV>#&)-jTRNgaBcu|7Uy%oWfYRIreB=kd77N6D#2Mf z<@2%#I=yG#ne;g4M>e=Mj<>+k8PH+1K+nm2YzANcOsdxIS$D8My`y6j7Z{74+Ii^6 z&T}!*x!1_}@n0W7NLWT_A4R`3(DF$9R5TgD)2-YmH+0x2O219DOA0q#ORESbZLKIf zEy@nPr`0}e`YC41o}nQhc9+B~)YWg_{iqZ0Vb!+#L^l%*^EVOKl9Y$Tn4m zJARd^z@j78qjs;H%df7gY)2yFnU&1TKgRPQYKV(+hryWaeEr*RpAg=%;aD|QJ9aZub^f_sSR56;ExXySVQrvXU> z0{w}F;(If@5^6*bySkpJO_d(_SaA%Zla*hV9u9?dO#Bi^*P9vxsoe-3f@&eMFNA52 z^GCHyqsVGNN=UdjFy5Pz=82qmIOQ*go6 zVDPbY4>}Ep>Q8%B;WMQy;-_>-7)n-!?*=nyaueeHiscYR&lVN!j9I?EIiRK29+hb> z@gd&cZ(2|JQCu{ zl^}|T=hv8$F+M=C`DB(PDtF;U{p9m)^Qz6?!aK+x3R{F7W7fb4HU<|P9UF%kcG*bA zX4w_$s|OEBWb%(^CXvG?Qbi$;tx?sHvC>bUx*rc#)peo(L`Z$ekOXuuh4U$dp+IG- zvFyW`*#jM_v`kzA6u$7fW{}`=m;{DGEH=V5_dr-C+ZVRcyEa$@6tS%&xdzdj{{DMS zV;(JTl-t0lv#9_F4U^fj{Z?WI?$Q4Y4 zkO$6b*dZ|HY+*d_SA(Y4)^=PwG`_r_neQFOul;HGq%3WEXtakzA=lwtxAO-5)r_Vo zV42r#k-@j z?1E!~Opw8p?{>EHhVAi`Rdimb=n3|A=MHzlvwt{)sOXG-L*pYjGYLyCC$VNECsg~F zWe9r4XErC@dpOsJaO#j5g$T)mk&HC;-a#kGmt^Eceq;$4n@0+?AM65>MfF$RjkW}a6t%hgjkd5kIFvA6tSB6FAj z%=ZbYGvw;9P`+*}P&?p&-HynH*SRa@4@=?7(?_N$fgWsjwbS#Odw&4PNDUOkGUTXd zo%ceIDj%x{>fnCdX5v_m{nG6m!Cf0r+e;e(|1)%@24c|m9P))p;`G$0N$I}2d{5CM zqXs>$W-AVLSA*}Y5ESsw#@e<=^s!u_34>+cD}#cB%&E1?QI?fs8mkb^-=S8$QNbag z!MC4E%U!z#Dm-FWD_nKD8IeUM@Y!}I{0YCi?OeIKX4`=uK$v5F1`o*n1*i}~T-B8u zbvBhRYFU+s&?^txlUY}xDtD&t+)0!^qxb4!JL+fIuH4v{GL7{%4^MbjnZs1Z<7a!j zmAmb)*E^Qbg)V{GlgC<2XkCCyx602`M$e1C7d-HGzDr0t>bfV$cblE4^_#h{XT7RC ztzV}leee`PeORn&mZB(=facpZH93Pwm}W7*^IE!#Ys9APOM`!W;@H6o9PVcHt7a6p#Q$J-l?^BOX)0#UoLp8*{19N(e#atd3H_L zvDw(RZ8dDvsIhHZM{L_h+t_v*G`4NqdeiHE-XCzDANCxx_nNiV%(&>sIlJeZbAk^( zYla4e(Zdk+K<3bo_<#LYn0}*c6nF#2Eb)KgVrV0VnG~T9T3dt*tKzplTdWdi1jxiTf}&~4Cq5NZa}uN_Lu#Ei;DwY1&y|s z_j27oL*et%owNTzZ%X!M7JZGkaL%7OeP&~+0T)$^}E@PRF2GZi?-^3eQDFwz{)baldP6iDE&TL{Yg~X zu#=#-Z4Y!Q!A7X;`{?9nVMF`x0sNa`2dg~0cVR4wT>L7tl_pyIIlI#aqS~}dbZ-;M zBg*Wms)8F_3cCslCP0uHu*|U5|MkQ3wu(^8(<2WtmetMWPgF?0=PezywHSd08e&w% z8Wg~a(}B5n;Ppzra!&9y=0RT;o_`X=Q(CpX)XAlQ%b$*lDWyS?{nD>{kVOp{CG}>Y zKd1*v1ihm~rfP&c$_46+wx$Ql?4vgnxR}(A8QCbxz^_mUzEQw)uqZo3i z)(UjnO~+YT5*ONhE;McdU(Iv4Nb^KtCC5?)y$v*s)dYc{Aq5+D!5TYx+g3v<*{H9< zT92h;?2Tzk%)t_LPuz!cNROV6yyn?A!xr*UsXn=!ObqL# zus10i^`BLT9o;WAsJvqK25K`lc;i>r?Vub)eXn{y0a%yHCe+0Px{vSDL~mjs#%nxq zyf5vTGE?W?j=G^rQI0v~Q~*0AbX{O;+u&o{a#QQR#uxZE=ZxrRKg>*N_MCUzNoNYP z0m&dpkqqC{-fr$`i~1kOBJh?@@C7sJ2`8gUhfAd23bgQh&G$ILPTY7;j|lLr;3jW1 zsHz!o(i7>IjCaJZ8J}sYEMJ%{<^t&|6isEEeGmN3d6;XFQO+W~_<->Tc?lkNEb6Aa z$oLmvo8iA&!jXv$rW#Jg>$wx(ov>LZlelsEZD{yhH-V%G8g$e7lc8A@$e?38McYZQ z<Uw|ES9Ex9Dj3i8Lz4}D3mw3bzwl6v={cd%a+R<^oJQu4VZ<3=F z&CLkP5$wrNDNmidoX4}7huvEny3x_oeP|Dv^@hjPzEelEZ>n?zp*X}TIgpUl8FMJ+pEp5uQt5j zXS&+y{%hG;zqZA9(UA?oS!@|xOY~O`2f+TW4zs7WK7Ja_x>}Dc-^ZlVLEM}h|ya5 z97-YbLOoX+BYGv{%w3_RtOQ$dF6Zp=#@?=%>ChKF z3&)Xy@B=x7K}=4R@wEV!0Pj~5=QytoPM$Q@7RPnnw;tT!Gv&3F7m#O*hG#P@KOJE0 zE@ep@H#d_2+6&8Qq=srILFMP?m`x0Q!9kRBbtuiK%j_rGkQKZTX*DWv+($fYePT<=Rb_gYYJ6dM>^d*r?~- zQrh9bzbSN_i^XEckn!&s%55NI*=8@JtLqN_{Q}S}FkJPW!5ByVtT1U*&OkencZZlL zsC}6i$n3&Vw(TXC6 z+Bm97R&6+9jyyoNznK$zQZugQyYgTCy_z+@kNu}vX@RKn&QpNl{a4Dv$#bN1zu-rh z?G#(qSoqddw%)y!UOl93O9qKt;y!ln&9Cv;_SLWzk;>$uZ`q-*w_YHAL!M_kg*G48U*QC9uYijwH0A{k zj6d#LBJV0oXkZWdSDvhhp!7e1uIs52vFBuAO(<;s_8m^?Qdbyzda&C2-*$x0`dLVs zA4V8B7$8U)G2m-7QKoy=qOha5Faw?P@3VP0eBGz@+Ifwc`LJ?HoD(v5v-Vz+OS@U+ z&&3$xcQSK*aDSa%2$d(y=Bgu#>kskS3wzj!@*}9C*80o&6TI-1+TUkHHS1`UAhX8L zrr^h(@QZ!M_ZDyOBJ>2|!1H!bl)M?#TC}eKR&brEGXD~)En4x_kJ^Vd+%sz$Y?DXx zd+e3AY_MUxoy6T<_0`Ztzx& z#SluU4>Xr=qGaip)Mqx49%P<_oE$b-Kh5?3(cuOTZa%zU-}cUP8D2t7ct>tdhN0v=S~lfzsM7b6O^=BrH?iY3xAybe{A*nA&6`-HwRFGfW&FM2me?z| z0NWR9efFjcfrh*O5gYF@;q(VeWa*V>hYhd;>j%xh?LyW@(k35^IXW(rjg7EH<(_Sm zFqfB5U??Cx@ zhc{0k$S0`p<$2x{hOmrLTtIqisrWp7|3HL~@qp3-5&63&22{hzr^?;a% z;!w(%by)LEKO<~RJU(Nx3zfZlZpMQLv7&g@PWN`_gQeFugtJpeMO$Fn$ITv^ja z^{ZfPC|&R1EG?D*2}N9RL0cK^v+u6kgiQjhV>J3dJpIg zHdVa0EJ;aCXgZ;sq0Zbn2JBeDSJ-R5*JrC9r_pJ(7k5Xw43QGCW|}&a{+5NhCnKQH zKAG3P2+asQJTc88sPAhOPz4HeM_ERq#Ws0*54IYh9E!MIfNJj8qT5A3V&aqby#U?= zkJQp*r&sp*Xh#4cj)f2`Oi1}y@k9Tfu~;}EAMxdHx7mA;%Y87{UifbJ>O@FX)v2*? zm4%JOf0G+ObE-?X+UJ-TA4NXfLvzKT+~f#!(=n**+zi$eF*GQXAUbo$5nds6##mm5 z4R>?bp_mJB>)u53MoNeKBNbn96L#4CJ~Xi9d$!%%@z=zB&@Zszo0pWUXrnMFGk|Rn z=V2S)_MJhpW?6e)58GR9EhQk=wXfCcWx)SR)~(42OPFvx#<8z_*)(M+LBWNa%-xS5 zky0-c+2AY%#iDkTXAxsGY?7_k&PQguTEn7IiqHdK8#RPLot3PcQ7_%c%f4pT*bFq^ zZ`U%oX3OO6cS=YTFSs1hD3MKJl~ojoW5S-sTuanh=aCE3+)USTJd8mpKB-m7c+IwFnoER?V}!HZBKORtoU+;{8TL#GU})gBUMc@J5! zRcecs$B&13wkF`(zgom{%Hsp)fumP(^Rx4~tN;%?J^`L|J_JrL{)2t*UL%6|msB@(ZHdRzY!m&9eT?FqG?eI>&H3`x*=7jDIZnAPZTjH_#5E1Ga zA~d!wGag#ykknCLwtVxnRE~WUFx?%h@uqr8RtQd#*xFAuA=&wDiCaSOmt4&O;bHPW zUu-8UlYc2Sf=02#!FbtPc&)SY_)($hXcE=)*mq2^TCY>%nTCIb#8O#kl5NgD5lI;u zU%?z(+{`$O^@)4+PW@Jjb0FU=kdA9KIn08+V$^#|F!?>6ijB`auocC^t>rZJk?8vW zP+)K|PlJKHa!^+5mfm$AfZJWWT=CY)=ZG`hH`flHE#-C0YbI)H( z__8uPUCJ$$MF9UYL~Bua2~3#;`MZRoQ=3-T(n1lwGDj*Z8U-c zfb(lclP*iT3E)&3*+E`PKF8*(!x;#R_$7eVTQn* zkoBD!!u(Z;{TBy<=@`{Wcz%(~zmx9)zf|6fP%yy56PxirBIqc8Ia(*s8c?C&ImIG6 zf`U0D0w_wtQmluntyxaw5HKiNN9|s!Lf?hf*e={+gtu2DHGRe(&O6NJi`6D%A7(l{ zD-71a1+{M{Eg(T`<7USvN$B7jd3;6b<_F71?P!x*#+Jg4iu&7-=hFH-fx5~sKjxDPM&j&~hXco3tthRu z6SwoUj;ufqJP98}^&}9a(1WemM%lTA^+YcC43#(M`~QL>N2|@<_!=zc=|9F{1G@|l zM+GbS7$D6o31)}PH{S>2Cmd)?S*@ZD;*nC_Etu_Z#gu<3N?y8^Sc>=?*DIS%N;+r; zj!20lHfS0qD#5GyPEjLPP+L!Zu%^)Gnz|Luz}vD!R?63!;7BZ?3ItEvfyRUW8N1Vo zvnzSuO9;zAN*2RSzR@?X!|wy&Q2`fYx+( zzA|96Xm6{RLOf2z+)Fre*zyp;Un#_dWf)t3##$I-0-1ueR$o^$nG3~sr65m2Y$YO0 zpwqp73rd$Kcheu%@0rlx2VkP}rw6ZoX**uQI#g{df8nYSG;z-2l(JSdwQ7$sbpO*B zssZ4Xq3RhRu5(jp z`(~QzsgIeR7ew~kWb0vy`DeODser0tEaHmCUD{bO*6bbF$#h;9_RmSb%Hz;|<$c3T5?bi_7J0 z`eWd7q-D(h{0>>L`@`TjJ%i0RFi07Ss1p{$OVoj%J@~9dU&4$sa6cE`#3lPlo$I>K zj>gt|-f3oBJ)5UNcL6mjovZ2FuSOC(tvrcbJQGW9(e#5)aw0PJ+m_wi>sN}qZ5tPs z&0i&?V*5t@q4k!sB6}h)WV8D~d`beQC&TlRT9^)i&wP!1cRzX#NjCF&fj8uQ8Nal~ z>JtR9|H^Fzx0=t^)Mh)F-_w0LCo&jyT~BiJBQWOneeLK$03c=ddAC`HQQ&qp3iMeA zgAdQfvuLZ@D`9KHIT#rny0BdNnUUb9NE3z)*rD0GCn zq3%Pl))p2j40vJWW}#ZEryy9V)~@~ZgfBbpeV>5FYEGr_6O-+=5;wM3hND6(Uegd` zVFM%1u+iuJV12S*H3$zTXijXl347%0)N+Qe2Ls`f%HVWzx7`()$(DEOc%T;KLm&1I zn*mi7C|}l}uNY@Aja$n@mQ=J*z91FwGVahvn7T@+0fb|5W2~THRSfE_=|<|g97hr} z4v9xYQOJMGVwOGc>C;CCMmh-F2jlHgWI|Qtu-YwQoPt|ev1dWYC^uSCbNuX~htg1^ z2nqe=#&@#rCyJ}sus}9_!Q$FTqqs?69VRXvxZpR3WL*GiU~iqNtqIAgC6T1_Xv{8n zA;aAF6R0g^ztMHY6y zXxK%0HMngG%}KSW?GW={rp9Q$QWixbdN3EN00kk0fg)uw&v_q7>soTjsqV!^4HLPR zljM6NlJ6l2SZ2<4b=Ya_zVm;ld47a?hD|%z$QY9t&5zkcI0RZly>_D$Bc@O@gXj^s3b$Dg z1Le)dw%=QHx`xi5qzVUpz$AUI`I}`S{o$NAoYOV;505o5Y2Gtj8?n-IUb^!EE$4fKr(HO4bg2>!L^?!l~9?k5X$U22TJq`F$E z*W+o+lCR+Ht*%=QUT1YbW3j5bd9BYj*(c9#CWTw>0^N^rO2@gGy13(7M^TWpfrzk$ zoFw<&({A+3J{Gj(TCrKSBjk+ z6K~#uABcZ5@3c;rl(~oCtLu`k!jmZ3R!#wiy)rb{LcmBsfsB$kX78^8CEfp zX~e?(VfKOqOCh{CD#!jn{J+9k%Gg|$$f-N6zPvboby;i`I4x05z}QofsQ7q0b;kZM z+{zLczOn>r$FG8O44F(>0=#V)!leR8nyQ1uJP91o=;G4yN%IycN1a_y1&p%9ND>(r z9G1)hM^I{W-WAK92oAhoL4R;IR&a+esIRB<6gg--MXz~nzcf#Ir8I3xuMoz zNLSo}jtJQ+Vg2ZBA6O*RtOD1Jm>lrp;=tiaFk0gxau!{{X){9VFNPEjt?3^+uZsFV zv`cxL;x2AAS!_>GA-`j4NvjcNt5KI78Dydc1Ha%~Se$CBY7G!0b!qG=Fk8B%C@NklaDKI6^Rn>=i?OLjSf-ieYf0bWe_{R}?(A!+0BLqiU{oPSv{JB=_X%_q9esPJ z@OcV(j|;VcB-YXt9dtE(>4zEpFD2*SV;OC*1E8&ATuc?^G6!3kjb75ft|g_ZQ&*A| z1mD(jfubwTSHdkjw;xg91yB%5Kq-2b)H^iiADVQCR%Wp+tKzC)DXTP?6XfFN`y+&# z=Q>7|DRRd7`zNX}MUx`LkBsxW-!+>K_rXw>wyW3x$eaqUOfkMK?WE@%>8nlnkN8;g zuTErS=>FU+c%qG$Ch(jfL7X$25UHrxN~k_neR4iSD(iWpmLdvt#^cSslwa&21#=$4 z_FP1(O=^Xnymq^E|CeWLq*omNSz}fAb?q6kI3~DLF`tF+C9j|`;^NOR+Gag+FD7s( zz(R;kI8GxuW&9cCLE3b4OBf2z0QizCJLDMdXxfUS<K&N}zHHk%zWE35_Nr-J&9fq7wy4dylx#K1O+F zsSPiS1Z0f(=Zrh4R`#yKDA#ZPaqasgKte}aSf0GhaXm3v=r3)9zD_!J=?u&Pe9VDJ z{BTQD$^eKq0T=dH)?v=9Y|{^mdaFxA+)IVSaoZwNO?(#BK;k+DO*vZOAMWgi01KY5 zWTuH#KZl6eb#v~WNGZ2juMvH1rnCm%hDj50EiM}O-l@ff?l~$dEybt_t|Icd3pGH{ z)Jdp#fz@%^p2`WEY^|)&Y$t&~k~G>*6gm|6aFBMEyoX>5K~A`Fr;AaS4vN3Z27_Xq zKA*n8Ii~XY%X3K(@YRi}fs7|Wul_T^R!Tlc>h{!2{K=Jh;hTF8j^QNWg<32V&9%w9 zZJ0y=Bd)WSXVvb#LOLN&2Nl!i{{D)YGUH?z>Mn9UJ-0?EsAnOi{S~?#l~Rz_l4iVQ zH@*(3ridWB&y#(GrbIR-)Ow7^G5=@@>FJ_3X;F91o2d!9f-x^9w(sTN0CWeCU-@Q) zLPw#|$+~nzxR~56qF4gPnxKAKWDW}2(ZV#uN7v5fVm%I`aSAGJQ=-ni=-(SD<%`9n z7%-%O;&uL1+RPXx1iWRyNNBpm7;3lI+j0DA3;UU7Ja;_9D6!308XXCpj+HRVsEU>b z!-Mu+F$O(w$AhwP5oc?*!5%Xt)=X3od|{Wl)A>`4=Y5&k!jGRKC=mihyK5>l4@2OK5FlWgv3T4=lNi zeVQ-0W=HmH>PF{M#NJrCW?XegbOL%d&9+mz!MX*EVdZ(FY_knE0#{S(-NK7!Ia6~_ zy%=|}tovj|E+GK^(#pKnkSP`YzsIbWLPt_3w(moe)p0cixY>GY=fJ?71;C0q59VgU+adLVz|)>AN!KU@Y&ZvQNs|d{f?bC#KPRYXG72H6{~oOe*H1% z4G&@xYsCT%SNV{{{jnhQf2EzLC29ajL@v_H?j}0YS=H`}>mYAnU$KGX2ULVW=VnA12;g0bQKgZNa9Wr5J%GK-}h!fE_OZ$KDG z4Wmh2Tj`JG5)JFL?HQ#mugF<&{yfRHD(SdtKNqb}hyZ zuL&JxR8s)%*r>U_-RwCWMr9Xh%=O=|u1igv2_^@0pYvDy1U6~fvXWyRUl!6@h8r+w zLKBXe>JWOY5OIU78^_HSyV`gcwJraFcuau?b7U}WJv3^s1LiT`O!?mcWBiQ_w@N17 z1M`=`D9jfGUkIoIw#MA{$^4E^7k%vvw3ZM5=)QGn(81TkmA)Ri=@i>Pbfs-y3iRh zeVNv|FFuWP%=Ai>(cS2sX~ZDo3gvv6qZ1lbd(zjJ%Dmfc(H2T&mpjO9eiNTQS6#0d zDTWxT=jQ!rNfL1f;u`;t@A_`j+DUntew86CYrx8(^Sbi3Xj*H!Tpo~{GDU51dfYTt zYd?LNv0QB}Xm*)BXbpwOSgn9n({dC#izisui_8@;fAtLx~Se(Au36>Z=R zS*k972vhsB?MaK}K%(?&RAhAXHK}It;Bo95!F((QPzt`kY_&nV(T$doQz@?VPQAU= zz&6rBNbfP?3KrH>4DC9QsL!iShqU?yIe!;@O%E2+sc@p9oiA z-)#4-M@xt(o%JgnXemi>hqaE#lc95|3?`<4?7w%ZC{g9|SXGNhO=oa+-2TC#vBWEV zw)}HO|8MDRwked;Kk(43an~oSBIh)!>&FY5AQCw%W5p~p;wVdc1a`?8<6CN_IO!<3 zTjZ%VIdT)`OtcJ$X!xowQ%45nzQ-j8cqCM&jQlhTc!ss8XdY1|+D(XKo% z7jAhDJRhH|mFBI#u$qtW7=+(V65crp49FmrDYL<9xRZpnWh5pUHNdhg?lS)%{8e@~ zbr0;iF|&h_6S~MEaEz)}s+%$bUB;|B?U^J+P45m4FZ`^Ii>4t$K6Z&VHFAf z^JL`LpLKz-4cP7=(A@XLM+~0WpR5JIB{3$z%Tw_8r^K}iK_fZEQ%I-=!AyzzxkGj$ zh0PBR`7$yKX&-PL0@NhP!q{>}Nqs8suMP_ic|X+~d;L?;$5I%^Ys;bE^W6VzjZT|V z;V+aWEa*3Dbo~_&BChg|S2;`MHnsfF=gBrrQBD5_(Ozs4A8U}l*OfYQciUb9Fk>1* zxCYkQu(x{ooL}Y^=Ii8}U>cFuz08b%qwH3#^hUjh0cnV}m??|5NJlaw8i9-;(PsO< zz(}y6Z9=BRz_)KzM(YYNsLbu5_^A}KW9}8a2rjy0 zsNB#SYs5$d%Bl?(fdf`x`hB{yM7dLZu4fKHYE6E{7KXZ6{~J$ZQ?9;f00@bsDW9=N zHbsbc&8q%rjCrovl(X|uTn>p+y1T-sAn2l7dAt>S3ST-ti84q>%JpW;lMd<8v>Pw$ zs6wdlmB2S%t&!+Y!B}gfVCEM0tsAr4?I5v;p~$^U?}+*JXuusH#-z5b>r35vDDfXh z*eb&v8(xR@H-}N_S+xMYzs9DnN4>Aa*5smNV(1{FOhMS;8XHwkGy?I5w58_^qdn&p zxaY5Oc)A`Kj)abuef-i;tpQcbFi^8jh?!m5P|-|WnqRC?F&%gFCKQ@)-o8Y01Lv>X z=B9j79<)Bu%K%slw(>Lf^`?G|&vAnk*=)gszbC$1T%@(cCChYAmFgh&;jchUQ~nDJ z>{p$?YO`PA=^wnB7;WT;M!r3r3Z7JEzhg0I)*phWR*Lx137p`HcG~Q*JV*{8hmjwb&r&5J! ztu@u=Z*~wtOWrlH=i!fFsKd2!??^P=-tHz3V!&{p0r}LU%t( z@Et>N>ox{&Us&s6Lp754>y;(c%R(%lkMmUiU}D5PT(la%Bc?=J;569mbrf&h4bfAG zN>+O&DsZ;i(l4+heq$)i9d3A!+BJJ%t+aIh0pyHoOTmj9ZKQG^=1q0Rheq&F8tn6F z4b#I~V59|OLGj&$kYH(GiV{zUj#8st()dwxEv^jF8EYuQjE9@dnRgm>m?ZVM`H^Y& zeQ9?9)!|pUkYqXh92VhR4FzfH-!StZ=i_5PNfwXTeS5J&w z)Ed|PZp0Y~foIlRSYxfGOA@96P|Aj&GFEX(ye0DArq^&uqv#(zu$EWDm93^gL`Bk< zk`Y=b%5stqG2Lrs4{u}7U(Gk6WXEaspzmp+)~RV#b+)n#$0r|(yj14yeSs}dO{u9u zPbHT6vHkmWmpBB(KG=-_tnLeP?+_=TC0jgFdJFx2ktp)IA2(Gpl&23&v=)au%FKgh z1lw;E>)l@dml@8`>N?=6O8KMMYvlu=8~r2jWT`P1)wuBjwDdo;@3ty`ol~nEs7$$G zLwgWJ+&iYk=?xg3p&&^@Bsd@@!?3ITO1h?#H*mTwEkNi~yRA~^AF`U20#09L)9WM= zY28zAf1aH@YCl75T!pq_bIJNsz)@ztDW+?ky}0`*n=Zmw;I=@3m$wk8b1)~Rl09NC zu|-c(x`7rlQ*DT+R2ucLq@KV&SrX@i5aQUkT%`U_#UiqMwGt8UnS+~J10eQZxjPAkvyypVuMLmjO zlrHxH=23b?Hm-&%(2Z!voBJbkXv|4JybOW|qVQ!jcy%z#WwF~1!W>(_Rs&kj{p>p; z<;9v!V|3EwKmAGbwnzNM3am;51X~?yv9Gd6u=D}YHT|fmNpF*n3W^TVi6wZ7#~>cy z&&W4mTXb6E5yGWgSB4@)7Yv%~FBkgwt!8eBVlvjc$0=~g`0`slOjpMV3Yl%Dcx9C@ z-{flfm-Qu^Kf*afQlys}8zkqg z32IarCnr5@PczFU&hU`B-whg+``PV(dM?pwJv3-#73?i))i~R-;K7P*S*aQ)P>Kg* zxHEH@Wt6CmZG)ftgDg?M$)aX9_KwvD_-PYq;b}-%DbD2}0m;63lHwAXs8Qn1aI*TK z{31Y8q`q_5JU$+tAyIbF!N1GiwQC%RD!tt_aFga>7SWL%bXG`3;_h!ze|FK=- zYOTwGpE})*5hW48j%ePCOtq*O>csu`s1&kusGIXDqmBcOShTHm!D+Dq6GHgY-DW- zOemDQNC|ezaD zafZw}LEgx;t%FCyQLQ!g?}3!79d0xFBbYH=t4yatmbNMBjD6P)5|}2;NF@&o*8aF( za?cK|harBPZ~*^qpn9nzORP@~oDQ+!?5KJl?hWAa`pyqB*gjf6Gd9GWN)$O-Vc#@iJ=b3harb;qK6_(%$y$i*i@G?v{jre4=Sj~lggS)^B zojVh?d&a>XNxi-z{$oC)hSSW< zv;zXRh`*nu_SfpHkN@s`XNh!JW}EqUTi&8|yisM`<@ZiC;90EwGtjnI#(kaKUSL z>A9T~q#jKhG0rNN-u<}12X!QNPP_XYQ{qiRqJd8PrZ(?Q8Hz5+#f~k+3X#tGo zO?7Y|YYu{kfDVZ&JBV(RSJ5YaVm&tA8BfNpg*-7tLi_CiE0QV`;(oao_!?A5)i7^Iv zh>hVrTr{OC^u%b@>?$>Ko4g*plaMm794D4KqYz>t6gmjLKNLg%Z8s}*IKb)CB}A(? zLEzEAVAqa++8&PGKcuKg1Z88R9~M#g-s0nnB4kqXPMkW7wgDlPN&G^Rbetg)r%#1w z#p<$1SMcTv2*?LIx%R2!rKKXI^pcC9-b01effy@NUX(>6_B`qFz5Pdj7f{K-U|z_8 zZ6;+#j$zq57W1{SRU+{sn4Ln#shje?p=BUcUgVBI>L1QreW&7mUdKxp@!K{&TeNC> z@%(k)R60lYQz!!srn4bur`Tu6P?)%oF9^1~IUcw`Da8{(sY5fXZS6gXu^Gc1;v$m5 zfm>BZHK)em+EmUHgr@aaK)c#ZRj}9Ba)eGJa${)4Ar0*JV{-+#U}ryot66u-T(R2;%B>R-Zc|%=jyfH7B!vj+yTNiC#h1wh&F3y zKnWLr+K!DeTBwLVxr?fGOHhc7Z2sZ0JkSVYkyTg$yKdH|!nfouHt?p(KSUHajcCyK z7WgyNbfQ?WDvo#3N+$%B`2({TZDBXvHiR0??HBHV5ph|bR$$8h#2Uz6#%DlG;+&>(F0J;?T!g&kQ9AoG>sfA$s3H-kgPH7w!o*ukh9c1!#2EF|pe zzx0l8UM%NJQ6b%e~NkTX!z*otbh`E#&P|u z3q4a3aK8`@bs%p>m%Boz?7XK`UEDTq)U`Up2{WLNW|lVO;?};ikG{UCMS`jAmTj zmgYRGx@~Pw^zi50sWH{gNFbJe2~v`UgD^(=h8S(pN~lq*q~OA7+JUwZufRB)YQm$w zk6U(-cA=(R+$lRf^;XzMi|ZOS+%4pLs>0zYV4-|$#ASfTDjT~86ZkfP_<@d34O|`Z z<6bAe}VrT5V{_jf`B4vRA!3#p%W;{Aw@dX~Ay?DD}+Gm#LUE-^= zFH^&|s-tX*bg~f-PG5YfbsgYK35syQQ?S2hkHf`s6VF4gM=^b&PunZ~@J$(5XI6HT z-+IjDZi-O)V!3+ont{>IdEM*^K-fxzVlq}G#!?gQoHx_x7=Mcljgq)e#(|TxeNOv< zgd0{p1U#P}yd1G{Z8zyFoF*b>e)<+Iad4U~bsLhae;%ujQKW!PNeA^_! zg^3lBFeglJsk^5REPPa$ns%{DP$-tHv|=hhoEq@1zrK-`J1zmXr1q;`i(@dMz12Z| z6Kd}Yx;Z#t+ppgftif^_D#qUbp$+q?mjF|gO-KVcqq_EPvMgbylXXZohj3sv5$A1Z z-w)9W2p*%C!-5uw3maYiU1wUuuYVog;VaQFXfoY>Toh=c&xZKr4T%doQ*X=D4|hq?jCf$ft;1!BB7X1qNoP5C?MRAp`koRhZGkp^;4bhr7d( zrt+sJk$Y)Q107X-EndFtQapHhB(i5{?Z*sEF3<6u4FV6QOLaCR^s8bcJXKp7gxwkN z%Sm4FcusK#YDanfT9P8B!GqLoyj3PiEBgaKD48P)3WV)e7z#$8yQ6VOb|g1<{0iYH zk;~i`s`(pVip%s9R(kE*(!Aq;B-rP1Csg8?d;*R$9M_(M&rUL(*7^u7Zl@s>KY}(> z6m9T@(bWYIe;lqoEc_C@r!Q7VfEAcz&I|~T@~Z|GXC`3_h3QZMG0`1yJoF5vyo@(xnCW=iD`hKTY`d8g`j(kaNWK%Enp4A-Z+zJT6wGrg;=KOt z*>b;5uC2j#2~P%`uQrHu35LJC>h$ETY4){T4;zKYEQFbv=t7_|5qoYA=%kyX)h$yT zY&|snckT%pV0_InbFdZC5~j9CK_xpOVWtl65nq+X6?ul39;k&c=BA(6_>{l0LM`B~ zkyQH3OWWhSdnTm3n>YaR_~!%R$7rEaL6IxJhV%>J#+)OLGKasA_v>uOk+@B`I_b*0yX zAi9h0!>aWEu*N$vJ#?BK41$;QAEnfO=s&1j-0uq)Ti9D1{tFWw(K3&chGs3IS121a zTs?(j)&LsCA(S@{s&HwHJaquL>CtFppDO;hCq%6%kUyU_W{3!)J_F0CJ$B@d&35^~ zKsXs2iPL%*i0Ez>zNxqHm6>kfXyqS+Exm`>Z59IM6dd*YWiav|rv7urI6(zHBuGMm z(%4oG@5=X~)+mssy+juY@jF{|)eJAAS6c%=(VQ|M;~qlSa{~=WyT9%H8gZDCoBXsX zkrNOM^84lj%B$$*!{t5>jj{fLo`Q%-D=1Y}ykp`g{QC6kG2Q+G^EcpCJ|ByPEmKJ! zx?SytmBU3&F7gV_xJiea(Y6-6HQ*%Snu2oiye}<9`Uuzv-xBTkk3+a=^DT_?UT20{ z<;VK;|K!UKqU9+qOLUATO{Ty4fRkby92q5Xyu;c8_k2Uy!p1_4TP|U`Q4UCdhBJ3? z4}HNJ{|`Rjz89Bed!)2e+Ban{EZqLd0g)Zv$Tq5Zn>)!M@`Cca$VD?W=2`BuI;yq6 z*9>bsI+2r1&-|3O=t@|#6t>gO&MzpkCztZMmqb}HdTE-nywm#RN1bBG@Sc|@1)tFX zDlBYD_e{_Pn$#~KIDM8Og>}C?Wgi5kqLex3=XqQC!7_PkGh}2*9<0sR9U&Mr+f3S* zSlEc-2n=ApknbNMIm_D`g#Ccx<+HQN>Nk4%B9|UTQdLO+*>00QWYYq>MZ}Fl&8-cN z-*`Ci@B5DW-R6D2yDNJ!)gV~Lwd)3u{UCJKREDkgQT-0x*1A8K_f@E>eR_i5#OgAO z@<8j!b-nT)Nb2$NaozJ!g2Ef(-d~t`EHOxlMm4CGpRPp`K}NmIW7$i2JhPO9|FSlQ z%7;;>>;HtbwVsO+>P@&()Pewf8>!Nlsg~j-Pc%woC(I@UgMDelWQ z>SK*hD%*6Bi)E6**>@Q_fyU=ZVDclq#tW+|y2~6w3cc~(uBOEE0SBp5x|B4ba#V6H zB4QHBcd|2?>MQ)`Z9hgbblBgP60FnBZo5{o4BLE7#Op+;4+K<-H^s?%e)l7`o``|t z2Y}nhTs6=oDbbH_4Gx8n%R9kJdG;T#(+*^t}6!)UVo#Ji`SqNf{mkq=Gdn3PfA&Vny?^ltjoG?M*ST}j zOR({v?~2K{P*k;FivDO0Ew$5C@mEFO+*j3_UM~69>otvBHw+`oA>i4_!(h>VWCsZrtHY@+{aP2J zjq(^}hK!13ikqX{zi|9R!LbQ zh(7fEA4Ck7*Awx;L4xQWBJn~nd)3v?$xm8)7#XnsnrpSKF7Z53`wUNwXRACDGKxcB z>dSxj6VSIrR=FaAzdK}*Os~TB@7WnpkgSm;Q0;nTl)ZVUHTt0%{n>X+8jJ!kx)l7) zzOz~@{JWk)3BW>*M8bQfQJYrKLrx{L%krNA5AS-Ok=JyP&2g@oRFglTbHy>=~M)Y&m|*Az{*rw7T>o*<+Ybhga=83zok!CvB6VWRg( z$+orV$nR&3lBB;Pkq)cbb{1|}X=!ErLL$xk6<$~{IGsPJ#PU=U$ueBKpXYV~B&F6H z^K&QFq>|cmcbMDB&0Cj=nh$E}>g)QRul<-!|6154p0V$&r=N1*NE`fin;^6c)?M69 zHE#^P5nt-@DfMq$i3&ooq=~(McFzFpN+xsaJFA`q79YX%J2icbG9dwoj!M$xwI&%) z|65xO^W~d4g9;1CryoGnz&po_=k(U?GnrzQtV!(a=^keuIz#?nbzz_K$J!6D`IE#j zd2}{|z7L~~A@ft#cRmN1j(mOO@!jIK*I=Ma_;g?Yk15_wrpT)qLK=aJc~K;4P?l& zWj%Y?KiOb+WKnXS#p}xYS99`SIEAmr9m=pVKPJ&4-UXW<^bT#OyT&!xFiSzo$}@)U z>S$$SxDi?f_CuLFWkD?X}F#B4tbJxMFsPhYsOk65ZBb| zpp&8S`od>t<@6oTpBb-)K_je9SB1;iju7>!=PWn2rguD8AN*pZ)0i**i1fApU-K`+ zW0hp%7pA&^%PZ{KjE3sI)as{~ziY}dgvipYG2>1i;CdUfN1(LeWZ!1sGKXx_H6@n1 zd$nd3%*&+if@|{-%(voZ5iE#r-L0Ve0)A!>owJLDGe7QPJgJr*e@+Oxs#71Yk%0v> zZvFX$sPt%alXhHu`L%xx4=?)RqLtp%)2dFH%oUFkGSC)rfvHcn%lyxI2;Ystxb=jXU==xnU2GH=jW$U=w=S-n6q?*^>naQiTO6a8MK}J6sG8do|e0LHM5?XBECy(it zl8{^Q#VVx9e4*dceuTVA47FjqgSc2waIIZ*pvrPyxMH^5-(hXiEf`ka8~!IqmQ_QwU_i+FvQg%di=H)pjHg-`Wt=n*HCd@94kXMhO6$jP za4Qm7`g%M(O_M=dIMt2g?}#-L=~I8E z&p9z*Wo3ZUX+8%JDAXvBoY~MnBBKX zpdpUpZVbc#Lw>VAd-sAG;D1iHa;cE97CUBUEeGBHzFw2uX!xlzVfm37RcBY`c`pxL zFfJVDNVKy-9#ABL>+joWrmV~b98gtvX zex*O?a?PqQfQd12KAZ$w8edoc$3tTNEf!mjqq_s=p+6OwKyoHAifv%6c*PA#N^)M-xUP;cz5hvL_FUa(;+k6+ z+_+9oMC2%BX*zQ;7wa?ptKuLG z*a`x!yf=9}&L}Vy!-u&~gU1q~V!Yjgr9n;Tlp$Cbp8uofXcu<{j^|I!@s+rEfi!~PjHKoR|4VY{8Xmm1Y_T}|GDm?!SQLohlj3bpo5 z_C*%j+iV36=()D!M&gG11Cz5Xf6m<&i;IwmA95`2wo0EwweROE=xm`p z%yGFGkySa{>CLEZjUtD7VisMdEytof8k8d#dClTUmCE8m$f7a4_jq+45NQnbmxS@6 zrRt*zg_@?2EX-|Bdp>?Q{&Y5vfVUK)HCCjJDNl-|Pgz;_q_FILC_P}))`_JBnk`qB zR^RLvse0u+%y1<-uJWFJq06VOlA`Ulj`IJvDYO|EYQ^w_XuFc*1LNpJ&dWC?-%Ml3 zbsdM+xPdK95ndYT8CV_w1Ub6oFZLn|DnI4@h-H`kpzffwz8vGH30I3z>DN-G42s`e zh*1OwlpEIQVF128|DkU%di@10I@#mSJ>`o=)#`_uvRY56xTD~mjFTtZt*j=So#>E_-+fnPdov&$RCu6ONPbwKkvJioku3ETr6U@ z{no`Udq@^v6v;pWbtlM+=DuS6FAS;*8gPaewQsLpt&6Nb89qM7tlzW4R@dQAPgl@W zaR7?9Mz;>ESArKn&l`BB!)*h&c$EizaXw4o%i#eB;iu>lThci;G|%DOu6B^5 z?fZ&y4PM9G_x-SLk?wR>#3)|F{=2tP4y8q~tLK5J`DiKVWv=|I8lVl*6|7iUA{h-A zkR|AKN-pLV{|sN~do!KrT77( zh_l!TY=y$vzDp;Y;AMTFFXcIItxw_MGW#NvR7xr1>n>?%IPnO3iaJJ&6Lv|_fqeH= zb12((qe`4XWo7Ts=J|w0^M%QnpC&p8G5iGJqwBuza2ZC)4bH$RTM4a_@9=$j>BavZ zGy!Mckej&n*|qc7rsZRrfb#bHthj~cz$>cTly#rzoVdqZku&NV^x#%TWaV)G%&rDO z4;)G(xbZSbFVnAAWbM`j>KpKBo)7z$H2=kN;oBciTW*yn@pc+R(-fY5v~ROMUR`0Go?@t$Yp$# zF}c)#l3w;@9}fd}h~`HZi}^TVZHutEU}qua9>H#S;0 zmYSt^h+3vrz%Dsnliw~3IrH4)pA~V&fb1ud0e$oYird+Gz6;Hfzfnn%A1zud0RIR*Uzs6m{2{HPs97Y zJ65S-C*ERGCzIl^X4u3UO>(v}2%6d~zUd6B@P@!oafnx_{QBjAOtJk#aO1xC_9Dn^ zqfY!n>!eQNQ0O+@I|rCI>&};@QAmOz838(A5z{wz7O>f6o|busJ3J?BNkHHtQaDe|DWBzSzRUrHbK(bt7bX6u5nZCM`xb|Gmu2fTJo8OBMnHpoyVoU29Ui2u?c2*GUssBpv?8F0uMY{jsRjyuQ@Mo<&llk{bHKg zq?XjmTO|42_^2@PU4^R(FXJIOm6l}>r4Yjs?==ZPA}&! zerW@Of&!a}J4pD}wwa(7s1-Rgpx1ZM4`a}XgQ0p*H3>8z=V7D9yVC&)LZ$Wz488Popyagq**|-#LvZ_6n)1$n+nkqo|ED)quXk!VdtA5}vIxF}t14vN*z5 z=rK2se63p*__B%>*j{)#a!HC~$>2}p?;nlrYJa;wzHuOU&$hq2War*aT?S!W<^4Mq z$j=2VHH>Y9tYt8su=|y~RHP=kRp-vBuQb#M*f~k25Jv01=K4U@W%Yr{Qw_?BpS;xd z;K0gJubgubRy257I7Jk3@G%g#kW$Y5;Ajqa?LPymS0N;0cXm*tv-x3{TUhZr**^pkXQN2?k5$(?%aHlCO z1W}?AR+PkbTghW_$jutHMBMvK6bw~zW(g5D{{&G91nD*KwwU?Y)Smv#@6=Etf21PZ zlN;e#vahCw>4_U3nQy~ApV_lcCj+5Zq{uu76O{Z&qiFZt2UVaG7~3{r@lx%xKYFZM zo$Uipv$wCD?{r|_=R21IPv=dXoPFmDPK4S9CeMncub?k(Fvh)EBax_pql!(fRD zbucyvKP$`ma|@-Y<-rGqi92D3ZAEX~KE8=dB?3~~>JAumDCb-mR;vc1ge6E^EZ)+C zpD1Bdt!MKwm?Z2ivcME=R~O`gA+}6^{NL6cJ%s%h)#WZN7^jgbbpK%q8;Yk8?k4>0 zV#BC-bNL$XaoKYpjU9ZsQbzYmqDJj1RySop!}T{n^T5@_j}X`E(TQ9ya_Tt|H$dt3 zpCwS7C}ctN?w`5Dai=ZHkI<7FH76z0fI)>| zUBZ1JACWv6NW?w$e#W!jn}4bFEqpCS7x1Ypt$VGifWoKi&IdST|BUk4^d%(*Df-8j+ez zvnmeI>(}Zh5IKPEk{<2OG^mg#Q9wTVRt#Tkgt9h;py5GQV z{vnn5?~KMkpi=yX<_vfkY&mja>cQ%<8Vt7$JV`w%Hh~Ve0#&uCYeG*jzkq;P5Z3bn zm|?g^a`vrPoPpqIQo3lbwB){+-CezkwcX$-%{We(R-*KK9mMt#xdow<(f!*aS9ZCq_Ox#n~H&jO>InuAfWt$t&Tn7EJ2F4yW>GC0SgsC64A!}+IjBS zmn_Du3f2tiovq(%`mpw_&|Z*)(n3Ke({0_2-m0E1arHLDV5OsM{mJ7rys&}2axl`l39{(C z1MuWsh}UcciORlOylu#V(cd};oRXY%2mi-cUbqjia{U6b9}C1Nf?{DQc&5Imu8+S4 z^Bta4X5{@(>-JKm23)>X(11R4_0GvF{)I?Ovbm6{ILU5vTRJUgJ-4|qN*pT@57Jx= z*a_#dG$QF^QBw#}Q~0hGi}xp>qlvz+R_Bh(I;N*8Jc@toZ?;1IccJrE|NLi7Xx%(- zg6bVxi&3W~F#79uov<0tp2n@jr+(Xfga4ewHTQiz_jpLlI{{1&Y@x6K@&#~yM*d63 zM?b{E*(Y{kA0;=N+Dj^Ckzpj|%D`cQM$EBss(TyLj*T>W_#BaxG*mgE>SfA*S4rEkoRj!%tFc}fc`bwCS zVf_xvC;}R_8fTlQCxbE91m{m^V?ze}b*v{DHI6UQ_>V2gpF+?)WAw zIdxI3^Hk>|7F2$B<{0+G=ErR2_8C;PT%`HX19tD?-&v$4Iw*~u#Qs*);^1ED5hd&_ zy{!yrHlY^3&u}{#M{tx45pFEayl`;JDOC0Fu}0=qNK_LhGOCMqRqP~DI@?s1e=~7~ zbh1kWJi5Z}=i$T8XU_2RC`j*FCfvcRYu^8qWc>;D8a55S|0AYQZ8u4SexiibadW@N z9aZ(&IcK+@oyOtn-sLMvw{TfinALKQkR=dGNGcn)n1KKO9nF51y4Pri$1xgR%OAygQd*mAVe zDriNSY1rpaM5spah5T=*pFbWC;K;LPSJk#yP0lnghG0fSlVkegoH>Y#s?4~3>a2Ru zhi&RTk3QeWdUq-%7pbrO-If8HrRaAbtFO8>o9=#cM+rw$UP{8!)ZJ{`){nYrs*AX7 zlShVj6xpvJH?*AADNPIHTcQNLzLPqP3?Ngu|JEK)e$R)4F#lozzoKRVrgf->q&L5b zTDJ@{dyE_x;|3$mS+KItWG$aPJ%b>9Re|a4cX}o^K<{&h*i(V{c*p5g=jih)r_b8z zerlBpDoOkL;iU7=0K_TedgC+6xRuZhf9)|u%9rK<8iAOlmlZO_)#cfysbr(zV~&2y$)&{xeYU? z4zPnUUDO@sV*kzYh>uHdQ})+lRlyN0j$)G8_X{IpPC&8svcGC$?EQq$Ey9$<^CHbE z-1v0Kcg@znghmm!OW4^U`D^td7%83PqlG0ki*(2e;rv}>gZxa% zNkb#0Gojcx`esYR+GhUNbmEIGIz+#}vhhGJBdP;aQN`&9l7`{1dK zXa?dtbRU#cT7!`?t_!~^4cF1pYCtHNA~+}$z>0mF@l7AW_kg8AIv*;_i7P}ODG&_0 zmMtzAG`9j-#O?7(!%SMm>#QkL6Mce~$F{7d1^WNx3-iw( z@l6DKxxo=NAo;y51v$Y3KTj|?!l`>Ksx5E3$kd%gHxqC-o$DWd`F`>zyLknKI+C=8 zC0HPj`)DO587fnIf@~r;;@6P>7Yq0Qz;o2{STT_HXlMwJ-p7noC1j)?455@IOWCi_ z6+gyvF%;J>Hz)R=zW_LhxcD{1$sG}3c2UMTO!%Z(uTjq33|>}A|NiRdrrvUn!nFL; zNfGOa^4(n%C96*g-;FG0$`dJt5J`*|?`sYrtk?SB<2Z$HgWnq8#Ypu3v?Q|B zZ1E6&PAXWEgF-~C+Fs-a?VN`#*>L)*Cwf>hC+wmXkT8Ftmw=_KoaO{b zvEr36&xjR*=2E2MN=Z57Z&vO|Nln~S@z*z~xD&?L^?Zd$Vje?{&CJ=mcTvV&p^-*AWk3uRIq@0{D1>XiVCJPGbII&yaFCFcg|8nGI z(wyrPzj*L=5eKFahppltj_L&3ww-Pz;8ACdov?y+r<_MuaCPT(pQ$JGY`tCrmTvm@ z7U%P|_**NaQTb*I%1HxP(~%B3Z`JE(egtTyy?poa?{4}J$u?ICb8l=bOKEB*X;RSS z&P{FayNPU{kV z>u&T#80D($BL%8lzQWr>SzF?0I7Ukv0VaY9i@EC>!#FQ%-PFE@P8y7M&NN;=L4IM- zRCXiOygdA{|13I87e7K`)P==k2TBRU{?I!`hJgW8UDWr#PCqP5>TCR4G}&@m%={J_ z&oL=C38WTWR}8l-A=xpqZ(|A*Q5F~xPI{Iizl=-XB_^3q_vbqv*W^8RapWIX=ty;< z>{I}aj5x#C0Vg0j!LjMD{uOwYB6S2F?C_L%`~A9`JmX1S%P=Y2RAB^ceY2O|!WxN3 z)**aozOCoEDhI|5v*mcpbdt53=>GZgaJvQ{ICZ`uGQ)bak5z7`ZZ&8g|pN#4; zQwyK!DHM4oq{OWtjFpc8$XtBczh(?^|Ky$*;2gjM2LtztAt7I?qJi`c<;i_%qx+A2|9 z&?!DVZ)?}un#`#+{T8EIf^I$}RV-H`75=S&LGWL}IHLQ7zN(t*^%e0G$r=Ch^msq-8TO?8TXFA|N%TTr zCJTw08Gc_dB$~V7I_5uq?a+xHBF;vtad8@vYe&E?`W^3q#wYYvyP}2%;~SP*|ggpEM3q z*Dw8Gm8s9}umOpy0vKC44&b^WcT_42E64r)A*_puh9f;)OmIFl97OJi{{8U%7to?@ zUQ}VW92W@{)t&b}nMvuvBRLm4ve?l9L^QZ{C~Yxp0iVTg6J5%hs-(?8t*G?qvz&yf z=Y2<0Ptk@EXu?kef!De4j|sFggOx_RFJ*&J3MHm}yncs4u7O|*4lH6X^QqrJfkzk= z$a%O{t9O35tZLYoI6H=1JvZzxz3?>BB>}WHG(@v)M66r9MaWkG+eKo_Nfec^|3XO^ zXfc&ErK5Q=TSS=d2*#`<2;@nlUHmk&_|;WB$B+&96_?+#8WyY=Kk=qhF8wW7@Y{+CSIl9A*bV;uWV$P z_=lkHFw%3Z;;31)ST)esX*rHGMqs5 zQ2b6wR||kvI5gGr;y&=cAJVEr#K?spw6Rtbi{tvuDs@g@NKDF3HC~z_{B-2czR=jT zIBZdTHyo?k$RO&Oj#bFRW4?4ADOpTSU6FvoRf3@-Cm1e`v*WeO(dnLo-!}4{$GN%kEZ;IoPZZKNTQ%`qv{Vg=hzr--hdJdNsaMQO_|8DyT6MUC_S*_Xe!To z9N;QWdKu0{JP4F({n6GaZ^2est`I_Ex1{Bf`-}3&#WZw7)^J;n#s654c$NIWr%gbZ zESjXf(wxnjsy!6CKHtN7FwK`}LSrFb;uJ$BrK$e~zw0v>iOq=OpI~rcOuwdxuaHG^ zLv-@g_bRIs!QQyo@TSF#qUu+6<2=bq0Cz4wsoh&il3dkO<3Q?I8oBq0HqC*7oomZK z%+11$!BWz<){YjGD@)!Ep2#aN`3;Y2Q~aDp`eX$9l%Bm38E&`#ji`DjJ&oaUZI^|& zo$!Bn3vq2nh2EXp)KpXngRp}uwS>{}qw+%p76*o;9U-YIOt)c8_q|6)9jQa0PVm;C zi@gqKhM9;<^iS}OG~flN z0?}{5?MZ)fSb{VFM*qUJNaM1$SqP%g{$(q+P$)Q^DCj~UYj{sayk5uz9K{}RPhnaI zhwYs`(Ch_dq%XI@FKWXj}ya?YzxtUVttvnBJg8uFc6Q> zf73lLu)vNG8NP@*z&8__#Qayv5jRr3wR5)Hcqw{izi%Z?xjDb1q@n(9?dMH1AwqkT zIIcDu-mZP|?kxLlZ+emr^%(h`&g9>~k*knx(m&U_15xBwW?=&}y1#)6OM3l%Az7mV z-fHb{SZn%X?9o&^>L|4bMgPe}ej*& z4<1WK|KSu)RjnwxPxUjYx}Daun;B&(lmF3|qwB%fEy@+3HCPI1Nlx<0zTgiWw12-& zDP8u^()_8+C7@jgZ4H?ArT)IpGMS#2`lTL{*OdplJ-ljipe_rC{L__b1NzBg$V?PSm;Ppem;uSJ# z;lmoTEx%mpyw0G$X&d|%e!E?Fzm^9j#UbBG+QVJFJA$|t@Ok76%QCJ3*6h<0_1E)7 zt?aC+v-m&OOkmo%w$AQJ<2-?)QmghK~GQ0Q|jlz zW$dR-1S~j6f)C>eBU)JE*78)aV-K5G8KD-a?63SSAi$r~0vJ%Om=Gv?iO1-eAV_ zRYL1hV^^zNX?>roBc!Wz&EUuEC3#fGnB{Erh6*2`58qk)e69YUPcpV>@A%k@R2C;Z zfW;zxG9tYEbWQjd7!5TuGF(!B{)eCY4;(X`UBV5_&w2y?@2ft%m(}@b{{G--xzeiD zbFYl2=y+baE1f2YWPv4~^v7qN^%NCSoIJ=QV4cOg-`j@z{sH>>TSOR<#fbU>$rpEK zh2Oit861SiUu@R1ahEp-4R?LtI>-7p^-ei_t7FLq^j|e+R7yMPtc-fz zY*pg~E5ONHEDpGR1M62Lm3;I9+$r?~A;)u@)hYVZ> ze&1u;yyuB#)sueIBrkEqMHo%ZRyN2AuVpT$nE?g!c0 zT8Ebk7wa{MoElvlwBc*1kuo>TYo8N?x0ER5^_y5a#&Zs=>*+vmlB@%~aKgka;7?FE z&8@@>pM2o-&wgSweIn7*?aF7Aou}>M?YPM(+FROOG+M@!@A!Q!9ruaYe*A7b9U%WB zVv!MaKip{lnt{+hrhDjOCs&pX`AyNr2u= z5dR+~EE&6clIG~#FHf1q#lxJ370g;)8s;)`wcMqC#%0{QZ{t^8Fl| z;BROuS)Xs^f=@oh4lk&VUM6YakOMOfaK8`E#o2i-;w`dxi7x=2;ZsoI<`5LgV9Gl7 zlEbsPLz|{6dS%biSG=0+Y0O=g6%tsOU$oQMkwx2`D1aKDtC7N!#u8bn(5*PWkd*$F ziBq`TmvlSV|IV9rz>TtCh?{D+`!${a&d$8OQ7_Yk3)6w_n`sz9*MW)r8IV4enyUBi z1lM=xv&WDm8Z!!F>%dLIai!x{hq(@FRX=Uti?>aT%y0hevGFN1=ME7D;(TVj?H^e4 z@<_U^x|iwS{wf6HwAO(~kR;O?O%%wRFt5tjo4TWVlUI@x%0`YE&v zCYe&%e4XeCzN4fUk1yKP;7^su}f7KNK1P3>l%H>obf|sFJ1^V{M<1d~?h`b>)Yvz99I}-@_h(|B(4rsf&=9 zcDhtw5F(#SU#@%>@GbG+a}d`O8}BiC2k1+Q+xy5Z$MdDo=sql3NNq^wzoqm>Pw|XG zCtmus_$3cQ*;u`??^<$qhLwrYpO&Yv(J#AiFPGdK(l}lLo1;LiP(jDAGX?UUM>}q} zL@4ut#Yl&`*MD-by#fr2ITESv+z1pX@Dt>VTa{=^e1nL~f{j>-YhKZQ6Kfg!AR9@su z9rvwpJy-@DA_6T$gfGrNgKo)k?wA|xCdrIXE`U*#YM09`dw1W2@KgKEO&XAI?4DKP z*A@G)U8Jj;FQwc5|8hIG(n+UeT(c)lg>y#5X9hC+^S7DXW^+Zd3+hd;HEOu+S={~+ z9nZ=OrAA8eRSTV?-_bjjtz#-Y}lyKZW0m%XH^4I0bj{v(v%~m7Jp8{18Ap=vo*`XgP`~pj|XIl>} z=;NjHB%7?g2D|Q9M?8J7jDF%WK(TgCc6goGD&5hXCQozSwXM^RqpB=nC(y?=Y8hB8 z4UF-YB4a&(FK2{zfv4B)ZydU9zfs|%vjg*mV0H5k$>j03M^SOO0wZt zgbe*@GkJ6zk}YMmqCHrP|>rU}f@kfI#kGZnqm`aWBHEl5!nSvtOF z+pZBtO!O%I#N8Utu>-|U_EDehP_ojqr;aDZf+YEuH zE%3j^0lY11uytq@XHDk~GQ7AQa?|-Mb_t`HQ1!zw>mYMnmT0(iRQ>ko4CWXze#yUU zX&jceHS^UJ{*}4nmJ781D%-fcfBcCy8jF( z|7iIl+!*I>E>v#HKbZXGV`hMoa98u)+<~C2S13|LHB)(V=aP zP#qw-%pGmX!fuUn|08?f0T23|n=zRP23aLuuyppNG&tlNxd&We4A?$DcbGnYf<3>G zz3WVHBm9WsIRF;*@+H~J2iB91_hnc)C~`UaL4!KPMVk!4k|R(z%g^)o_+mabRbThI z$VrRYxjrqrY*XBQQC`&1Yqcjsm*g$II**Vyt;&t4h7n)NTNsv##-W)Qnsr?@aTeK{ z66g{OG()x6=BxtSDS1CQE*%+QbyE9c_%>rLJ!x_r`jUx2^I1>CN@O6oKW&`T4>ut@ zcn#&d?1+L(w@WG82sJ80(|~Kgb z&pCf;vcfZMk_U?QxStA{pXgm6(jBR7V=a1;KasRX5&UYzmGe_X4n<1nS#YH15pATF z3ZmcjMb!d^$fbFZcggHf)WMpIT0*X@o1cCo4IU+?{JM_*BOSUu{L7U8Y;}D@9 z!QlL#ZteF=hrlGWlQ(n_`nVEx;tb!2g6KF0W?e8-mJ%sv0XTk})kyEzrLVtj7-YYS z16NlHmx@YWrOOZnm}G2!2*vOdmE@3Q%hvgz*AEcTe(qxCEmJIXq_bUpBdV8j-WK(| z-f7__(oNZLYtA4soD!q|X1{nGo66_Hu5*dj3ZIAo`P$TiEpzCVJr)LAiY#*KUwMw& z_M~5k+xR2gc!58KMJzZGtsJlior?Iz>TS6^ET3b}nGR$@!g=}Vx2n9!+Z5YqwQRas zcWta?;$Y2&qKn)EjyjJIle9q)#=x-s-)wQWIpKp6oxncNjDZfhSU48&yhywSScE>(}7hg(0^R6zb7$d2vdlp(R`zQ!q@%}PN z-n!$Lkx2W57FrkE8cozTs6B--;fM7oV;dbcnmcd2rHn4>s>81xd7%EGSMruc^2UgQ z^V_cagq|PP{HLA18gyh(1-U7a36F~rM?}&lT9tH0JOo$py@^bZ$Gsb%HbMJ?iY_e` z#DPR=simvI=*ioBw)mQ3(e}$c8iG3qA1f1S(=oB-Oq&HC(-U>ysQLNRu)x!=r(*ar zU<+JxEaHBiZ*(;2eoc=oEvnhlCBb$y+-ets5LX z(p5>-BU&aG`rm8bR3rfS9slJHHxqWmYh6kk5A}>P5{1J{BZbs?>CZKSm!DPT_;!2c zUxVGH^8)>OZZ!J0t1`B0vY8H;m;V`%+g5J>Q5Csp+>qyG^{Fk*y<^Me&dsZH9Om8? zz;*J)Axt}@FR#|q<~WYb#BJ)&&-kA`W5Q-ysJQAMp7I8wl>uN&5+x;FSLk>s)FCBi z810j^FjBm`1_MeQxpkxX56512rm3cV?3DRS_5tI5vd6-m-)?2(EKG>bD?>@!>feR# zIW2-UWtaSg-ddL)YR|@yu16sCL6%J3&o8}#_6b^1(7~9dRcuUR1uRdI?AxgZKp}L3 zE@F=hFT5ga0!R%Uc~RK{*A-Xd9QN1uLT4Qvw&8|&_)PYOLRwj`ezABZA!MU|CQoT` z;nW1#O6wVWzC<~UGP$ss9vNIn%Y9^=e4`8-_}zBdbM=N#n9{+%V4NxAcer74;VtvF z1{LQ0?5t$7Rkzx&Wr_6m^)8O#=(Mp`k2I3okL}*Si2>Hy->Sb06-+pIN+vYuk4MZN z`mudz>2)j5*|vw`Y*39N5Tm7ZOufd5GfEciu|Edcf?+Di<3&z)kkrH0b1b7_mOGli zox2dv%;jp+fMW_s6+E=l8r};HD1O>%0*cuUP+mms^YbX;oo0eXCFO6NU8_c@nTSFa zd{vBJ@~`MlC!cTvgSm`y1PZ7>ioo)m$m6?hjUl1wlEQ2em~67RyS`JxDQrdK;1G2p z7}T5yJX|g3U@^=LySP(%*6}rnJVF>LHJu_>kCV>!Dw6nBNCA(Me*~9S* zzqKP9qbRgvHpSz<{8jbq+R1cmh+G2C5bZD&en=qZ%N=1qDPa^u9R@928n`7$Y zKEmL%L^3<7AjwGX42OU2+K&0xMA}e64Z75bd>Mrp8G~;oqx(?S>wEes--$bl>j*>EXNL zdG-_;HjeTO{=uO1NGTgfIhDS%c$@6l0sPcSo?{YK@y}!u6>Ft# zet7H@z_%tI!pEx%tHDm}IP%)F7dN>$<2SF=t{v z9PmPP*vrov0I;!!TovMqLYZqqs0F9d0266;qbj z?+`gdR?b6DPsf>S2GMmrQ`@`o44Dn#F!2}LqHSevzPwGLy5Jiv17vgcAGx(n;b+#I zV|}TR4vL+TNkYVX7+{#vd43&`#xuJPf4Hq;Q`!e`0m>7fCNXMK!Wx(=v6?93Z^+4; zg%(N~6=O$aWc6m)kz0?o8We5}lPeStH`H-%NC~Lf=K>6j|Nb zP&e1ev5uTP(@+nlKiyeDVu{G+C4>(D(tmK*sE}3SoCtRxCXjR*)?%~6uwu>q`vGFJ zX!sh&RFb3?kjZUjKR3By%jYfbrUyj6og<(CFO2qcOwD%Z=QPcr6&!K7MuimrwkTL|B-xe zI4fl-CehFyYIaBd4ptJE;s^s|*nQP>fQaKRh=)y=8>^9;D2#&`asAGULkQwyz?%&j zy4tB)5p`dw9w~>%e>h+MfRkk|w0}x) zm4j61DU8ucF)l0m2^ZojCtornwrV2Kr0}d(tTpIfhxIKkw;t%$O#vsKxq!l|Y#oh2 z&rV+uqzul+13{AvHKgq~*|>OVdVcs<_F}x_(ue=Hy6y2j|5otT^!#1$wFO{%4rqSd z{-^eG;0x^`mwFNg%#WBSO6g{DnsxSG!yZU#6dyES96icqYhtluWnfo@ zpG+;gj70Tcv|bZ_fhN%eHyvF>1#n#3>8>Cp725=*rgjLz-7I+|)T1bOj$B%wehCKx zFcb2a*QGPEN)0HMSLEy~X&d&n5v-nF5SXhR9fe~(+%BuW3SoBgyTrobb45dGj|*CT zUV(p`Ki+4!Z+FAQ!RZn#^RIiZ7~^d}65_tBUqYKo7x|>zidU8ub=FIf08R&qgF z=X}~zSOFW-%;PxBI8@I*9B#jimV&ez89n1vZiMx*NSE__ap!}7p$JS4_(vIBx{nzf z$fQC7Z$I!{&6amy#UaQBV4ZF&vJyH<>X6&|>JIFj^gb@1Wn99AwIX`P36?-9`vCrhjU|wUdK& zY2BIhrCvb%;u9$O(Y%9&vuUc>+bS6=nZKnHIqy;0(7zCFp&=tfLd0b?b@QSAg@VMy zncLz4hubNGElm;G0vV`DI-NK;wdlnZNpk=tiH!$us#2CEBiv+arByM`ta#?zpmRb) zQ|^((1D<+kekNf&diGQ zbMDG*1I>cSctf!3g6!Q5QumS=-42YKKjRV`NN|~Ok`36*&FKcgs z4`=l?FVen;R9J%hwr-H!(h2{CF2fRxH5tu%c`M*PYCl9`NaNOvSybOtAVB5!p(&w! znZPhwSS=buzVfj%WjrwlnQY_Uy~PjDN5l4y4;7+DJa z#JXz?!o#h`TG9)Qn&OHo z*IEEqwbeNz!=6E+MOrig9`fEhE{qs=1K}LE0WiaCH39wf(bC=SE{QylXGLchus^8q zS6!po85zBDury4pT_|v@K`@c|;&|}BXSD;#w`>{*v=dE(TpFlagD5_WEb%OG)5jWi zu4!QBVx@0vHxa4db+lC_kIVu@{&C?h#0u!r^AWw54EP}-h4hKLN^l_28dON00F7?` z#GJJ+?SXdGkuRNBedFR(I#ML{CP?6_x`V6ECPIP5(;h4uZa^nVN_hc`b5NCMyW4_zid_ zL8l#O3z*8~<3y%4N-@z5NNn3y1S>-=!==rY#K;(HgL*a&;fD!aM9v&Rb`keF(A=g0 zahAm6_GO1D?Kw)ACU&zNe%IJR5AJhL?FhTAbo#dXyN?TIBz9yyWTcUc^<32&V+t%Y%}<)vc+9FUF~ z!luU-?G7hPKL78kJTc;lNL>*w1%rUk6>=ZsIcLMV^zhj(O&nw}LG4wYNy$Db-*CDZ znbfb{f5#Q{$9SxzTD~fMfc2E-YTuS;%O-3eO(fl=DI5~TA=X2i_~uDuY&W*=r-JCj za#z)X0jdwm3M$gGnV1Er&|trk>~I^xz3cKJ>-Yx}Bwj3hp#OWm!#@q#4nM}x>mrFV zZ&$_JDPFXQ<>_}-(c_NsJk^BpEs46(kMTFs6w zj@eCXj-0%E3wusrYZ+&~18(JnKxq^(iWLE2%&WuDnQmgElM=-J6|S&K!Zt*PO|dTY zCpj4*Vs?!?XCWj2B|%dbi9(vscQ*h2PI4X+V}>7GfvwC!WmTm=0C-1;`DdP;dErlC z5l1t5UO(>5Zz~7h?AO$MzQ$zOBpDMgky12GUv08n372LG_}g)zwh|=rYNo!iNesoF z*^1nT+e360S~O~C>q&(scA5TYy*RU|L2K#Akzjc1Cp+W=WC!xT@HURP0&8@2`NbBL z$iG2=xuHG`f=zKHL`{{wZ**yuuJCCVn{JQ!o$Lz#2(NqVjM@#s?TwNVf_!FNNkE&L&4KW8>Z+fM5(UuYael>pLnhEgfQ zj|t?1(L2PBuhHDxSEfCsII!aV(paIgIXE^))Wp4XsI{fMl z6?OMB0aaR2`%-nvsZe$R+}PD9BnBTv!#MU~92H-uK83?B=3gh$uL*Qj)3X2zWXG0X zi4y34K2Tzt4F%t+4EbjL(#RPy-L?)J7IG8e06(bl|A^1c#o}F(O%g|nwuUT4NgDYD z);*?X$NGmL#$6xYC1-;{r586_^&C5Y$oTan0}8U!v-B~JLkQ`h zz!7!r+{e=Gk-9(AF$ZD6Pqy%>QK6DdfppIQ%Qr`6Vw%4Vrh zFarM$zaH)f1J1FVV@b`aAkWgKU&xxWshu{z`0_h^tvGT9-n)ffmI@Zlhde+Ru)u^s zrfbEHPO>L7S^wG`3Ra%-5q=FAf@MGzxeWAt^Z`&B*-h6KZTX=B&o~EYlKQ5mBBUKG zR!YaX)>$!EOn|Ef3zb-1-V|JjmpOAd?so@jA4h$f3~wrr$dd%Dc?!4Bx%y_VoYS~K zgM|g**wSjnCBY zzCRbTXtM{0>!J0eG>XfuOp)X{oX5}N{@HoANXGYF)A3WiQOdy zrBkaoJEyR%-lft(K6}Q-0dyQDrPP)rdOg^X;#C!ZkfLNDTS*FEwFQ6l_!dlj$995M z{mNWZsMgX^^K5>9M5Jyq){boy&z9Wyy-%>09kISnM50}n)H7m@G0p=nUC-@Ky_ZN~ z)Q}Z^+*G#X^5YD(4d4vm1#?i~Jfn~_Uu-U7Pz`=v`M4LlCS*dsBy=}q@V`I0M$uj{ z7$uIhllE4M8FBY9G_78RU<1|cWh0WV`(3IK4 z&JH&D+qQQf!5%Am=2gLBU=A!WRxWMacs=8T-T?5F+vpWN{8{^fl*j=m9}wZqTX<^UXy+rMd>R9_^_E| zEJsq#lQI~8obIw8(7f8e=opq71TgrvQF7^Wi9m@3xj^ z1c{C8zW+N@niTFc5<~u{q#4+rVJMCfbFo4E_>- z@yWYs5QEPr$XRhFx$+>-X%^<>d}QX&c(-7!sH6DLSxRU-2Kc;r>R|~~B9s6LVcxc@ z;Al+IE>3VZX%2BB%xJc9Wh*`_RkRb%hX70vnZz1Bt2MwfEau4gOv61qo2{5yY2sQO z&vDmtr4}1nARu<0TQW6nTH~O6Auf}vj7gj!s;Y2&+`4Bda6+z;-_>XWA`W+8!4AjO zm19KQ++8oyA4lG$UzE0QsrT2BqNrsTwy+Ksa0Rm`7!Mnz4;H(XnV@mEGiGUdJU_>6@wOYlXI!>)$D!iSwFSHTG z=s>U2e)Pdq`y|5JqFRVPw7gGpdf9J7f2Ec}WGfg#Wwp*MVZjSolm2C3<+A$BsVKnB z{&HhglJR;Ih(RuEi8K=eIwCas#<2x26k{_>W^4UPb>V&wsb77D^5s^MWXFN&N-@7o z%m-j6!ku=_sjnvB1C6H*R#~{NR;%;HP!N}8^jD*3*bV)yjd&p*gEga>i_z5dS>n7n!0tSbwBq0WB*v) z8Qd2dm?X}}p(P-OIc?480YP3A(A${ah0G0xDBvIwo2nO1r3 z?pW8-?EfwG3ru7gsqYLYHuM`OFT8jrY8(E4<_KMhWMJT&#Z!|jypgygeO$iSvNQQXUEC^Azmi<^cNP? z1&2-KN5)+pc-}Sf`O)cO{udeG;Nmgg`rxhQ9*aDQh`|T{Jy&va$fqb4sS8 ziIA?ylSU{LLBWe%3cBe_%RCpTIsKnC-ei3TOfes3mQ;|2Jwx#@=iBn~EYhP=w3&+# z2|uygMS`VF9WhzGxIeoh`vFBCQh(cRjlsa^ZkKto;QzP zV;o6aMr$x1!(m#-+YBdw{>6%$-a2@uoB0=KIJ-D-GRac*zl0Lr+pN8T*KJ=FB$45E z0^i$}>iDW>L6HL2@h!POMQua__2Z2vKTK=-of*={VT|aU8LIVt4fs|wxJfx-*|vsn zyhL$8g)4SFk?42`GNa@z)PvQ(OesuPVt?vV2eRSeIiR?sSan7LsKn0(yf_HqrGo+3 zHmh8EMzgBl0umV<|i}4%jjom0BiRVy;qVa&NBh~i} zg`I5AyD&%7-6jISXQ%`%;WPHdQp9q_v^!t3KgU_ zAyg^bO$DBP>e_w+c(TrkMeECrBQ4kCa*QXe@ve^X4t2o+z1ayfp?==OE*hlx-%(f! zVm{6ZG~eb$oG~gs%K{V4!D53>_M%9O;XsE@%*9qa%|*l(Ss|8kwAjm{ z;Ql7g)>8+#=Wz`pNJB3EB# zb7jA=V4_sqHLG^Xwgi&aRXE7?e6paEjlSgt(HtAad>feH3TNZ1gO>$(Qm8Vt_+Wg> zgr=mIcfrVux)ay~{Vzu|IyyF;BePW zu*APXdDx2oxO95Yj&#_Y{+ryoD>(cBY*>VW`xT<7jh#?C@~rMFkq_zHXkDX5GO|BT zn-H`_4zGC`IF@10l8j0L<$J&B-y60H83fZOy>z+fcQV?=_eJ`A=saq$AIqJYff(4* z0GmaD0xKwF`JZtiZIx%b0A)?6YV(hUKll}TzcL6Ec9}#6#P_TzOPeOEosP@nFGS&X zlth|XwWSAj9j{n(5HP3`J1hJN7s|=X>k~DVx2lz)c`1iFt{MX-&g+=0>`i$U@C)sh zxZaGJfTPq*8ZmW22E6CejKkGLV%=6d0RPhIzPO!~K8@lSQQ8-Z=Mo|c?K_y-0|6Rt2d)?Y2uvu!epYO7Uyh`2Oc)@;N5oq8kO}~cGeUs{$?BG&Gn=94TD{{c-o`Aw2`eKtm zG;#4*?yboI0krE=U1p`Brf-o_PKpi^-M8X%z}BX7_g!w-F{w)2W7gsfuB6d7z|fEX zc%KcNczZ<dRLORdcGkpGmu3tjo_?aN+QBtD(gUx3|RsK(C#G1i#? zXccsD;{kvcUpHfDr;>R!BiPPxasHYoWH#R~(NP*^w7|ZAklGpT5XeY#^I01tovP%I z4nWqf8`L1ruj>+9vshCts|t;+CPR)GF5Tyq+I}n8#XsAhWus><50U$tl1tT#xnRa< zagdj-gSZ23Zdmt1_kfqifEMFVI0MV{WK+x9oXO6W$%N%5J{iBlJK9wnWgrFLfu!|z zV@Ho-1Ndds3&FnKluwXHHK`3A)p_5{aXQM`x&`E(ULeV&K&Ix!m-!&&wMr~}-M{GT zKq%--439~G>zmDDIQcq%n;6!-l%Gm`>BnmScAr8783ED93*dNY8YW6d(uI>wh>Z|K zIgn-_uv)p};?0F>C73f$9p*pkr!*w$#~Bj?`G~zVUMes^NH>sjZfbm@ZmBmNX@=9m z=rZO?&@$aQe`KBDo>vmg0MvAUy3Gg=AK5Q3l5{soILM>GcE`fYx==6<4OJkk;!nf0 zBj=)(QKDdj0lK%RASFnQ<%ja#1YkW-IixUxgk{qqlS0M$oxr`2G6|MVqbZ zblg;=U|jnnt6b$Ofmf*8NezzzGy4y|#29#m+GSI~sTu3)SiODK{|CO>sm5YEp_aWk z-n-(EtT4w=s=<<35E5OgdZcg@q!vL^S(VFfo0s9oD>=cE;S6zdS9~-5NGT<~eWapg zzpw*%%e}Nj({V?ZEg~^)?#siEthNs>;Fv!Y5Pnqg&OO&I)RQ7n7^PNcJVc6}lN1clz!#%}w)_+P5XP_${~CC4#~I zd}Q-LkC{H-QeyN(Gd;A#e;&SUgtFscKi~x1IZ#G^(?*bp@RE+!HeAX;Ohs+RFAQ-G zr6Wqsz*KdS!HVM`u(k?}RuL#omtjiqabEc@P4o@Jl~v4pIY%?eT)h|q{p*O#@6jM+ z_&*_J^t&6R)+?Z>-d{!-e*oXcyIn*NX%DQT1>pqKB^+e`7YW#};_(!{Ze+Of^WqLWFH8(e-%r7Qi2qI{D@85EuT+7W z7R4C8T7N3k_*azduN#=SIlD|3;|`oax-n{=K1>0#4i4uM2V+JVb>bAif$6stqCvDY z73o|4>BmNk{6j(M9ru4f0+z`^z@-QweIg=CH5TGei2e%T8%!jYCWnz-t#MH&yINc_9xzov#}?B-%JsTKNkiF|MrAlsCL9jV-71H{wkGfvd&k{umuhraJcuoLAGu@ z(}mz3vwXuN?c?UUn$IlkMd#A%#k(h>JOj1?DY5suIy^Yk<5C7~XS?g);0Iwt7l)kz z(y?T!E9#|bej}sl@zQFM<(`Px0wY{Uh02eelat$g4@oeho3)V`C{GvswTa}gr^0ji z9UFI=mf%=pBMlevngO>6z;>*~yd@f@FQdSkUT0pFuzUfW3aNYV`ZCgW=TtsH+M$kF zW-Bx77M!FRJldY9m16h_1M}E4oi<*|JpZYN&H*{|N^5;^vKasrPkd@IR{ zaT_!woa;n5*uos)7-Q8GHqJ{H!%;Wr>HjFmfc`1vDVqzlvzLZPoMNWX@2aA z;B4xnTS&juS{DG29(fOSB+8I@_q>rQnI<&g|K5K6i(en6>4N{YB54ydk|J6VIWcEk zINM8x(n!oXlPgKmCQNL$f;}by`g`$}QyB+)_%=^Y48K^gzdBDn;i=g->@dbFTca%{ zs>@N$(B$7Y;rBeu?Tt<75|lY)6^l!Yp)vUrJH3=8lyG{01n;zZ_%k)hKB`Qke2R3H z$I{*YYcDcSRrM~B`O1C4_}{g{{XS)fba<8_^J!y|uG_RP*)CR|7R}2V(Dk6}! zCQhBoRDrP6SM?`ubGwwfi#fs1^i1S_ia-X|`YMCC;V*5VSZdH(B)Hw$n%gU4xX^}X z-i4G9TF45R=qtp7+{3COb@<~;_jNrYs%kodYpoV2d%R zJ^=d%RYh!8v_%>f>Rp9?`J$aB2x6||0b39o<=$--Hz%g=pz^njlyT^`UUz2Z*`*pz zwz!};61r7y=6R(6d|0}&_o4te?9I-E$X?igY7mg&88Q9PQR5P?62L0mZ3Im=V?|>u z`b|CRuXct|VXU6~0L@hD#z?p5fQ^2tikXF0F5~+5eG~;v)ogZ>1ft4-e!89R?okR7 zD2`=U$Z3j?HMXT>enJG*AEF1#4tnCEr(nXZKN%EA$<CwY3l7x{Dl zOA!O)TS{^jVD6d!lPvZi-~G)ZqWCJZw=slB>dWg2VK}91%FB}z&Dlyh#=cuuV9bQb z!ueg@SKth_1k;LB5)`3Lra;T_)*B&T1>0UV)6Yed>HX-mAWrWt(Kw|wXycijz)eH@ zH}`R>cFbJ=Xn~6V*Re^%_dekh%QKh0{^TrxXCh7~!#XBZN+TFZg_oSW{9nd9B&?11 zYrtMNAkg<4OlKZ=&LGmEY6fFVe{OK|pWB`-u8`sB7Inr+c|q?v!Ni=hBcpDLgXfYq zWz1%fDAmia2Vzo|+4!{duD}gL{GYWsn8x?>>$t*KSHiR8;ew+L_RvpRJde@BXGu-~ zd{5cu4^&C5Tye#~Uid2xMo&iUlCHb{%B>7AZl{!7JG=1Bc%8FrpKe;je;$fNg;w8Y z)Jv4aS&<(qy7oe>uZ)&7{btxQnew#6gZ2L6J@_;eeSn;?r=nc7Y1?NrH(^hx41cv2ad6htri6bSkp^}g#I?lR8N9KtK7m{7N7WyGVm=% zj#hTPtT#gQmu%iZDoc$MRHkE|s%K-8070ht9=G6_=pKgut4`ccH^`BcYoe&8sFTm* zcen~{CkV8VLP(5)#%SL~&2vC-JSbKa9ntz<4_gcnwcFIV{EbE8RxWY(IY-t0#*)qA zMg9(pk`dxEfsdY1GIgSehs#m{#>{(cO6*$Ta^Rc{ncQM&s?VeXWK6%cn$19`i z!eHGn34Y{{$LZ+-v;sP3HF$SlZ$YB=lZUS%wq3>2b{=e|O;1$R{seTK9*SzcKUAjo z0MCE3Cv6Klm~tkq0uM5vYG=htgX(N|c|0uwV5-H4F(6%r{~%QnY;qZMR>fR~p^_8j zRMJC$O@(4e-^=<@Qex*z^JOengD;AgS30(nwB`bj1%1d|NlT|yFl@1p=*SP*rL0e4 z$uP^AD4aj)oS~BFV_;2E zylgYjP+&kbCkQaeHC#~#s?1N5{qfk-R5O@Wa!SuMR?(1U`_3TTdczam1${=T>cMpBk5_9{jc zK!BoBuAO?LY|zl>5m>I2OWT^zV9IR!hhy}rA@2E;3-@DMTl|`|xE`nc1}S(m zEsOLRP)rxuascWA_=l);YDU8K`igt}cg8p#6J^2JT32>(nu=KHcD#o5B9dm#l=Tvq z{b9N7%VJMZ;mF_EmpuVWTW^YY3oju-mn~&N`G+R^m%g}76jqn;D{+>x>@{A@)plc5 zGnAJx!?^#xU>E4wlKff(;>;2PKB?D#63@PE zvq1ZKuE_5A?GJ1McQlX9*oye_gf=bmE7$JH0fE`LQ`13`Zevn;s)YeeIoV*%9;4iP zllH`lG|6QcAYVprv6F~aU%G$AJbW$U%ZS#+!b>7jVt)e*LwC3{Y1U5Y_KP}(#L;ub z**PUu1XPe&caL7l@k1BndqLKFqsuDKUCstqhideV&qhE>Lb3jSvk=+J8>$TrUp90o z93m?;CAF}+OiygySOhLwboC{VKabPkv1;%dx6+b&k2h(z|7xhw4vkW_PBGX+%>VDrd z0uViz45*eUJI~C}P*iIa@%HifScr=(Wf!@lQo5_?ANS^GmyHUHtsLr&;dL9A@O_Wvf_iXV zgdC~nOYh-{y5sz1ck5>p$YkC$Qx>I-?SE}hQq=>!E8itmB^DwH+c1WpW8G+V$SB3w z#ZZjRLI&CidysPlIMHG-w*RVCXQgN;1R5vW@BNfC!v{~Dgs;ARbrXstE{FrD5xklb zPL|~zZjJa;?ta4z6YN`}AexZ%=7{l)?nYlhNAZ64*LeD{L!BV_wrlCbZTUd_*z@9B zSM>fB)s$X$+oLwSN8Bu|2REn>ADDPn@Ay5477KLOaL}>cumo<9oZLFR&|})r8%P4mzeZZsg|+@sG(je%Gs- za>H}~l{*tKY_M@}*(d>cD*GgFVF-uZIw&DSDQHX(CG8+?NHNe`)-WaN|L$9aZd+Y~ zDIDHOJBo%b8w|I1-G>0)f^1eXOEzq4j?ES|RF)r6iaXhm0@tq=rl6yH-vn}=cXWtt2{Me>XZkay#8BDh+B}v6*5pL_(JVIGM#;3g~WFtRmoXL`tR)i0q z8r#3Gum!tFo`nby%0T9rMaYp$aB87G<%E?^?E@HN!e#64!oNE2v^MH0+pQ9g4R0xC zZ5*HA{6+QU&c1eD5ZE1W9ya6m+RvF}u=e!R;#(4jZ9XH;g}v7?R@|~j;pmF!5?0{N zbq*(TzBJ2&zOrcOCdN^*^8r)Eg4y+>{a~tkL)6`s;*A0LbwBBekF1HYxq{S5B{ssK z&k2UuUuIVhM3YD78FGzX%ng5CI#DZh>e@%A2|#XeSm&v1hTJdeOxD!ITx=1`Q6fJ~ zRvmUl`-iXb{8wb5r88OOMkhEf06agGyDDQ#I1A ze}pB;`@S{x6xS!^?zRRQ)Y+p|j3Zy}Q^FIzPL4_QGW$hmHpg*kcAXs-Lf3B11)4TB z>+(|`ru`v_$Z4}-GE8bRG}W$J8xfUS9x13~iZ}Kg&tHAyw2XGtM;zU4XNkDjwPPcR_Wg0{_oa1)jTSwbOkgC+aGw(w#R{L6 zJD@b~BSrApo#oXd-$&?DtCK}vZ0O4o2mF@=6&O*I7)ttBvoj-gN09UkB55Us6)jPI zcZZQz;@|*|otFu=esdwd3T}_yq{E%Qb}yoV-CuBDGlb)zjS_DUZ1tr) zch*~Sn*}Fm2X)-D#R6>m(lTh(2t~MImWEpc0Z@-I{Pm3%HydMs3jyLUFPsE0DsR`U z!ayNT_on}xWK+u{E^MiDCV~xrS~ZK#{-B;#8$+3NydoCN zU^`1IL3@HD-)>gE?;IYhTZad?(_f!l)kD>A*rlurK~Dii(u8XthPtAObiq*C3?VLf0KX}{Xkd!P(5d$%+GM3)?~(MV z1Nw}^*=0C9*|z)^GYKmfN2oOkZS@J_Mh=HoSI@O(Pmof#RUoS*mSzFBmKs1&{sr95 zu62+zdh>{I-CtmC^ustKtFS7=8R0xJ@W) zLMl=Ab8WMLoTse`c2O=>KSvYNDW4*Y=^iu5jeoPWX!?b&T{3bE@81l8k27j*;$rm} ztvRHkCN`@mIcgVxqlY(-GJ$N8nE^3fV7UUFOSKBbK!-pN&OJI;o>F=d zX^**RbkrN^+e~?~QWpds`&zLupF}$TZIk&K62#B8*(|(w@}A0G|6^GI4c%%1c5Zpd zR&Cij*>Y97p$W>~5yf#fcGqa!%!P3?NWVWKg74rYz4I!OcQ3(*sY-u^408fZ=`!rk zVV@;oHm2=Y|B1k*F0yiJqJq! zX&B44vPEX!%@-)Vjf>i!_LaGFlUTXaJ{;(ls1Cyoe{l*E<#1H&udKR*TQ;F-pd!>o`ZUV}cS z<;o0)1gFA#35Ny-4@I~vFh4mPTz)t|uMLN=b;_|t*I*uwYj;n>#Aw42A~o6Vhr;a+ z$NWMBY&y2<8#6j_Rztaua=7cW)fW=8o4*@T*_>w+yR*1`AI|d__duR)Jp?I1QCYQp zn_K->j$jE@{nSw#?!Yo4SN-S0jgNTO2V#zH>|DBiVqi5tHaQ2YrouXI`$`Y4@W*j< z1^DvuiS;}Os_3r2-)z2!cE$|hH0&|1ip^L5^{c_jM+m9Ubn$B#vGb4%V?Pg}CXuWK zC&C|O2t2kEY71miolJKN>BuAXWI2Tb?+O}^1GfNX@idz&g$o_JY$9;q6W;PO2UOhPFCZOmKL-L18*51~ z5sUjohm5OPCLt!E(#)ja=adeAOj$j8P#nIEJ_byVZ`gl*kqNm-ak?eg8uMl6wJoxv z(&UM5NW7av4WKb91pCGzh}A*99kqtT&1YF=os-H9vgH**N(wcMf|_^?*iJ$Et&*2dP&}E|k}D@f-!)4?hca2Zfh~0KFR>{5@M;yjLqfK~zfh zBGAfwM4>UtVY(Ou;1EUa(nXNgpGB(U)Rj9x)8TzV@OQEb$n4?fiKd?E*}4hJH~)nH z00&iQJr8puapZMG#(*IIZck>A;o{A2v9^Qu-dN1j}M%K z0FKrca-GGNXs!(#USEeK=jG=(g$z&#d2v_^7M?7D_*EfCjDd z-D+{*>>1bqWpV#sp92nS!KPgPTeF9#z!IB0Or!VVJKa>*$iqpi0WZ?$P+W`Hf3-=E z81rwi!VEXObPTw3o~2VCZVbY07Ied_M`d~6v0 z+|+xS9ihTE=+-L{`Tm#3&JtjoCkMup3pfALh8kmjr$diw@os;CH=ldkR^&tK`vJL{ zA^63A%>6G`yc6=PHUhmbeIU*IM%^;NE^rqw0C7Tyh&khLgloDtqglrcq(^p5DQ%Sy z-40krWMZ_s>qj+koa0-TeSkp@ZITN~IV5c-y1<75kX2-xkuG20LOMm4!`>FFC@-R( z+oR;yp5*B|9Z*3bGs6_drlC@%s(`Num)ZCK->cN|TJ5^lAOLcDsdmQ`khv3&=oLLc zu8DV4l14?v-&%O~uSmbuDd4eHM-AlC2GNiTWyqGNa=?nsq{3|6FVJ94VxCVax}fng z$UbFZYuRU_V9|CY=xXmtqJYtX_`7H{usnQC$!nRCCC>0EwZ$Z)sRu3rw4TZb=NS`+-vsjD=$vq__l$1xP}Y$5%#I(sdx z5%omO?s?L41Hai;w1kivEAUZWTsS2P%yYT^^E2UDNvoZU_v18| zn-YUU5aoG%=+RCXP-lFqV$zEeBP*5sLm?ES+=7Z0*)+wr@P^)Bx;Ac$+~1!H@4L#IZ{^wwG$@Xf|J%al8(7R4Su zLc-z4|LUzsl5f9mj)_cACcG9Y8DC++%>^ndmD9ns6!idA0VUi7PdfiN^n+y)uu85g zQBPTV5fb#=rW{%0AudbM^Yd5`Jqy9aMRVsG@GXJ_rcAgYzM(AGy>CgX-LDd11^U^i z31^Z_%G>|@Py=&zIoHF;Cp=v1K>W&mMfN2~{c=#if+HVhY-U(`1C+;%Vf3Tkl!*n>KN^tYy(DCiyKdZ0^!+$+o|=t8)YbOJqlao7Y+wY<%#z-H>eT8=q+r<691WK@ZQP zM&V?3?;Z=c{~Gr=c3m=DAXd(et5;z+X`BvsDNzBPWFK$Yot(ngT%_2SN*@y}?{>bY z@t^r8Id$=o52zC@57O$ZEbnd(oY@0H8?b*#mpGz#b=|#;GnV9&-u1UeXpl>O{ym|N z@7i?#QW-APL@nKVD5Voxg6tzL=XTbtplf;Jrah*1M23Y}C?=nWQ+lUN6lfa)H<_x_ ztuO$xCc$+LG?gf>5%T>u=^s*ZO47p-IFE48I>KF?FaZ%8gFSqNkT!6i^#f!8nR<=( z<{YpNX%hSiDhGzt9I%y0erogXp*-Ss3|pLH^wU zDl(sgPgNLgrIX&3DW}UkUA{ZQTnnxQz-}yp^MEwEQNxZzENXFRDG8<)OIT0QfK}&h zb#8=T%>yQlYXS|@&cdyHd4?KCH#Yj_l!F`T5!RkVq(&4-6uv>GHT)hjwKvHJj zkmu+$MEnKHr~RIhKA5nb-P5s3`4VVHDBUJegb>;nY=?SphW?WykC2T};z`kfnjNu^ zm=mqFQli!O-Wu{pC2PLKxdilAgUW`_2ALrm>O=Ko)gwQ|Vcc*phXE-$8Wj`KF3vkBA4{s9hXSbn=sAM*v$!d(>p={t! z?*2BqsuM-l&O9thE={>8p5P~|`*y|_(Ux!fRnNor?rlX|!@Do<;s3F87HoAj zO|!-!!GpVnKp?ogyF+kyg1f`Q-4h_VySux4aCdjt4V%OBp6@5DYu3#4RM%ZC?er53 z#FRF*a>!~&XYCbwO6Jswo8CsajM{?yKXEqNFCxJ~7Dv&cyO6PzOW$}~C&!Th4c@*F z-htAoSH7cq#WZNcd79)LICixB;rYGWx=dh$pA&;H5D|f{RYq4rSZ#4?BN@(Btn{Tc z?}hio+~VhXb+{qZaEroNTa|0VG?^ib3dLl0&AjhP!Re7#uj628&xauE^!zWGpMO&d z_r2MWWbG*3@QrMD0ZF6c$-Lu|+=RO5Y~|p`pN>5k$~|fbDIPi=0ITZF)2|}v(E*1y z%o4c>YI0i#(rA8oC9Nx61L{?Dx&M(>)$h#04HXAV3e$z+n#H{EAP6a4nt{0T6C__K zesFvQ;a0m5`}eFW0RgWE?L>3xs4;f`8ljQeW!6MtzHpBQ36g2-%!dI~K0;s{nib4& zljS>=6_e$8LPGEzSVV-Ikxz&^6wLE~ZGBnbU>uM0#Xaf?3#(Q%jjd77q)I|{nWB$HQa6DNlF&w_($LLMqMpHvDFad%F_WiRJOOa zO^5`f5cfF-ks~{j8%1U!7pzwI*sI;DHnLkV z`fB>dl%3q3=ULSclP{sePTld=ob_L>^I^$ZL;0a`3tA>|&&W8we$b^+>Sn(=o(gE~gW|J5)UD{=A(1?uNOqY!0j5 zM)ex%8LFfMwy-yl2Zfrf4)q}T7Evb2m`CGEltlkLf6m-ahgb@IoG7lHULgPN?K)rN z@1tIjh3-l1EO<=zs6wv|VbX83X*`bO^t4PAg7Z~|@ho6hY&CK`C$77FY)B=R)Ij5| zqzd0Oh;nxdGh(e~D^7h@vmm0^JiZQpw>}K?P;Mb|5Mr-R?W^6#q`qc|HUT+s~=v1|NGwkgr-~O^GdN{a9fMpb&xY zTv>zq;2-XB4&!$2oDr7uL%FE64<{Y6YtO z?(2m`1}DnQ;p3mDtac)qo_J-Z9FvzWn&;VMuhwTUYCa#;O=OV1BYq zu|obNnw1-HX4WPWAp9BMkA!rfjTEQLfo16XT45Ja)Oj;C^s%?CJO=WTtBr%WP@m7( z19fS4R6+(Ps?`b0U~=Z8(OVbn1N&)^4&knct=D^7Ch%=BZJO@~5nzUtR2y`8bZ3>2 zElyNH%j`R$@tr4G5Se~gg+$zd#n1$zJpPF?Gw!ROD<@6tx#j=lWcQkYy7csZ4cx@;jDc_7 z`#o_h<_~m_qH%cS-aM`7ry0yusFTIrQ>a{ys=v_&;c|~dttvo!l33pYsbWbV&S?=n zZ_W=r@zHUcMB|z=WJ$3QJ;I`ZjKaa_OKyyOkLs=Au1tZv=1`F#K4+;u&KyH?P0VbF z5BmkfvAoh?g%w*%t%N1)K@v5@Lon$i%&oq-pAw=rsW$npJ@Alb26Ht)teyiFcJjlZ zmT(C#w=7h)*)|OjVMqp`_f4ia(lRn)AE`Y4KN`c-!foK4m4MMx^F0-1w6jCjaB?l!*u!Zou81^V1Fp{E}b3G}VufR@P==Q8u zXy0XpN0^)26xwN1kd0Nz3n_w!6f!V%v8IuMp^9f6&5-r^+0sm5glhDeu_-0rTl4qB>+e-Q zKHj7^G5TKW-ry!5n|3N7qu))V>zh8*{C55(+n!FS`INn`Ys|232;ch&6)%Og)l#d( zDr$R{V2xL*X1A5zLqGi7!$-GYZQv=lmbJOB+ z(q8PlJs=(o*o(PJ`@G$94PVuPLwU`{$;xRoBGHz(#Ug7D(e82`k#s z8xLtj6}2`l6s(+oOuwuk+d58dS3;lKwq3C1`d)na|M5x=*ZK1Pp9fxtrC!K8busQM z;D|s5wFVpVbaWiJ+k`ia#h+<}#If#~0be;9NXn=RS zj10yBjWz_}ie>F17R7xN{fDRSKiq@iGI^7cPa7Uu5k6ETTrOGKgQN<;3-Zw(QO5qr z>IBc2^1s|hek`=W&EA;a^zb?j<4;Zidr(n17T0KnS=tJTe6--X%fgyq8f~n6TV;3O z`SVz#MT#SPlo|VPU8Xh6#q6|kp^x@xLd4bb1%vqB_^b#E1!m?l*CkpfUbt)DKaumg z6Db)99qX~-ZvB*t3Y_p~+qloZ`3W!MnMhgT$&_ek{WID!(Ej;a9@861US(T=^UxCj zo@M^Hl}UUTIR>U)Zx|e*u8U@~AKQ<{pFdxgoJwnLbl!WI`9R-`cmFaV5Sz=|C)`@A zUsqr1+235$8Ql5rXoB>%eJ3Dq-K}Q~i`;FDEtB~2E1e+MZZrLq%)cU#rNdX%l1&Du zAjdx$@nRokafYQg%5rO4xD!zO!(1VZKpG_5m(>Y%$)y&3uJz(GUnWM!F^ZVg(S@NE zQ^>YHEP^6!fZp=s{=D_1N?^L)mBi7?@jr4g9f>FW^beh|3?eh8VK&Vf%iqixNP;9f z;W{l4hjdjzH;-- zVv%QQ0sObIQjcS~H-ND*V{LG5Ru`3*u?j&SKhycPwv!Ge&K5#OAt>%;v<qcUI?0BZ&LugK9mUtV=s-Hy2d@3~@!u^y?YsU> zeboCqxa$4#T36s&-NrVB3hRP+U?2Q&3R8;L3UaOPsQjA*57^1VE0pG?g>Dkg=J1Vdc95#&oS66#|kA2^s`ef^5^dbBS;aV0q(dM;nUYL=_u$y@!#^^TG_yaW! zq~z9Xto^q&>P{(FD0$;D-SFuJJFQ2TC+Xs!Y_TJaKNI{VLBS}y(b{Zg(V{Gqi@}vy zvlB@m{tIUh{IJza*Hd6EZ>&C^%kt;T&|MB)OZeXlsuve&!!I5YdQQz9f>aEmCD%IS zo9`lC*`1Ov^o>Z8KjUyfbz?FREXtBD;vx}2%F_(zG&G5e4ZCO=7FO%|RaSwM(EEK4 z=4Y0r=s5wIt79sd6>R>;x% zs`UBzqy1RYzSR@DbB)u*y73UBKTo4LH`*#Bk;E2^<-!<(EG2JylxC>g9~cJBo==(9 z`z6KvblbV5?^`qzC#klHkX1${$IQ&9m37jBS?hW-%>dsaZtXpsRqrPLMo^wl9W~o=JAq!BEwo|ckl zBgcord#XI$D{ISAG)@(082YPGgDkN0ft&Np`8`=`fJXnKlO_O5noE1k zR=8cH(e~5Us<#1-DLUI=7_zp*&`>1i++ayHXh@dVMfvv(gMZsO3$i)%LE{CS*xy|nQxL4C7K81Fb2U(wUE1FcR%3qT1t>Hl%R3_ z`%ama{=hlX@aRtiCiVS!feJP$^zS~xdPM6i7{T=!!2+8BFz29bm%`jl^QWfB+KTo z#IGnn<84O$AyM%)%wFZM>?^*lffxUu!=s(N1$I`t5Qc-iVrSZ!`W5T0-)S{b%xvJ| zI!W(SAqjdP=2x6rV9G1pgLyT~&W31|Z`C+V#bYE7an-G2z(Z9#k?1#1XVEfjYTHY? zSw#jG{N$}=1(B6Lp`*-yhp(K0pEzy`Vy!W1L%InxtvreeVxDNvm=FYnZ5$e^)dWpm zR^#T#vF&|k1I3R{XIV%Bst{3mf0~Zw5@(vZJCf3jZk!R|3dq7oP)zP}-4IO0fDJn! zlYNrel7`%r{ur62x48A=byN-IkOAcf#KdMK`(aEba>sL<}JUPL)TjKMTYPa6Ca% zVihJfx~5J9c#q*X(aA z4#4LlMXxGn2cijuj&&tK57$3rvQceeHML?pbj|O7=WxJ`?<;|UL(?w;Kd%pTI*yia z^zu)8u%FgZ7YZ_yqlZh@AC^CcDT(~OkW?R3-&{6)(CXs}e52r#XgvArJsxO}?LN%j zc#1#&tzLhX8_hop`)5~nc<~$IMj8sRk+G>K&B;AmS+A|D;T z>!crf-Fo*!4Iw+f6Q}?>S}8TNRZZT{x*&HmwapK3qc!eiqaCUo;N}*4s<{IYrUzS{ zJ#yz6BAhmZ$5G!K5vy)elTsne8}a9}qFy}l-`}OYUrzbyGh<#$x?Z{l9$)wLFL^PY zdKZ$S?DL5C5@{?@Ryw~ax*ZWkZJ2+KxR_GR%a%wPKHjS|PJ6G!MH+tF`%jAYqH~px z5L_RsHr93Eu)UVHX3)=tI{{XP!4a|9vx_x`NqR;1#)&IYfW+~y^bouY{-ncbel_Gb zPV1U5jA%FIG_t4|8j1j&Q1p)?tMD(NCD$a~`jAdH2%yOr(?bVH=ziNuK10x=_Vv^i^JKYaA!SkE=A4)XCo(lsoago|f)&?oX zEZ%!W4;ekoWRMM163BGymPJVQ?$XrXnc1Kl8 zXR9DWDnlOWkfqp)xusY~7ChK=-okBjdZwt1>iKxR(C>XQb&t0ibnXeB6$x(0x{IW> z5q023qxWBD-Ax(^<$^|9XB34|Q|&U$NJyhkjjgR#q;^m8+x)#S8% zscW()5(mJHyPiwLzUrC=eF)lrwh?XGTE;RZO6B${3-TUw1d?I*8WPzJf+2>2B6Yf1 zI#59G5C5Zh@3u<5R&&!uwH|W4o)ErgV2&PP_D2k#BhMuM5Nj(+eL0!4Xt~#PD^Q5n zX8jj#I6FjE*Q4B=a$zI*$(FqQ;*Y9VmS?*>ASdU;F6_IwLf!1QR(TKV02;OaEkdXy zyw^35WS-p1{oN!11!fW1y$6P3Z2f1hc)U@EB?6M`-UmOun!x%6`=84xMQ`!Tw-d%Z zi5l@MrrLY8!nEBRchYFvr$@2p39j#=>o?*=>IlQ>oNw>cEx zEADM}Q;PZALxGmQzhwzOCW;cMKrSYA!|CV)t-7!3wVLN}ZF}LTE2Mb2>V|621Sx;c+1bkzyuqgI98AX6JP6`l4IJENmD$aF0~#U-2bltziUKqZLj0eNDq@x80LH__T-z6-)pe;tUW79Q@ur9;ST1e7|_72VYlp zRbc{IGfEm=c&r4kRdlzHtm|&J3?~j1heB^gI?;K zF8^!FkxdowKB#8V0kSy#_mBkBoQ0wHs2UHF>Tus(Bjusd(_Ih<-~=6DX?&~)t@5|K z9E$z)`X_U?S+{g4p%VAfaP*(_M$N_|fuJq(Vl7FyM>bOMZqS?PMnBz^HAFIcRY!P#c^HKr;5$XJPtKTzsHvE1XrF}r{^O)zaPy9 zR^P9hbid!n0V4eF9?ujE(aF58xlf61T~2z{`x%5jCNH1);*D4i*is=r4esHKZ>y2) zGk5-Uwf8zo()wXvSd;i2oi|zv_s%*-h*@pdC+wCT;b&@P_o&TS^#L`i&}3e7hBTwJ^|5PuaCf=+00B4OueMrfs9f^QIafee&fXldSm(i+k7U0+zyJiD|Ii4 zwYZNgo5SZ%W%h^9K_ougk&R65!(>yzI#1Aj$1KA+-2A#=uIu%==mYOB zovI-o@Q4V!f2}@X#|a|H3;a9RINdGp+TQT;>y93CcBm;<4*S%YK(0PKn@h)s|LDYZ zs7?+s(@g;9K(ENEHAjxxsd$Qy1XO?g$>()@KHVr3!jW6!AVAlRrKJml_fx}tL-0`}x^1RLrEg%j)-tW73)B}toT1_fMW#G()lWEk0U_r&%IWh~$wY|l zV7>Ol0u|oZg*+={8!bE@UK-JRXgyXev8n!C%-i_y{3Gc|kX=$z9yOdxyTY1gys4lP#}&6UpxBNe(!G z*j|`!PI4!`Vbx2FJuHIM9ae!ozvpy6x!p_%(o9qc+7D_4pN2j}JGh$Ty6FAim-|15 zsI6zSQ@?o))eZkl44LhX`LOK`G{ca8=d&lLwe5IT|CslngBZJlE&r|Zu=>o!=7*-C zw2TNA(f)VQe>~x@7+DWqJ9KtW=hx2r!25GcR#=noCI`zn7FB2+Umv3nwKve2C-T+J zbkY0R9xb_0y5n_$|8z{Q(Ftzxv4sC;syO)By4SOYD(JwKvZh&+IZospeOck_pGHP_J_m}=iH z5GtKu=#^p^qP2U5dV*yf3t8@UhNv=h#S)c(IbiJ5o!duoR@J$s>%EGfIxu!N)kvuz z@p9y2uP zbRbPIKkdG5;P1Om6+n!?s-^%eL6t7B!j)L|GX}=^9m`g?2A`xNB*~SJ7P*E;t zVa=l0R5gko=RV~$%^W~eNfE&roGov*OCM$*J(57o)E}0ZuQP)jBUx&>JPq{glf8ym zH7rWVBO*`Yxy#4uh{+9(T3g~2e$8l$um<7Iv~Pr*oKvt>z)^g69#hKC2wY4=6? z;PeE6PpdC$FPAP=?l;hv=^tg7z|B%J@U15K71_iZ3E6JPDLP?CREg}BuC%ZgdW>MO z--xGjDM85mMl0m-9Nj=>zj+ADM!o!`nB{Zy;5m&Ek#SbncO$^1{GZHFuX6v2^JVPx z%0CxUS#vkXMpyTg(?9kFEPUKsCqAbn{9~>i3MSrQb!YB9@P9Wn6CTX!05v`7-BsH6 z7KlF5>$QtYT2fN8%uU4)2mQH1{U&9`=jm=+!>AnZUXP-MABsl@)SqW;`e*t2?ykho zoUxue5SLi_;sJH;ySR;>@aUDmC5Cv+C@jh1@0k1iiuij}ei4rfZ+X`^Zr!__ohFB288#l2!5;F-IREwOx;Ri;h&-s(lj~xbmcq z0YTHfH~zM>LMMWI#y8T&hPaqX2kk5+V<0D1#P3I9$7n$!h zkpi832(WgnQ8n(H3qkAwvqlLrO}t*KpVu~?9qt#vntw4674uwvjq_1UpY7RlI^?NY z{mQ$4Px7*@(3FPKB5{+j2`a%yeG0UHDPAE&*yDW8fu12{k z@Xd;6AT9)2kV0ubYz-}yi;8v1F&pb@*an5EK!^6UnVCv&o{l;51hi~mP)$|fekd~D z(JpL$seD@_qG^*WBOc@Is*z1=K>PR^dL~`mXpu-+9wyZ~UJdf^zUukb_{!iNyAP=|0>5 zMO881XZ(I^xOViTjt#>Wh`WPhelOD?ACArCLsf4`&atVLh`izRu?U8Q5SNnZU0!e< zwZ2H7RfZ~SIz!WzQH6YhoI;}&DDgeRkXY}M?ZoK~Q>77i{GqY(EpNKgG=8!rcJdo{ z7{j0C{N5=X-HI-*@VNT0bQElpOB|MCAVqM>5R3A};LY*o$;3yNyoss`m=B#orRZIF z&=GR3nR2lhEzguYSe3N~*hz>|auSuA zXNG>!n?Ac6SOpm-vEzKRkgH?z2=4YESn66nh-#4a9r>WZU5Vx@xAGIrKbqbEY@?%w zn)#Ccv$g;SxSQ&&k`~$h{ifl4(XIax+}Aa)8WHS=KRAQVFD&k5xDg^j@erhmd@R~= z5}$E#`MXiiU7+60b%_vxFWK`4WA2-ovS)G_F$dZL*+tdP9Y&Fz zT5;<;m7uwZO|&GL6yZk!f1Ln+$#~y0L|0J@+V^26<)j7%Z=LIV`8gIX{LKhaZ|AqT zOMHc^`W#SRA{$~h%iyZXEgEqzn>WQqxy@axQkIV!Rp69Do8wGlQ{heR=8jKt{6n(& z^xusQzP4H;4;0!#j$M6*6gjTYwe0_?DO3z;tWYXI)AXc;PE}unP)v!y~RkL-NHTejL+TJYOFx zJ}Gk;>kr{akrm0TTbG$vIKW5+;av*5mKl8+-T#TD&y-J|Y+}wAIl(9($EOCd;k+)q z`EM%GcKk-1eiANj4mfFlD1$+d<}H&6-N;zc=b<|JGYyC_aMRB%y^VW*ga)1JKd(IZ zjFe%>mUH8!Z7o9>YBZtcXG{-*j34RkeqEJvIow|sQRhwF7?)E>e=as+=uYNP!t5ZJFSnY=+ z-?ts(V1Bu>1Qa;enk3gO`c4E}1e`5?X=N6m(eVZC=gyYwnq1cNC#^E_dI-^~D|rPy zf_&rY^QL=1pxOikggj|C(C2T3l_(YC&nC{GUrGBq$nKBfFz%VA!~BfJA$2px+9DGKz+Y%#g3w?1|Z$lRLM^-t;fjxJJc=qSd_9fcFvjn}F(ZSL41DpWMH?aZS7G zrcbuSN8g^dgTR&~;dL33v30qWShP=s+NtIf{4iQpha%=J1KJZ!y39rAJRp%22%CzL zqa|~J_eVCRP@U1Pp5v)j`ks$B9j!O(gxbLD^=N~Q7V6fB{pP0t*C~L<-M`&5x`8cUH!h!A59*2aYI>GWMn1n4j~pnOP!+SgfXgvoOgA$}7o6PxCiM zo|o2F3nc}n!@dV;ScN2`uf!q@*0#Xk@9UafKtSjk@V{R|-oUc)Zx^g(K6F_X?eV~3 zO?pmOnzf`hLMw8+k~+2`(mAS~L1SF8xLz&6^u@$1H zjTd-A^|c0h+t`r_K#-8ve>Qx)d~vqnJy4#+ZjEr@sKiVd+iZ(q=bI+0LE~g_imAcp zLj1%y4F0E;*W_T?H;4LDHv`GKe@5+9H*`Dd zX?TI(Oq+3Ks4W>ZkoAOjt=e@zaV@*&xU`7_E~ttHZYK3@TgxhlXJ|3H?^9xF0tL?9 zTg)a$!kSn3e>S=7Vwi9Xr47jAI}hLjzbItiY@Qcn*x>X z?S$~|!_}Jm?taZIJ>(jn+v(n(=fWEA5IZfGJ298VMk>< z9PtBz7zOv;XehJAf@l*0`aUVV7Zbc^hl2DTMf>w(%E6U~fF6-kZo+*Km*xgY9^P$* zMzLnd&}-7W-0QCsr-RsGdLkH6V0$*J<{F59KdJKedhJ$tw_)o$gp)bUX`?^$YCCi~ zoagElYj2srLjKZccupToxsf@)&F#;bcj^nYcm}<1HlGnUbQe3cZy}LDQnXPXi5lT6 zQ_)T$(?b8?MpRR^huD%@oj!<5rz?>nk=S_BnECllr*Im4;ZBt4+_&uW#!XT(o6{gQy4nI5 zF|gp~45WW&4ecC7?8qRXf7aHTs?k4pb8XX?=HA2pPwdU*igKzQt~h_jVXZILn|Pf*3j#)(52k-7CVe~CVlUvtIn!S zT1w7gel5QBT8R71!Dzs>WDu|SRsv8{g-zd*->@nRH$s3 zM6%nt-?)%is1rE~1e=WMO8^AV>d5yshg`;m_h_fjc4AdJ83YU^HA=oPYW}rIm;M1# zHz#}&?)*s3=-5>&H(CU0UvLomNZ61X0y;aFIm4#n+jG7WL3u^(HHJW4po0+nLn`)^ z1RaTD_Y7D5)@AK0QL317%O?d09Mq4gsBAIO)Ak$4|`* zeq1F2RjCuJ*4UYc_>g>iogeWm%|hG%=oPK{XT_hACKZcBAmK_NGEGcOYdrQh67tb$ z832$$j^Y;U_uP%{>CZv%c(jCzSBC3ATV;1kZn|Go-#JR0=1Y~>k0tPC$5*PFhqkrD z#72o#1<#5q3k`y&2jI?&vQAshzYk=g=+!p6>RJn0kgAlpokMb6ss1;oR-HQiQeEX8 zoy~Ol3_34}d^}{hgZCPy8zsnm4YL^AZ|n2FTUP(f33rx4OM2&X9_p-&8<{6a%i1vr z24B4*&swW5voD0&FR_ZITK#kwklK(k%vbgzz7s2Tn*ohE0Wi_Nn5`6g>Wx>NlQqbi zCUHuiR6E&BkSBkwjzY!Ngp|Hul+<3ndW?0wtnMm!zi98YPTzp{lQ*8nu7fw9?;RS$ zdzdnvR9`@9KCM9(Ih(7QUI59bJIVHT2^kp>k#$ouoNI#BrA$|&FV6r0{~5)l)&^M< z1z)}w*IYCspj_M}-i#H$#nbxMF#qlV+e8lxRv&xo{vPz&bkL+asW25<1ly{VA+zIy zmUVCGP*j>?Qgsw9=o+4LT%>B(Ga{w8`PH8y8c%<|7rtbWozqR|5@L0S*F@<;Q7THd z5SD4DEhYO@9-r%@Tnx(O59oaUXSyr)cH{SdW3B@(&qVDaFoA5mPoTu%-(#7JI)^eq2 z?I;dNzWy^6AWGfR^Kc8@IWt3`Iuc_a^r$2k$A8vEA+2srm1>%IE4T*XIpchbMET1N z61gF6*i$%kAlUxp1@HeA^=JBti5~uUb7GRb2kvkg?w2uZO3uuGgR@ z>!TTc+~7ULiyzY;M?K8kk@W97Rp~j(Y&77$=O4Oj%HXcVd-n>zLv-n(-u||J8Kw_h z+Uek>nXGRF+FxIj#yrk8q9RKBNyd!xx|U;*#65HVSC2pWXAJrp?v-&#oWgYUgU25 zQx8$35~1^$cAj^Tk2(lKmsUspn4LU7l(A3eFV~(Z{uU3Mxqi<|P}=m)lstwX?J`c(IIsSy;bvQI4KJuiO8PBG6{_0pZdN$92~JOq zXmT1k>Sx-*XK2vl4{k#xYt}HIbg34dV zkVqcFfnnvaX6^8(DJK)aJJpt!?c<0kIJ#^*>}}qqsYr|;*EXKhGmg_g`u68;I21kW z>11)h?zwt#$j)~{V#v;OhwZu_k;H~uKWh1dBEZ?HdV5tE)PD&li6Qw&F{#TqhU^IQ zn1-ucK_DWs)8(bf8}vYZI77Ic64&m)MouaYu$r2BZ}na{72pCo!7QB?k7pm<{bYeB zoSk>@a+g)AC*OvG@p-z2I((w*G~qAp;x+t`Q=ej>jrg<;6MgK&T=bIGN8EX_6O|v_ z$8Xf7W!M;&YhDcqEPXz(QN9(qSDE=(r1u zEfIA!uwSXnZyVr3(_-MwTI|p{;?v-eFk#VRBC&uRM6Zix-*Fb*oQ#{+ZXl%^0+v{A zel7|7w}@D*2bT3CQAwoQoHds*2jNskH;i!iI~d8R-VzY@?YRD{@+|hL!VkH}C#gDs zo=dEh@QYnZw}N3?CVW6zbsIkapF+*l4H>>ZLF$GFNU|w=72}L*BGlHPXus1T*DJ^< zlI6L{3$BkLpynm#-xU|Uw`D=heT121I^LtnTkYNx*VHds?0lA{X(C!ub;Dd&^{Blh z?#rLONilM4hscQ*UCGh%Q32v1FKp7Xj)MkZ5<4!EsL&6(uC@`J>NP~J2Oh6OPfiSB zOBJ{Qoo^r~xt|p7oOt)WIGbRD*@+d0(6x5&wck~F&|5yyV*0A~8u+di=q#fA!IG*R z;X>}-ym+=hM07ydObgiXU*9v`a3$M&$d@;R@$NNz{2KS<#Re$bhR zTiA_+!1c-b`xHpsSNpY>2dwG6jtaQFrgQ<%9oGbhn~X+0F1kl_*N2q>IiET4>U5E_ zPPN}Zm2dq$?|<|$K9?5&y$Hc&>jq1?F&EmQ_uUSWHR5o-Ll{_?J9; zh5uEb>E%H`q3!w3=yEZPUfDY^GUV4;VOz*LX8y>d*$g7!Sx0A|bz3P6D7megC#nE1 zAMhND#~Z{N0?}Y?!eo1Hoz|cDHZ{FySqszLd1eJq&TAv2!$f8zv9>@MB>mls7bSci41lw`_`rdeuP^_`sY9Kqu21WZFHs#h40)db+0d{^z0veE;cUx+ z*|0I#%jXA%6$p@{z*q&!q2>{D*IK;7(%=di2OYuB=r@RnEq?b-JoiB)yL7xlU`Cu` zqsNb|OE#+W5Y-qRWiqF!wGNJ<4@oqAB{nQzOY_ni0>OdR^DC1U+*E zKb=m5@hBs$QWF!vVv7M$G?A$uScA-HOIGc`ed5$AVidY7EW}+q>)d*PfH%6B0YByh zUAhg4v@gjj@n?90cI+cgctGM$5l=^QqX`R5dfl%~g83}z1@o|$eauUGPNK|;WSr2o zzyB$ofA|=OVxG8cj!h;4n~CTiNay4lV9Py7C<|ux*pPwCFDDBtE;tZt^EAp`s6;2? zgYQEd$q;LGQd~~=3t*(d zd!XwHqBBH9gMovDMOTXZGzI}xdl_Wibl6pNTJ}=fdg;~E{`C<^m)`&``HGTH_}BG) z=5^Q2zghvTpThodr$<13(HRl8X|Mc;ZeyEUuYN_jk9X2Bs%G;Ur$rA>$pBTO0&h3OCSqW)qKt4mqi%pEf{}RdPssnyTDm#a=>v|^{-rczV;&Cp} z6}wl&AkJ(hV1k?VNrgM3$Nn$c7qXr|PkZpt>EIB_T$^^6%gV*}l=i!gE;=tgzeX-M zk4#?R6?y8n-P;pLZ-9(HAjsI!kCDoXmi_glTAw`ngi|6~F4N#gm;(8{a~dA+ zH*cRCOwm>3-%!NFnIq`8kbVRt?zIFRLw8>r=P{8Ch1rjkel4bbB!V1I6o2irW?e3R zgXayV%8%koX^r0a>06z4QwV_>xJcSk#vU!cJaL18RY`k9UmtYUGbfA+*!y{h>0|aT=@Od_Bvf*(4XQE zU<7f?`}mMcXU{MbVrjS=Es9oDuRjz+g%Coqi#+L9h6b2z&A(<)I#1F16Dh_w*mBI| z4BhlKQcPN=O8CK*Sd$p5f0PB=E}l33q?L)K# z28;6V^xjeCkZjO`K*NLheFg%WZe7(x(aiYw4cRQ#?L*LJ5dj+9($;v%xi18NU zm}~~oN=H}o`av13VMJ_fQAC4Y$8d6iiVMi*$t%MlH02FG4>uD;y zz5~9M)6yA)$P$|;;%q}O3nBQ6I92p6|DS%8f{YRj_ax6ch#l;HYNjA6YJXv>HOv6* zw*JNNP$=v?5e?X9+~OTOhU{C1A>kVxP#8_o+0Vo8l+ zSV>&qE`&6ufy0q`pmdTbVNcG2nfLA1sN<#*d(BUm&|IL<~hf32(3ipHJ=gWhrn985)yV zGQ%CD;Ulbl{~M(;AzNpnl#)`^Dzx;iG|2cV+&Kb&+~c5Y;-KkATCSs@Yp)G&9d`@s zF6W{gB4A`X%F{XK=1Q~;hOH4NqUN^Sdz z0tg3YN|iOQ>_RYS=)~tH?pM!Q7{BOvnhV|9){mEXlNag4$y5@$9%J|*p+dC}rCr$f z5Xzp};BcDJ0nR=R^4x=_UlHgUQujJOo1iaVqd?bwl@9fwKyPW10^d#NO-I(Nq~7!O ztlY!XL!jk+gTs)E2@rtu3x6ICwvso!9=#%*9OZ9~HhBzz;hcLD-x=J^jMw`DEIU{M zG(NQFLE_C4giaVWL@e3&&W2=i1wF`VPP#$_G$gS_(- z@bvW-sUbdWXoiPebYL5-1pHT=P;iv06CD=4;!jD9YB+nefpy-){#&8iEj{{729%Y) zrF?~z!K#~Z`9UZubszg}#G#$^8Z1pZhP8bsHg~bVVOg=r1D6j6INu8APhlqojj3Y> zcC;}{o#aD%zpM<_!ysrlv`g^Sw(;93?G@mXtlmW-$r2^^vM@#2kF)BTGizg}ZCOkx zV&RjzdAZLc040ociS`FlLghv;-QOtwO@eVN6oP|AWU;leDgQ(w1-Plqa9y9Jq_o)> z{iT9n{{f+2vl&jcQz}Mn$O-qiR_NR-;0HF+cZlk15;_?HTEU>ldrk`0T5=74^fM5; zve{cu@YrGhiltiinGO@gR-{<2Reu_4 zjYGq7YUp);Zn8)$q`fan`AlaaDfo93^V;O0d|)~&sn*As+e5C*C~(FJJ!>b?zTc*6W)p}L);B{U((`?HWU z_Xtn2hAGMk|Ifn`RE&Vk-tibq?)_ExNwJ8cdDa?6Ssou%pn(CDOj@QFEb)wu_fLll zs+|oZq{namMGYhOI=oI#e}#Ywjo)x@0C&}S2juABS(_{xB^)zB#Ry)@8E$_rvI zmO(zURFeK-eis=ZsmmreM_0S7L<GsNk9d3{*qY#PW&llJwgML?e4_k~II@Dbvp@xV zh%8#*+d#ENgkW3COTi_ed;z>X9}blazP=|{dk!O(>!^hsw(n)dB(=7^(m4z?b}&kw z&p+F+Zuc#aB4@+MX`BDTVJ^99D#?Nj2P4RLsbBPD#uF2_u`f6sg8weG4MFg6$T*o0 z(!Tu!TF-t}3Ve?A!=o-w$?vV}Y))tBm<^0knnkBwvF!JCuMc*yng-GsOUaeSoG)}& zPUYo+`UdtlsI+*4%?jqXAGwiG9<#XVy#pcl#j6j=V$@>R;X*0S_EUGeIcr*p_!<1$T6;0OMpUZ>KJOuK?cS4iT(;dqZe{~#O)_TQO>f+8`26Lj6v0C-HgWm zVVS{|Bk3Jzbq@8`0SCeX5hM+f+CwpQh;Uu$uhJ?^dTPye`cme<-y7Wjo1^Nwd~E_+ z!&|ApHHCGZ!%1?@3Q}*M{}IcoB-gS@g0V7RL|~^ie&r}p1So?S^pKW_;5bR*qz1q~ zeb}LSo6my&1R0a*hj|{gt@j|gk_ClynmITUQDL!=Z|5&|A@~)#ooC{*AeAn46DjdP zsAyy_JC$k*2Ip3c%b~<>(mmC!)Gc9{n3u{O{9xk}i1eZDQr)IT0qMA925O%v0aOiF zmc?j2CnaycfZ@J91x7;{&3b`KCLdDXo{^GkBPPh0!ac_)l#0htSp9S~Bc55p7;8dq_H7xIl3%*|`$MXF;mh^~?%QrSMi6 zvrfeBBJfVJ|6qO*6D3nO%Uhd~L=!7UYb->IF3Ec&Bgac)&mz;C#qu7z;!~-0obB&V zjS@SF0O>9$I3oHK|K74cv1c^oXkU+bpWDbD3(m|emc*z#Y3&<$CaX~nBjlRUo7&^o z+@QlzILnNY$F$0K#a-A4O1VhYe#U>BWAa!b1VIp}k&e5T3$) zCq(*6IVf|?ylW9sj$N}bb#K_%jBml%03i3RG#4w2p65*%aQxRr#GZD(E2`O25TrI} zZb}~Z@InoQ+$qcZIt40sp+{i0Xp<2ye=E(TAkAPQM_1_i8x)3UXYG%mOVp4X6F$5; z`B?n=-l|76*|r^`-Nfr+KmTLw$nxQk&peVasuC?P;@8~jVJ)rc6_MXD4#9M~(97KvHdt|` z8SGM~>7NsnRBE?X8H#l#;}YIkyB}UfxT;zS3}^?YIan*fDJv~1n~B@cxen$(&M_g_ zs-b>8gt=?MajINh}b zSnL$Whp&?!!6GLOZO{V+4B6S8g3Jo+(Ur-mB}P|K41eo0e1@<8UbC6wydI-!#fdMh zzn)0&E|A4>IMF^T-LXy_wBt6A!JNNAPRCa_#fK@`$ox|XGsGaJ_iHi^xVC**`kUvW z99LIev8F>;v<$0%)AKpBoBM^rBC!YW|3N-7F2jhfe_U?=QWi(3nMHgnycntgqwrU0h(YUmzl>MCi@~F_?{A&J8x%C@w)QJ9 zE0_&3oO0!;HjRWO1PW?PfZAvkL}eVfc01i+mYH(?B&P*a$Z6KQqEMpq+m-3~2BtNo zu(O&zrX0%Mzj(Oy3iHFgAnQ(*toeK!%XVqxe8idh!N8J}e@sT>be1^?A+5JCM6Yci zYA-M*qoNnqIGDPiu%jk14_1}8tzaG@YmMFilvt5e(`QH@`3*f7NXRSXp$m}fADo`M zyj~f__zQW1RNy5Mdc*f_bQxPpY*)n(`t7=|BF~G|*fvwY@BZ-=2RgO&$<-;ng$=dd zi(A`RPc3Rq37p!HBKNc1FB{-Hxf*QR5*9uiAQZdI zD*RiUOvN|rA7Zx+hRBeKZn5^{leIeJF#;>k{=R8f8=2pQOoExrEMadQpL+(01bAK5HoC0C_s=6(pFDTmL&t>}F zP%>c=j4$-_f@?&f_(|l751gol_6d-@%3Xp6VW4}qV@=Vzt7D(eDA~Dy{RSszi~Z%B zTCW!DA{WU&@$VA`3IDx3aownx_Lq({<`*4sAV{#_)&?GRqpx6pXI{T)=|*$(3oqV5 z&opqdc31;RslvlpUjh_FW8utwh9b&2<)6SQiJXvqy`&ZXuubix@+*}=X*9HVKN8Kv zH}xYd1{ZiB)F-Kke$jO6Pf#PcxSwa3uSh!-^~63;V()miF$KR0C`{t9ln_;K8dbb# zO>R`;Elw$9t_b|2qY70Cvqx_AyZ8C0J&`GoZo4AD#^=kxG(iDJB&>t#{+nPgsD|lQ z&T7UVev0rb`|C`-&A-hR^`5*q&rmEX{y@BWX$A<_(y8pEvU=My%%L6-LxTn8f}=jRl9Xv#a95X-A;g?pBDulMh>zs+ z|AM!&LXAIWv)gBsX%jzE$;)AthAd9*RhwByh&V;yq!%Bp`ZtI>l}?*6_LV4+ByZ#x zw)Det@*ynPrA;EB?bFy5S7ubXg6)`6g!STT?6g!x=LP#JRKwwsC>^eB(%76LI>iH^ z9>sj_94Gp)_wUdCtC6Qa$Xv_xA60*@xL60qIyUkA2Ot>a{sJr49jcA?ZCwejY-Nzx zu}Fak!yq}Iho$rldWZ^2f{P23MzNXp<}TNrvS@7mK@QQ}l~7z4AT0eOY9AZo8-%y1 zHRq%{o&!e2IeHtF-qA>_+SG-}u?O&`^65;jr=xDxp3x<*Xb!QU?kYDC_*;jlCqST8 z=@e}hKjh1CIBr9Mm*7;t>YWIWl9Q^3_J>?Xwc?mm#Ed$mPgFV=9Lu2m9ob@&G?pt+ z-y1WPY&_PKhrX)F;|Xr%!{fFIxd#)XD=&C`nQe*l4~-6-PJ-L;kCJ&$c_84qAP}T# z!YOcBkipD!cZQK~2a6lVu#-5@TE}8+jv=T$*>1pTdn+AP<-iE^(Xk{dUp^Q&4^Qe? zr_>#`T=h`^@`5ktl_LZ~PoFKEz@m$y`kD};{6bOaPA%WDeo(J20%iM@*emJNk&4b? z>hsz7Zvs!5m5DLlPqpQ=0L3*Lo}wilny2p zmXaBZCE~>keZ${(@+u&bE$#UVxp835!fM>06>8wCP-|XiDOuCdX@LsAl|21i$dqhv z{=b+IQOTAE>cNh}@Ou7q+N;hU_kb8_&UYHmwVAM!@n4|3a2VaVueDjGsf z8l+jW^Bx6cQ@E$BRYkzsrr9)vsM3&gr8>;wjo6ajYitzf=dGwqXewX#}<&T+*&T z4ivqmbYJ5dS8bKuSrMoeSyoo`b2R#p!6d`aTu^aJIG>I)bl7JeO=pIi%r(%S31$}<1u|+8`8(cliBCAT+ zUVNFwbG0GIE|j+OCvuO2O1PRmfW3q-6W0O82)v)qZ^Ez{WbFL~HO3Q~h~y&f67O#o z%K*hms{ek*_XNrSk4XcH|C*P*pFRa+T<;^52c!~&G&|8xI*U8ck$X9fUu7ehxDf=a z4IxC!S2!!1)_r3QWT6B;^+{$=KQhPg{1CQpz>&l`D@c6R;k%4lLu0Sy$A=jVq%`|0 z8-s37&|MzQ$k8LO3M(HuASEWLid|amfgk3Q_7q_j>T3K%VLr4HPIfRBOiRK#JUTo_$T^>;KWAMcL8?BMQa<-Y6AYKJCY_3Ye_d8tF^*GJ zhVJ1R)b@qm(i8fKJE90^YITZ9Rr2h3yHIKpr>9SY)lr_>yE zZUW2QtzD0~;u|xH0F#{Ffl6a6T7?7E*I{ks}X9Y5pY6IRAQ;oWIcOOcfe% zS(_s_;Xk`)X&CfU(m^`|r1X~KSyP1xum91agS`B7)`4bzbB7@pr21JpN^(D#x3y*O zucAra^oN8P8-?mqbW0@c>|~4LV{?mCe4dV53$x6;eW2D}q5T~1IT|y;D{CbOcRnns zXSkB<9ZQtcGvdAEOV{BYSWT)Zy1eiOx64@W`H$q(*WB)%-G=MK1L1bd0TiEcraAgGg-mzHl@|=YDJWQOKzi z(lzYWG}AMh|2F?{1hv7K`}$W0Yh`=`EVQ|piuPnAwFuvOFcNvj1!b%nHaEKM>|a6l z{yiJKe-e*`SqXzHfN7=dFjK?89ASf^nVo9OsX@6(3z5$C>b_Z(=bG_U#I6NX@`&oi z`5D<{*JTQiIa-E95R&~B%1BQ>y>x>e<^x;ROfmgy(m)Aq3LV=-;y8JsZ8LXP->+JR zVqc(abt?g4zB{LehXv0@3@$9-H^BzU2ws>eNRst=elh6?FhA038lI#q*#6l{Ul76N zJ%X>G+FSc2VA$F5!?Ee{zaK)FLC>F)uZvFQu|JZ-Xu6RxQDrb6)@nxgLY<67Wl4>X zL181tSTRd@m?PvED1Lv7r;#}-M&<&gwh2zc=8|TQ9;RT#5#;;o5CWwGe;&0Y>)Uky z_Di4@HY$Gr*fahA+&|xh6g9$Bho$5l3M>Ue;<53>M#5JvY7F&u)iKtS3Q+vSHAr5b zAQ`f*VV_CPC9=)~D_0!wsRo6go9-n6HzK&W&b1KB#0Dl;6$*^NDvc21+i5<3pumUn zmU)3bbr83;oVTe4tg$H?l6V9P4&>b2;Ir|r9>p4fADdGyd-(xmCvJMIUW0l(`A4MR zg3xU2h725D+ld)ad9D>3a)Q+`EVc8IRw3-#3m3w?&#Yo zL7O^+ZJzZ;Phu95_s<)qUv^5`Tvn!8aff>JJKM224jA@$mLV)$) zOgLk^il6lq&)uF4j1$n&>`ud)a!ZpYDzYzluYxCWkjIDFNsL!#xlL=cKvPU#TFoq|2!HsktX{d!8T>DaD*~pfBeDoCf5eUtu2|pQ4xpTMk>0otn8MJ~L&)tNumqX#DPhn3&vs zzN;$!rL2j6$**SRUdZ0$tsUK6>teB&61v02&An3WF6oUUQBCmVUih46?s?hNCy(Qc$`;TGrcp0`=n4Uz@A!2{plw>8m5H zbuq!4au!>>`AdYovKrt4Du!tW!*7UM)P1VpVRe7t!?g2G~}vr^jR0FQM4GB5u^O5k&5pc4hr61qiDN586P*}x28gBq*VaQ3WN z0b(7#EeweK`YWx5Hur9)(Di1CWUdJMC}?fh`LfqAP5wlEbQH*f>A6k-AJUE!yI%>1 zb#{2`TS{w97LFeJh+owp3_hOR<)dvUXxbNYQ_^^0TAz^wT!#ljl2e zB^omiWsH=^F7d1dOUzLinF_+(GGsHM_4PoSovlVhu{Sv!($k}-3TMn9W~VZXlw4^* zzH9VNqAJangD5FVQ>P07k`p=opy)1R&I0sT`PqG~(*Sxi#d!9{_1rUB3vDs!{tH^QV{$M zbA*-(20j4A2>~tQ*OuMA@1}406kD@tRIE-{x$G_P47xaNU#iOd;5_)tHqlzFDc7i| zL|w*WK~<%ZVRPPN0TU{tC^d)<8=$LGMI&>RRn}Otp^zhZ;P=?bqe&JRKXo|1eMBP6 zV<;z<8m0VMJ&OtY+cz=1on87NWh!~YEr)CFCw;)VLo`s-NcNJ+kf8a8hQKUgJo+~_ zMCh>^U8IFtue@C-RE1`6PK4vj{8WUM_s z(hTEmK8Fu;)_-XoQytP?h^|b!{wOrcre5URqi_8+K+|^D4=Skyq~)5T(PnQj4^x5H z0sKnH1_AfBtS(F%Vtzvu1HQRv@|vdD<(x8*)$iaLm{YJF5uv2gBtancA;7#+TDzBHFuQUi$j-AhQ;I;jb4vrr>6; z<_^N&;Wh#Z-7snxlmEqY3v<4gIs^e$))<)ot|p9S)n;WpS!(6S7;k+BA;SnyYp=NN zM6jPl2V8S>B_a{okP$-?=qH_Zf4#;nLGk|a%*kj#H-OVd5wEu$#ifkHF#xYeD=cFBOTlU)Qo+$4PcZk7}F#TEEze5l-! zIf9<}`(-y|;YWU=pZl*wi;8-_f2UFiU#&i^V%;_*$>K5Q48u#%byS*EX}H_MlJHx{ z2e>X@8rhHT)B}ForD4z8s%u}=$3_`%qv+ehQo0I^)T|<~hFD`>*!OCUU@Gzo#s{L? z9+$CprnZAs#l$tETrr_dn~($l#HB>)R@6FG?>L$+$yX=xc5j%<;Ixt&d=#WRJ`zYq zr)l_Q6+DMXM)z5~x64m1Iv)!517C!sFWg=)M_eafb5*E2@$J4-T6eZHQ_%<=(Y3BU z0_#HUin@2GMGsI3t4b^|GkoijleOE#I=fFu8D$g4DNgb*4-9ySgciUoL`Xu@8d%M9CZOmG155;l&r@YBNu8h&-xC0phjg<#PX3>sBkNcJ?^1ik)Suw2W% zq|lGIM6&*lD!H96h8is=usL!bZ88~3QXVFWmxN!*Klim&GGoF7o@7w!L@ogkAeOkW z->!f%kU9NWL5F;p?$oEGnot|Kwh#<1^pIarsg{Kmj3bO=D-RsEnUUPjnnIFt)ocrcw7M2w%yFs0Pp?D^D!AqWlf9Vo?z>Y6G!oxh+4vnvo8*hPc3h!C`EE!Qkn2To zFPaB!Aa;70^(FgAaTHYdF%ac^vb9hoOX&DGxa%~6p+yybQ!8D^x!`znU6kK`-K09p z<<0E(45$mv9mpa1i40`Z>I@^Y{J;rfvJvSD48YhP$QG#Q1&ZLKVpSH~G4y_AVN)+R z7YoPEIwE*CxM>e453D-}0w_3^|5I;(F*x(r&mS~l#5X>kncb0SIBcZ7v6-KXQ0!!y zYVvi#)5f!g>Fl0wr8w98=H>7?Ly|q~yF3A`ze){CR#(D#uUyR3m zJ3?qQsgc6l<<`@q<9DnqIzTCXc5`D+vrY27PE_6Gu$PyaRn;iaY|c#x?6qabD|}mb zLkVrY^_Qns5${d$2r{+yA2Ub~O2X;l1Sd7;|55z(Jjl#tR;Tt02(8kM|47j;9{T(R)>y^$`mpEh{Kr^*q2MVdoXsXv215yw&EP`~7t$OO z_Lf%DddH($Qug|adyf9+4?=OrK=sApM*ZPy;xCp?vk-<5IZaQuv?OW_L>wU2N%BB> zOA_~Feiv3i*>Ks$G>3RM)}0`}12=oeB(A~%DHa`mriCu(2r z)3NohT>k@VWL_->Ws(G=;}W5K&GG@Au<`6vU3&GLoe|Vv%q%5<4@M% zst>-`E*yO?w?0ZMn!g{p+acCpOmS)FQ$h;w2v;-?goo_J#;Ud;#SEZ9WbHm_VZ zZhD9Ueq_Dht0|(otqY#Ldq04Q-AkWP`m%oJ>yNn#e?jSM%@$nD#AId?g5Z8LX*Y#&Q@|J9?rGe{<6@Kpn`xtcz6VD-A3;lv-8AxxX(2Dtth zBRv`ObG7f96bJr7I#%zMx#W&C#Y=Yg8>9JR!KgfH*D3^dNcffZe|7J18xxm;!^+>~ z>uwLN*>&39`u26eKMw=G5)VFv-9REr`fG?(9{vDY2}f>zZ;)5<5i2nYuzku%!ceL( zEz@PpOg;u6+`h6=5BavrSi*E5^5I?a6#PNyszwSw()E;)On}~A7CEBw<6hf=s7`|0 z+4JWYXr+_)SfZuuWR?S+cu^ot-)YXW^ZpR=$}>AIa6*W{*F;r0T6;LK24DTEeV)TG zG)dyZ^fZJsiAEu-+^HU(X;}Vd@3CIMn8A;Ar#}sJ$9h_y^?ZXVny39{U?HQ|f1id$ zZtlWLYNRSn%+Wuq60=L@FVV+BjEbdp^FE5&E>Ypp)eXARYdTe2uMm=V0})-)WWOz_ z?IkMus87YpBakRE?0y8o@=M!zKHj;0DsbMHjzKFi?XJ%#whi&CVb^@PoP}#r2Q|ST z-@*VcHSJNzMF~gnC!3}j(oqhsN=!NJw6cGw%}pchcJKKlVX=z)1~Xqwb(Ut$9)NfH z#jJq|!Uo%`_rdNLb@jCG_}W^53Q}~kJnKM)Yex|U>>_yF??-Ix(Q8&YL9Anhx@=A# zn#Tpv$Q!gQ7zJ9$_b@mrcbSu-UO&A?_)q+4_xcrPAHBhRc@-(tYlpZhAnLMH33C8dS`v=o7|I0(2Z{^%K!$29dzfMK~w+XrQ1) zrDcFdu(hjN8%KB^TeS;vYJQ3s%sIl;WPuhZC0*^ZyxdI4yEvU*n-j&)_$APQqJq+T zK5TU`Npl-wN>Fs)WQ&EK=XZhmevS!&UKo$}il5J%%@M_uySi5Xh>@O-wPcpcP@>IA zYMCuUyF!)ioJNS%tlceoV@izIF@VG#8cJFQA%?4mcHQBdRBYacwmqg5*D@@5OVq}> z0Uwo92^~KQu0AZOZ;zT37?6vxY*A-F^-W-HG5aw(WjN`+vu*88lUr-i3x}s{U|w(I zuo~2V`PyMUcx9k#aw+iV`XfTEb(@*xB|+~c?{%W&W7X%yB0G~w5KWyb5SW;%1#6RN zf9nbSO2@ZqnaMBauLX2DohU*HTB&`Z7s-M^JXirU>)U5R0M1c%0445N5wMZavJtuNjJQ7pPF-IYGSV7hL(U z`z1vl;%Gkvux5~~WYAZJ&+>yeF%`L`G8SL>3Gb_4M7V@%ZQ}7%{)@5PwlORPT5>(;#!NG+5sB3LGNLKfu-F%XwSN3 z(J4##q@`>eA=ZRVKs4IQcz5=EJ(a%v zBSFc_#e9h)%S=Uuj(C|J{OOq0fPw`-8TbMlx5qQ>i_|=xGQxswai)B;R9crziIWm$ z0nkvHqw=;#v{^bw|B0+YjVfA`aF{qZZ3&(rkRx{u{K@oUI&*; ztdNv_{QgN_&7zfa9X>YJbZBg;AgpVF)XNnq-!lotrM1wO`tU2-*C6nVQEwu>sSV!9 zVB3KPXd*;NtfKBigwJ~N!|buyn}w#*8`w(NvtfA_;JwMHHJ+3`BV*zFTrL_4_=#?N+$HD1t7OMUXcKj#!yU;jdNx~hlszPkN zxMbl~Jbl6cj?r*JDY4CzKOk~6C9+kiQrZOjS0x5KP8^PGk*^Vam)Zo4`W)MQ4D(^j zo+xsbb0ef{@|Ah_7qa{}FRpCX%{{N?EIe3PFE^=ZyHX1IU9W5JrFRvGSk+`9BW!CH zG@I{ToJOZW9v zV{lXD_O&hOq~{ownLoV_Ho3!@<2f){V1jp)d4!V`D`3nIRfI^S)ov`QecpCbip+=m zAwE9BM)y9zGz_N^Z#6X70Ey-KC8xew0oxZ!(VeN7aU*?TKe&ZSoah{AC$x+y5PX0( zybS@NFPp)%aQ>wx&~rJ`b9PsKH6FfPnQ$k!Xq`Z;{NXog&>Cc9U_P$HquUckjSJ(sLRUY-5*Wcfg2|au4K|6nmU32k1Sl(V- zhongWJ*&SeIp+e~fesNp`H9)`xjuQ<^oPTX7TFt2SoD{FA#iL!yu}bZklCQMdyY>)1;F*A?6!s&(`}-C-bknb$ z@QyD7grf~;Jd;Nz1PeI(j#r6F@;S`11{ zllEvQrnE=cfL#tD{12m7^}I6^*h^`>Fu>8Oo4r>CWLAX3I@s%7XIsN;JPb$kFUzg1 z9ZJ(RnzAy)p5tHmylIUTurx2;erqaGWWk=xX7HBbf69J#c(_LkAVF*S)|9dYnww14 z^;smdtfPUpw;*Y>m_)MKio04eu)Uhd<@c(QEo}KX7Qk04rls3V>Cf#NVAjiS* z3}1_O>}Y*voKJdM6-seJS>OX>Ne&x3Mj>jzA>v@fbITW5lfEQMJc18*Lim1jJug#L z`G-f315rMNNN!r!@039mu!23Gj(0OrI|mIKn8B-Y4js)|r=YTcm#3AMuLS!ktMsSc z2y?m#hlI=%{{j8#Rjvf-qEiG7g!IF)a$=dLh^46AJQ2mgt9DZ}iuiTNtB6!I*s1_V z4jFED%DV?P|6a&xnUw>v6)6(?;=Lh`Ufw>W6$uy}SF<8+C`tI>2>t*V=s@iQxm?#C zT6$!Dr1vJ+vQwbd#7uco^D?AGDa}gXzJ646D6g??*ZC)s$mC5em5J&(nxFb+4v!k% z4}MU%ZwR7LVfeQ(1FhhBx|>dqSqfl(pF~i;k{0IEPA~tE1fI6gJ3Wf><%F#&`dMfO zOzaGQdzf=L2XcOZHVTs974m1_Zsh=zAbQMC0eZcZ?Z5?3p%+C^ld>Kq@UBNJU@@SB z&CK{|8)%wIhswLn>+pFsBsB-`CdgGUM&1B(8cAZ-`#a3(a1JU1Umya%wi}4K<$u0p zLvN^Xdp5})qmKBwPHO=NF9h5TG^T&nvcdi6DE4Fmyzzv!@^RH=#d-^WTWk6>RFC&^ z=q5M;whs|ugw>ulOM(e9Ytbj&p1WTwpP%-3)*M$G%~Q|x8*PGSS+7wv-#@@c58fSx z&7wG9LXj0D>Ad;FqyLL#FW}6>8B5V6Ym>kzlr<@Zvl8KO*Lw7@hGMk5cq+j1*L2Hq zDe-^xEWTaz&9D6nw`5{Rih(zN?R}*lCV>YTOP@S-(}(u8M&+3wjQOB&Sezw6`0bAl z|M$&vVLVm*l8RFlgSbb8B78VA`oA@2nprA-@HFlFq@AK7Z5HEzdYt&HsyT@7{c2ju zNMiZajZyVHmwl|g!$V_PzP^FRjNv^Yi|IMq;zx>?hmo(6=auV;)|Ids-jq9-cE_+h zCR^@kTn(ys+s_;9OD&-&=B&@d93xwM9QUWq%t9l*g)8taS@}0b%4jk2%sTocJ?&%n zV^@lfNIbcWSh@?K$Z4puSLriLC>2-vJ)!i$0j<-!?ZD_Vu9w*}^mXF=g2N&w3Z?Tp z7-!_L<4vU{{uU{qs|t1M2B$A7&|&WP?jdPFQ=0lAr!-APe+D>D40W9HpOf&p)jUIC ztEf0Fouorp4 zx3*UZ9)`?iXY?8Cp1?VBs32~<`DLO#Y4^iORT=7_ET91o<={_;LH+aV-n8r&6k#Od z+I|x`c~;Fl{L!K3h|!9GCR&EOda#gG54*Ho%9*2==v$qeZ_LYDJVWdu@(75NFez)ZevOsQqj+IJ920uZnc*`LHBM;LulMpsgEkX#>?`^dyw7xt5^b_4j>rRgEnsM0uilz4RNRmQ*UD`R zC{Mb$)(z$ONY)?min2-71h&wg<_WB`XSZTLu2%os&Xru&d~|vti`Fhy&}DL}MW21BWf(loCj}x)*yhqC z_gBO~V#(c(cgEeZzuH_s$f_hvt0#wfCjl88b$0RR&o&uHB3Ze ztm9~^!#8#){L8%Gxj7+eqIiDrLy}SL-2t@P!QvfBrS28hl(AfrqHO@KNTGJuSH zt7+ImH*Akz<{wKVYTRKJG*n}W!kXL?y?#IX@pd($*2%%-7Bp)Ez&nsyO`Y#!PtO{5mb`0{euQ zaD&;OEddZFoYa(nw2>d{KLE1$kFl0(_D%S--TjDd+x6sr_zMYb zXjNBIZNa}$TsvtA%MY&TD}wvYE1)~&9NH`A1z)Bwl2L;FJs50D(vf>_dGVI+q- zeiangxKhu9gz5fbm#H?;eB|5xD+NUlba`@)z}zBbZ?O(uAcdRQ$YKXZ9N3VPPE=UW zvta1eK6S@$?)&BbIKHv8(W~BV+72gdQs7R0H(_4wvh~2EBjRh=GR1@%k-V8An+1^s4&D_u!ID9EZ6m%ijq`0FF4YWd|Gt+cUF#fs4x;lGQnr;i9RA;Ctjg9>m~Fdr zeg9PAZQSBL`!(9SF&W2l+`+f@SL!HJS^x1*+_NLML|GL8URUI8X*z)s*}V|cY`VCD zsgfC7mWe=3&eIT^p;ZmAH9d%Jsr;cCYOkFy#OZcJlAX%s^~dE$JC#?2=<|LIW=JX% zybt`%AC}onMFOvQ4p9Lp>p%7)xV#?5NJhjIcoZfCFV{r8UHwbON+E~ESDd5z>eSTW zEelMuvy{64j%0?@sZdw+0Uqla^X{QR7kcAL@ytyu^sCkpllv7@d;-TM9nrJaZXeD7 z_PZaTPZxMU!8)Y|F<6+FbS2uWJ>e_3*sn6Qr)GN*_$fBVEp0165>4u9r%GHKet`Y4 zInD7+Gt+=$_r3)N{5RhL>qGC*Jv?Q?T?V)CIiGoe&p5vG#)Rn5O~-no*SIW;xvZBRfg`SKKX!3YJEafAtlgC!i) zB#W-cW9>3t8)7Ry0;ja%B%Y<#o*UP2t;POLkw4MDMo~sc_Ui+@aPvipy#zKPaVyB4 zwgG%*ni&gFBmbI&9wou!!5TIgZcPc2JBb79gnen|*Nwj6hm;b&qm(>YtXO`sw_<)} z(s2Qy6DFz-ohuyFAi-f>NS)$2tS62CxG!(!=0-y2zBo`kYR5W@CXkm@#mZ^bLeB9-)}09D-wSiVjFoeR09pBBaYHA&OsnHG7f=h;s(%t!KM z#d|dKGF%w+<%0j+rN`hlE0X!h=r8blCh6>3Bi7{uf2hdn!ZHA!XeSAzfCC zPVe!@cC(!qcA{-rH|4W0QP3> zy`_lScUEO}>jxR)^cL@&qtvbZi66h}pqt-W0@>q3R~6KuSBWEMY= zSRd|AO5EE{Az*C< z8|T0;>{X8z&VJM&i>ON?Z7U~R0LUgPXPnWq0~^EsBp#kYSH=BT%_HH^T9?-{?i>hv z-SqCz+^f(@#tI{+fLF{X!yJ-CJjbzX7iysh9V#37P=`i66Qv+@<CO!!b*+iVt*P%N~E4 z8O;n4jV6^3Dvp4>6MAr!Y2QSWu-Ml8)PCS4T$_=_giyA--8~ECf+N99&Qe%-eL#N8WQn?~|CLRL2vf-eW~zEOwd2q;g|DC0%rXmFv-VFGZvQ$a{q;C_(@CxV z;vF9Z&(xnD$>3e+?g^Gj+DmXM%a?oVz&wy3WwXFtO~AOO_dHap|nYlDX*lo{7njn=#kouC9?^0wUb>nnc7CM zqd{-2fBS}VALDh6BN;6@s5&l}e|BUPfd(q4%~4UKJUZ+d*8+&v5GO%t5| ztFnnA6+59L94mra+htWeBPW@X47u^8fzc$!i!OEJbh zff>9XUo8h8 zSJbC>nx>Z~uwWj+ zq`1)k1LQy(zp)v7;RJXw7;$+B{!9jzh3*ZYFWiIJIucI#lw)6eoSbuBTJh$#oSGikB#s-1n8!5#4$q{7=fEUBW>ft-V;|>-Nu&a75kEXN zLy&)EoXBveGYGer63Y!yQpZ;8f6S5h&Kb^OcM0GQ#uf_oNq4VrxB;cXa2JcKUq)jAKY1HMFz9o2nB&p-n{H8Cj6Q+KixPRA zjdLR$ajcKVG>mY=391TX6i@h;kb##|CE9<^X>!(*(iX~mY&BOSBnsFyz?4u(P*k0$ z*4|UKR0mr9SkdM-OxxqKXPY$xo+sKaZ7mpif6d`y5Ay`T#swZIL@b7kf{igIDTF2g zL?|CaJ4Qdwx0`aNFg0kbS^zhviDluPc@JHxa?JyrJv{q>tM!Un5|)i3fjD zl#Qf8R>**Z>$uI)4%{9fmXSdER=K3m7+fI|^2~(RH49zW@5xT@lpwBKJ=017s$gxv zbr^woE7$e#LS13WRj%vOc!L17*^-rce$CCSJa(sWx9i_Ru71!J<+I=Xa=XA|&J6Y9 zV+b^Zy#S`mju~;AB#o=E?PkCTF?N3_DHFU%Mzwq^OUDfc+>(R{?)?cr4Ic<^)^u^- zE+F!P54>r5J>Wxce(|}Cug2}8Px^ED^7p-+DW26;ad;YE#bx&r zTR8v*y2Z52nj&Cg)w)&BAJ#Xv8Gt7N_ZKNY@<=S9z@kk9eIYJmzyaoJ@mcs|u0ig? z@>fqdf}HUU@yz*?C$sZvyQF`(BBTpB3MRvy@R>(%t^=Oy8hvH&ys`-nn&9Cw=CDy= zo&eamFd~Olaf;kW6R@`Zh#);F55n9jbbGRP@;fLGM!OpC=PH64@#&9YqtRP=rVQr(fBaEgf^%^`U>@pgfF!X!1p&p;737 zyhe&lO&SjA?FG5XYu24ZCHHx(nrmoyxGIl$iH#ZL!>{~H5GVuVANLn1(_gC`jq23T z4L%}%cNBrwCkjmf8vkHS;POap)+H3p^@4t|C`{Ve)jidrgRgZwrGuU1VL_~N)$i5w<+{ybqryA^u!#X=2Ek@1g$7etX2+|D3UcPReGr>au;k5;QRiOUH#lWn7sfbx%ajG!$@Ce zlDyl6```SI@{H47Bi}jm2a@r@c!TwS+5=05vtwaPUn>(-@!dqyh;W3s>Tmi(zC0$w zWLfRt#*TjjVGJmozluQwD0E}0gGiswGl-C}+>-MlCmttnefZPmMprm|U8)NueCP|G zlBb>aN)e≫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 @&NLo1Y3 z-@O}zYglTiM_o3Flf^QABf14=Qqrl{fLmX~7B6U}rXr0rPxV#)Dx`HH+Ki4PV^Xl& z326JpMddf2rw{h&?rAgIs_e!-kwVF!jCj zcN5g_PfPzGx4=atw^|EQ^%m~1nFSMm*`R5TPCb1Bg8|2vx<0ze)5AyqtOx3gC9>xV z?>n!6UDe&s{{bQu);z8pHpuUrWiRmy1}F*_cd2~Tw>WaEP-gl~S%eEY?FT-@9|=Ti z7SM+d1HDHIN|OiBZ^chxJ#N%O|7siXf@v^*6mIDv0pTcOY9&g^8ZLB}uN94(!c4Np zDzh7T#cIKw7QrG5qN~AbG_9m_H}<$G_O5Lo!h`tWi~SBdX&FoNTs`z});>@&p|=qD zVzfkSqBy@D>otTaVWjf&)OuNAbQ&iA$9wXDAl=gRBRxCP0fAqD<`59 zYfnkfgF=8g)-6r&L(+u~_}OWmG)qc0f_)yOGyH&YGAO(y)mrYjzwm7aa{CK(@O`|n z3)lJj5Y3g`vr_oX`l+XZ+m|2uKX4n}pPlY| zfr+R>&`vSv;L#b8hfjC2b>9qJ?lf#dhF78@pk^v#C1!`2WIV%htYcqHen$IXt?ZuuIU{)ej}ypCmN`t;JfUP}qU5pc1UE;tDa@rj1T=;`xb~U|Er8gTXWgZ} zuHeucYSO+C&Ci*n%|r&ykog0`<-22G2Fnr%ZNMkbOyXMGKlb{zpGA#E%*Igbn{^+> z;S-zjIiA{bt9C7z2kxr6m)kIL8S&pfW2;6`f^X;2c9={nxMGM&^3DAu3J!5kmuOd1 z!YkJCh)xk}Upyz7IBPb5`BvoRUnL9x@af@C2g?=$+(9}cKfV&NwALi>yCR$^Z7 zwB{NL_Uie0XUPsf&p6|Y(9G?Yz4R-sZLj0nG=Uq(q>lGS5Ocyi_j*&r&t@934a5++ zRzoBuKyn51?rb!M*8fuGT&5#iM@r2g51+?^H*0f42M$8MW`OgLfn8fi-%$CQp zyUl-IdUpZ`YHX$5ujw!jD&Omuj@rM*it6v>++mB0&;z{Dh`Z$U|EUEJ% zO=yiX3HHc5`df@Gfh(7Yqoe_nW#rx~ykT&)PBm7@wR#~{Q9U*jX}bE0NWf`fd;FO% z8mm=+v+3Xj_#cI=CTPFeDSmANfqobdS}*wlGJU%_Vw?>TsyF_s^;uC`t}D(q5?vNhHI6oBQ@8!T0ocov#?kJFS-su+UuV+H+9gq9^Gp6RbQ`AK#T z=t%1+eem*PW(Zj?iMi)x6tZx?8i#&3b?MlRtAuJ_qg^2qIBp%!#G5VPpa9ucH#y-W zz%_LHnej%?yaT&ZrawEiCD-w%!=XeH#A2rbV@5s2!Y<%+lUBUabV!W3Hh_mge$1Bu zr7}=^1oz9<@1?NZWrnS4$GuTsa3Q^(_KJEOA}XGajQ#RIvjY42T?+d9JdFU4=ETh{ zm68kEsr!;5QpI`l>vL^wCgTf~!&fT6wdbsVMA5v)-QcAwDpw=u*a3wMcksIg{B77` z@_{EqYSJ|aXy@SKkSrj;Z*aoDV_^0`cii>NVnM6{w{hkA8k_ zIFWd=L@c9QJkj)(Z`$R3P?!U1nAF4|EQ z)(?FHFb*8_32@pF8+w(JfI=+}))yhO9-GXuFL;Cgy?){r+EPf4%{hk*Cn_=13{}2y z?>qFTrJ7_6-A}#=)KiI}mzA1&qfz!qtxHTh_;nWw55<6afz8Rd4q9Yxc zJA>GVj+y!rvqH|IF*;&p<+dGn4%+h$H1JyXA9TIT@pkMg9-=Mz>9J{c_$}sx_4c@{>VIIp#Ug62smPpt{Xh<#iu^o-kk9-t zO@7(lY0jTFzU6(I?9Rn)$e`?Ufp}&aM(jkKwCsa}B}Kq&IBK)zwyuk@$(sO8By}$D zZwj79-x?a_YmQs2)mJa9YwA+%8KTv2OAjKR#|v zJXb!?c-jMF9=IgXs2(m*wDzm4XgVt2?(v;${|0sTa9NI9vc7Dfd2s}!vSeadUfSRq_$R0#w5*9?Y11>*=)dDZj$27=`{;8pynL`x z^m*cRK&EU^_cZ5!(;bhE$)8h1J+qw+wItIp6x1{K4;7Z`kvpZsBtLIQHVRkZ|EtCU zPG6%C?9U|_?*DMq?5z=c;*q$~W-&5xaQ&IwsZ`NadNSCJoGw*4|J z5e!8~JG<*(=t~eMc(>ADvF%B}gSi4|G`?K-tRq?c2myHn&5Y*r< zvpHNg8LFTE8JBf9ur1O*o@WaT8qHb$wu!*i5;pT`pi?Jf|IKqRJ2ER3j#k%A2n$5mT2}_5o27YUf#u)|EA*~at?48s9L1vrdZ!>bUZr|_y z)Ms%ysf+8k(k_2$V!n_J^lH0p+_+OFyXSZB;}_@* zFSPy5LECeRUtE7}#~L{Xd$?qN5$aDU3I}h1Oa1u;;ki897k=qLvrf#^%%W-pO?df9 zR#>9+NqrN>doDas)$WP)fNyQADD#trxPPmp)8l{7fm2ZauF)S@80hEpzsn}ehK?D( z20c|iThN**nssO^mGm34aA&x%5fC+FV8zsv#?#1OA*2m}&UZ5cdyX1zeLvb})h4-Q zI?S#2lgY%ds36Q>IC}O=nkS>Zfalt$M{Q5mX=2PPe(MKoni-!fl0(xIWv3!^biaC_ z@vu#MRtoYIE&v#SPqGzfeFzy}xdkYA5^zyaydq-a;=2X>m1OI??P5=WT&1_G==bcm zt6u)2Ot=;s*@mxg7jLAC#;QFkG#c&F{4}q%ka1%&TLuaJUj6xZmri=ZNy;_sLCz$c z)#%_LT#%xPeGhHcqZsHJ%mM=NRQ!_V|I;I)B70G=0sI}NI%?lKp5Jiunz!v1GvKU$ zQ!R+KicERHMLkrX@~*N9_Jpg-atV#9o<%D@aLnNUI@R`1!-`YeBj2la$IF~)D?8q5 z&;2YQvfwnia<46BDfZ4_t--eaVjdOcu4tqKz?5b8xNCnFiy?$$BWDyX9W9kWJLjD?D8D`l3_|VsVoS1_PEGy;HZriRZSV3vcdsK#%^LvF+!$n}wh)Lu$nj|Gf@N zZd+b^>gI$1tzog@vJpp}aEcSp)njAoXkyh%h;mDiMg?Gz4kx(*QA#dfRmVR+|f@^yeOF_f&5NYmM zg*g5pGK1x-T<+f~#vE#y)8U}(>iL+{5OmVGdI8v4AN)73@Aa20iIF_!|5V?G?ExTj zKs-6*+p*-(*qN0r?&Iv4M0V>Vb2If3Jqt&1hGD(#6pB;i^Yfzb!G?C)(r> z6%sSbX!3zTf=^sOH)%~e19=B&(WKPmjDkDyun3qiViXiiNJtXNh+mSRN}(lTy)@$E zRwt5~?JeTI!~}|dz-8Vskjq{q-T}w|v~M0h-$_ik1^sT#g1GOjA%sgmcWCKU8frrh z4~;TYl0xk4M=H1k{k18hRS91(Wz*mIKihqD=&+qF(fwF+SLDE9wcrTN=qE>N@5cUT zjf}cX17^(j5bg79?M~oMxN4fsE`uk^$-R3h2l2!+&Nft2id@r6Iw9RJ2LPv)HO6qv zfOOdI^V3}t>H|vO&EYSkuh)`S(Z77e1FU9==OpGyOK-RISQL$~rQXw3Epaq`=|Tuh zRl|Miu9QK?152FGQ=nDwaVzEB)?|v%g}e}|kH3e}ab+N5AaG%h7#5fz^}IHReY2C9 zTtkEJWGf?$t*c#H!+15)hp3JLw<{|ZS-Evg1K!V8+-|p7K{>`>{MCA70RYr;!Rn- zG$lW=^Bh5z#37ETddnuB^%4!w1chKV;wL&-_#}{}>zJS_MPi{x2T;E}aUVAdk?KaW zEAhp>EFWLLf`}cRp@g^cOq^O8ukP2mv=68fvWTHRw@f&`{H&1KmNKwqbg+a1zS5iN zyZUTlz_!+2?&@oT;SOecREME}?7!zpp}y={MrBc??NT)2L$YBK8Qk|vGZNAdCG=;W zrXYeRLC$NbUn4`FfL6HnBM5$+UA+YUew_L+v7<@wu_w0E>fok;VcIIRmI2+lDHS}T zd85TQ0O0|(|IuIxRmAq|ySsON90NUM*Hu0qb{t(r?oZ~bM(sPhueUR|Ao)c>Rume| z_8>)$))E+;qfswp{cPY$vlQ(C2gxZ5VN6!Zsa)?$Cns5fdRqRolNyS((>>&{bBPef zfk?qGCb0r|Hn%~+iYi?Yh2Np)mFXj|d!5Zlwl#W>zF72Phx@RiRT%=YeUL8oT~P58C_+nl}4Ve z`r&15!RH$s*GtSLmu2nKVdutjh9i($y7mAy3%+b?rtHPNB7Gr#NNFdVsQ<{W zJWvGTf>83YU)crZpa}>r5xmxmzmk9@dJ;0|0mIVQz)c=SE zo_Tu&pMkt2?_4w5I55R}a*eaAUoBk;<-pUWj5X6&P|t-}1bc>2{+ zi5|)h+GJefgsDGA_|K=DU8WeBgcGbLvd};Mf%4CtdH-mOG2#eF7Q@h!s(o@dJswq|4_W+h#-r0&V-K0htS_6(@Wf88U@XDi^{ zc9z@UGPJcBcGU!j_?ejUxDbmp5I4n{(}380lYfG&4IcH)-i zk!>dL@5S=Vz(|PYocRFSuVY-3)Jpr}*X{| zjORCedaY~QIVtxmOU2`dqB94cELHN}zYes+rW55CHRrzbveDHayD5dO4zK{6zoR97 zJ~U&#x}4j@Q)&ze7XhY|r2?W{3OByv>4XtbL8t!;<~&URFu^6lXE10oV7%ke?gV(A z0dPLWcLZUN8t2k=|BC*TmsCF~f3iL{Yo2vi;pA~6Rar1DK+=+z+4w%RZdDwx@r5DNIJoED*Ap|*fZI;0D`Q? z6N?vDYH|~vKvd&f_%10P6Jw)g?b%slJT|_9vaK>XuW**{SvZ&$VWL)bRR0HIlBda< z6-LXR?Qs3Vf^WgBgqU>PgYM@~ zKu=E33L-W6$^IB<#ApX z%bXYk57>~Wg*#w>(o5uUTpG;d#AZ2aD%KpVSA5Kuv)Q)Ic@)dEkI$EV~({kRg%SytovQd6V>4t@^D)~14_fTJq0JBv6*R)9Q4E9dPK zyABfPM7BsTK~^`JU_>Bz@rKPg*lsOj!c63E`N+AjFlM-;3?q`W3`-`!ocFXbp$JV6 z3;qr2{&d$>{CDw|Db9AzLk1p4{|C!lCi9Z*Dv;KDf`#N9t&C@P+jw9EmY?)CXLu1H zdq`!Xo|1CoYPKa+sbeI||0`dw_7s*9-P}b!?I=x7`5gbPj~VNgp=_07t@H*ldygj? z;o`5E)S^t?;MdB2?u;Cns#f`7*}fs-1i!D3w4^IN7o3MWt@PYPKRzwQ%0NCI;7dNw zWkVH@<>6z-=Fit>Fu~(zs2kw9w($d)(InhSMtb5Xr#!%HF5+=PlKCxWw3^ajWfa9y zO&^0JpmVkYerg2>ANfJ2drPYDG@6SPJrYFBF_UFPlOXs1%_f4+@At!^Z}HFsobiLi$)yFIKAd4M5dnXoQFfT7X`j| z-5UDeofo@mI|hX1jo5QoM4M+?AjA6((*5KLNy*8Z@jqbt?sK@KAPK%N-1IT%R1R*x ze=A@8KzH1b&r%1uivuA|2zdar7~q7YFugIfeGVxU%#Mgd3>ng!viZT(=wC4U*?&PM z86vmsY%kXt>-u1(SL-iTWxmC5%MdUXkB8cH{bEzbBxeMRc6{)~oB<;M{y}RVHfS(J^#ab%Jz4#R_ zj}z!JC8Za(UIX~0)xr8&+a9f#u81u<(=9&UTOb|8in_HSaFB_x@DPj5dnl!RojF!= z!Ae&bZKokdNsY%Kz&z@PG|FdddSDW}`19_OC`jnA#Rs%JxHn*DT0p>t)*<{YD|Y<^ z44pS0o+<1QCbBNh?Q0VRQXO{IPFb`8S z4>kV%5{8WYg<7uwsec{K)0ZtqoY0G?fFrG*f_Wq)=IG*+>ypb8mOt1ld6(7=?-J83 zoI9hi&z-p5C11t$f4LPU@!~MLmdsvxNmFysg^5O9#5WU{R;SAridE@Ta zt=NIUUq3vLgQfL;MtM(et9`;1PWwn_b3O&vf6y5n*vjGMzC&E~!hAs!7!7R2*rsDA z_DSNA6gY=eKR-UhfZi^a!t*~zg`}OP1vh)P3v6!@OF0F(_==UnNmx%OjjRyZ2zWGL zasHX_Q5bYRur%UwNkFAHQ!s*0JeroX25kBo;MFZ7{Tuh(6x3m@aB&q4e0{1bC8xQ= zeWX`!%)xvM6-C+!{(d73WjffqU#`fvXMO6wwzJ9}#bUpixxuAO*E_IY@9;xNx^E2p z4Ji>TVA~Zk^R9q>#t0o*@KKRs>l}0`=a4)0a_I2|_9&Ccu!b zMY}fl%tPYgmh89ATjzJh`QfLs2*)P)DbBIJkjYVbhxFjg#$4kd*a4MH#W6wY6lzO(Wb-K4cp^*<0eGu2SEUENn8WySO-Y2je z)}7O|Gs(gC9c?j6*ssiY%UXUJsR^8OC8Gb$-Dz!KwPiEiH~By<2Pf?p+FiB*+nuuD za^fld?NuJ2RTpIxojx&QjSG2*IAI)@KsDxT!Gj-JnRLjPR!a2udwt4tM}!cwZ>S59 z>mIn&<1b)jenAj6Zfx~@^9*JDB#&#tRmxPbSRboJ^>~z0L{J0mpHgWh1}s32_xzB( z$3-VNGsFy-xr44je&$KI?`!5!srBJJJSh*uY#_Lv~HSCkZBialJjiFNIneG2C>O+Sx?mP!ryuz_jH#Ca3UR`PiKdw{N6* zcpu3|F8fDT#OD6%MH1m^unN+;r8{%AhLRYCMJ&I}ukRR~sZ{G6M+NatVc{L>sw*uO zpJg7r%rzb>t`UEo%IBOq7b$4Nr+wpZ);5yMZ84?g<2Aq^xqSmvgcfoS*OCzB z5B`+RY31a#WDQg-72)ba8(3Ju@!58Jh?{nN$K^Q_?IgyK+r@tdsbTvyiE75Zz(mhT-N9yQj` zfvns*-RbQd2Au!?g;46(bp^r z(kcABjm%wg@r(L&W+8ElOtP+~e{&DS5ZDTxLX|s&DtuS`uq^W}?`XJ%I*ij>foeL5 z6{CC#2|)h6Q}uKDR}=VDFmHN=d4@cNK32>41-s{P`w-5_;G-p@SeB zpaoSNFzoIP>vh*!+4}YvufO6li|Kc~3e<;A`{CEqeV~M+ZGIE`ZJ(1Il5+5CC>`5(^u8Mz$5c=8lfY$TLd@1>Ah8 z?5O-HkW&YGyb9?!d|a-4{@Bq8KJ@k9Y1}(UB-39%jvM*5#>r_o!0S$DC|gz(JDBZ~ zp82=Eq6K;&ylh&dJRBAyv8HC1{eC_+}g0ESH8JLaHy*ELX-oUxa z&t_B@Ppm17XWPS-F*XU*3l7(u#=oF01?I7h3W*hW{P{T!J~!)}@UWpf5-%FwBY(N& z!9yE}y@*BmOTQ{X*7f;Ztji|x0;R3)>z~WzhG6SES4vm2+A$FwNqQO^{Rfe()EYFn zCOu)*^STFkQXhq#fA<@;5qp=|gi2BTec6_F!cxqx9fl(l70l>ra%(D_fU0F5ABgy` z2rY#zKkv}g7~ei3K7WJmtTbVU+fKfixA3d}pizh+Rp@2YRSM8}=Gd`G5fBE8u7rI% zW=A+FwZcov`_`JVy*~5>X~V_glu{n5Htl7Ufc%MF{pOF!fyQSKA)gm42#TGmYcFbs z+wRG}y^>md#9=gWoWMyf1po(`0b`@;pPBhc@w^%@&$Sx~)KHEby_`;#UK|g)4$dAs zSha49n7Yql`C`TVP%SUl1$(oQ^q;>3j%hrc<4n_V9)`>b3wMlHbN`U8El{>!Um%zms zX=$wK7zM%m5;S3cFoN3Brp2~$3o}*KWbIbsL(aQecATfk!>GV+v$?G|TlogUcaa&K z8#<|9EwRaUhWPI_7O5`m4|o~=NQb7I8_7>S?yNG6k-~%w=h)Z4IRz1UwYHo-B8VvQ zbM1O^;;GBn$@uOc02IRh0MCMpG*Fu7QXeaL+NIUKZOga)OC5L8t5K*Q+3d}_w7 z%;+%L6*-6c=C|FGuIkcK;I(HaxN_VwJ#U-lWM^)E2$feKD!?~v>qR@8%bAFX1fG0K zSMBm2NZOg5{)P3M1SuM#tkW{RLB1^+^xjt@P4^#$-$F00jsyMn*fNGIpix%AGdxB( zALLOsaqj@lp^HFDa((QQraHYm4&lC_uokCsbi6;n?lq`*{u1uMP3^KD{pCjepODvU zJZsE8HdiV;!(8TY6He-CCWz5v{6t?`cl8_1*GIP3yq#Qn7Zx-%GYt~25olL<@EQ{I z466Ga41+(P#x8=ce1RyK6982m6LojxPZi#N1B^{noxyZ{pEqNl7jN-F>zDv$?Dk|X zCpwP4!7Wz>QB&Vh80G|d+Rj}a24=|^_v$Z&(|NkhGXKxKqxHV_z8UK`o0TZYl=%mP zyGf@5{HK``8Or?p1*{EAzQNn^G#V42TdM6$C4w~Z)${D%^j7;acu zz)ar{JF2IVjBi8!zv^}9U24;ef0K3>mmh(d3$3(9t<3Mlc3<;u4EV(OkbapOdechv zpToBfo+pj09Yp&#ZoRJM|09qh!^w#xf+y*84LXcu3|nBu?+7MIUkJ*7_vgEQ|Hi)A z`kQ__@Y^7&D-F96*fHqj5ODH-ckA3lv8curY8P2Hw5rr^!XI^qO zLX^~c-0K0|31W274AnbSn9W6Kyy H(2_)Deu|RzlofuG(VBA6M$QtP>Q%0%}|&; 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

    6e;5wGJAFSyF-umL@D|{SsfM$-COh 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

    rp8 zxl#diR~1@1y3>y295_q=Boa*9qLT``AP5GVR5V2g;EurPLLZxyLx<<=yk%^%iA!TR z2z$iuuVWDmMbu=KlBn=f2&bJvCppUy%#X>x`$)GUkWHi{WIs)PUM*o-^O59L<&!MS zZ4DGU1F8(2aZA@e4lthAk1YL6o3?f7ojs4-j6;VG+-URUH;*BLGCZ`ScjpoVZoU&p17kyDC}Yw#r*kle}0 z!6C0xw#<#ILRwFe9!i1+X&pauf=u;BIly{J?K_rQY#Hb~DB{7DSdM+GVFHd{r z_umX!`Xi8d|F)Ay7$aL*)+t>+OTE%J-u7*`J%y%FpHB3mhNlNKa_)+BbY8T>qyqKu z(WRR2!dl%@-}93qWWjEBsJQq7Y5>J_O~kb14y2|Hk|Wcrv84X`#PBQn^(C6%9@=}u zVHxda^Vd4WIA`%M^S979TGcR9S}nV6aF%b$mdZC~?lFpObfJgk9>;Q)d8at}8HDP^ zISbNPxK%iWL8EL<$5E?I3rQHjlC@ds$85G}hSrAcF5+oZM*f^2Fa$#=_GPrlHkd{F zxdgVuo<;KeY@956)pG;aK_g#p4pCFNI)5mnI0ZbVO_BVd*(h>Gi((-zjhe3HHKo4T zR1z}J32H}>f5FdUY(J_`=a3teAyE6lP}a&akeX4wGv}`z9-Pr)4=#h)BPwF1NxXm#*y6?ZbuTR$Te&o7w`2W2vb7k)P$B6$N zR=rPV-+y-g(J0*bABh0}3z>hV2=Ficntxt1;D2MZe}0<(b{61YyPW^DX28Y&R<-{V z&Grgf{#!i&IQ;K50PwH=q5nw_0QQ2%ztaO$_CnYH&jUCD!M%Mh_gbv8_U%0ew@hvp I>OKwq58ex4{{R30 delta 373922 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

    Z%oaJuzYqV+(pLIwg5}o1Q&hKD)7f=)FK+ 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 -grZ6gJ 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

    â–¶ See the clients list and create a custom configuration for a client.

    â–¶ Configure the allowed devices, DHCP, DNS or rewrites among others.

    â–¶ Material You interface with dynamic theming (only Android 12+).

    +

    â–¶ Full desktop support with builds for macOS, Linux and Windows.

    +

    â–¶ Responsive UI adapted for landscape displays.

    ## Privacy policy AdGuard Home Manager does not collect any personal user data. All data stored into the application is kept on the user's device. @@ -40,6 +42,48 @@ This is an unofficial application. The AdGuard Home team and the development of ## Recommended configuration and lists On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a recommended configuration for AdGuard Home and some lists. Thanks to [JuanRodenas](https://github.com/JuanRodenas). +## Generate production build +
      +
    • + macOS +
        +
      1. flutter clean
      2. +
      3. flutter pub get
      4. +
      5. flutter build macos --release
      6. +
      7. Open macos/Runner.xcworkspace on Xcode
      8. +
      9. Make sure all the pods have the minimum deployment version at 10.14
      10. +
      11. Select Runner > Targets Runner
      12. +
      13. Make sure the Version and Build numbers are correct
      14. +
      15. Click on Product menu and on Archive
      16. +
      17. Select the first on the list and click on Distribute app, select Copy App and click on Next
      18. +
      +
    • +
    • + Linux +
        +
      1. flutter clean
      2. +
      3. flutter pub get
      4. +
      5. flutter build linux --release
      6. +
      7. Open debian.yaml file inside debian/ and update the version number
      8. +
      9. Run flutter_to_debian
      10. +
      11. The .deb package is at debian/packages
      12. +
      +
    • +
    • + Windows +
        +
      1. flutter clean
      2. +
      3. flutter pub get
      4. +
      5. flutter build windows
      6. +
      7. Open Inno Setup Compiler application and load the script
      8. +
      9. The script is located at windows/innosetup_installer_builder.iss
      10. +
      11. Update the version number and save the changes
      12. +
      13. Click on the Compile button
      14. +
      15. The installer will be generated at build/windows/aghm_installer.exe
      16. +
      +
    • +
    + ## Third party libraries - [provider](https://pub.dev/packages/provider) - [sqflite](https://pub.dev/packages/sqflite) @@ -60,6 +104,14 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [bottom sheet](https://pub.dev/packages/bottom_sheet) - [percent indicator](https://pub.dev/packages/percent_indicator) - [store checker](https://pub.dev/packages/store_checker) +- [flutter markdown](https://pub.dev/packages/flutter_markdown) +- [markdown](https://pub.dev/packages/markdown) +- [html](https://pub.dev/packages/html) +- [flutter html](https://pub.dev/packages/flutter_html) +- [sqlite3 flutter libs](https://pub.dev/packages/sqlite3_flutter_libs) +- [sqflite common ffi](https://pub.dev/packages/sqflite_common_ffi) +- [window size](https://github.com/google/flutter-desktop-embedding) +- [flutter split view](https://github.com/JGeek00/flutter_split_view) (forked from [here](https://pub.dev/packages/flutter_split_view))
    From ca0b3e238a7d94111221dcd3ec15cc819d207be7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 13:57:00 +0200 Subject: [PATCH 075/676] Added linux screenshots --- assets/screenshots/linux/clients.png | Bin 0 -> 142537 bytes assets/screenshots/linux/home.png | Bin 0 -> 107781 bytes assets/screenshots/linux/logs.png | Bin 0 -> 135219 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/screenshots/linux/clients.png create mode 100644 assets/screenshots/linux/home.png create mode 100644 assets/screenshots/linux/logs.png diff --git a/assets/screenshots/linux/clients.png b/assets/screenshots/linux/clients.png new file mode 100644 index 0000000000000000000000000000000000000000..5804d4690a955f0d7bdb0f93cdeef2823c15c208 GIT binary patch literal 142537 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%0D?%8hpdcYRP^g!ETz&$Gml+=$ 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%0A+E21v-$)icPHx3xH-!YCMflX$*PG4H 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 literal 0 HcmV?d00001 diff --git a/assets/screenshots/linux/logs.png b/assets/screenshots/linux/logs.png new file mode 100644 index 0000000000000000000000000000000000000000..2cf184fc939fed4f61b64a4ebb23da00c9f04911 GIT binary patch literal 135219 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 YO*krRY_X3S$oq$xvDJCPIoFu~02Hs=-2eap literal 0 HcmV?d00001 From 62cf4d0c7fd2bd585f79c1fda6033f9dee7f60b6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 18:23:01 +0200 Subject: [PATCH 076/676] Changed linux build method --- .gitignore | 2 ++ README.md | 21 +++++++++++++-------- assets/icon/icon-circle-256.png | Bin 0 -> 3246 bytes debian/debian.yaml | 2 +- linux/CMakeLists.txt | 2 +- linux/build-app.sh | 30 ++++++++++++++++++++++++++++++ linux/my_application.cc | 7 +++++++ pubspec.yaml | 5 +++++ 8 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 assets/icon/icon-circle-256.png create mode 100755 linux/build-app.sh diff --git a/.gitignore b/.gitignore index 24476c5..0bc0e3e 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +/debian/packages \ No newline at end of file diff --git a/README.md b/README.md index 293e8fb..1ee0985 100644 --- a/README.md +++ b/README.md @@ -60,14 +60,19 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a

  1. Linux -
      -
    1. flutter clean
    2. -
    3. flutter pub get
    4. -
    5. flutter build linux --release
    6. -
    7. Open debian.yaml file inside debian/ and update the version number
    8. -
    9. Run flutter_to_debian
    10. -
    11. The .deb package is at debian/packages
    12. -
    +
      + Prerequisites +
        +
      1. Install rps by running dart pub global activate rps --version 0.7.0-dev.6
      2. +
      + Build +
        +
      1. Open debian.yaml file inside debian/ and update the version number
      2. +
      3. run rps build linux
      4. +
      5. The .tar.gz is at build/linux/x64/release/bundle
      6. +
      7. The .deb package is at debian/packages
      8. +
      +
  2. Windows diff --git a/assets/icon/icon-circle-256.png b/assets/icon/icon-circle-256.png new file mode 100644 index 0000000000000000000000000000000000000000..517e26ac3758f378bacb2a24c96dbbb08f561955 GIT binary patch literal 3246 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 P-#wt)I@vt5_Kp1?2o~0B literal 0 HcmV?d00001 diff --git a/debian/debian.yaml b/debian/debian.yaml index ddc864c..df64eae 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -1,5 +1,5 @@ flutter_app: - command: adguard_home_manager + command: AdGuardHomeManager arch: x64 parent: /usr/local/lib diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index bf11fa4..273981d 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -4,7 +4,7 @@ project(runner LANGUAGES CXX) # The name of the executable created for the application. Change this to change # the on-disk name of your application. -set(BINARY_NAME "adguard_home_manager") +set(BINARY_NAME "AdGuardHomeManager") # The unique GTK application identifier for this application. See: # https://wiki.gnome.org/HowDoI/ChooseApplicationID set(APPLICATION_ID "com.jgeek00.adguard_home_manager") diff --git a/linux/build-app.sh b/linux/build-app.sh new file mode 100755 index 0000000..513fd3b --- /dev/null +++ b/linux/build-app.sh @@ -0,0 +1,30 @@ +#!/bin/bash + + +# Build the Flutter app and package into an archive. + + +# Exit if any command fails +set -e + +# Echo all commands for debug purposes +set -x + + +projectName=AdGuard-Home-Manager + +archiveName=$projectName-Linux.tar.gz +baseDir=$(pwd) + + +# ----------------------------- Build Flutter app ---------------------------- # + +flutter clean +flutter pub get +flutter build linux --release + +flutter_to_debian + +cd build/linux/x64/release/bundle || exit +mv "AdGuardHomeManager" "AdGuard Home Manager" +tar -czaf $archiveName ./* \ No newline at end of file diff --git a/linux/my_application.cc b/linux/my_application.cc index 1f79b20..49e0a92 100644 --- a/linux/my_application.cc +++ b/linux/my_application.cc @@ -51,6 +51,13 @@ static void my_application_activate(GApplication* application) { gtk_widget_show(GTK_WIDGET(window)); g_autoptr(FlDartProject) project = fl_dart_project_new(); + + g_autoptr(GError) error = nullptr; + gtk_window_set_icon_from_file(window, g_strconcat(fl_dart_project_get_assets_path(project), "/assets/icon/icon-circle-256.png", NULL), &error); + if (error != nullptr) { + g_warning("Failed to set icon: %s", error->message); + } + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); FlView* view = fl_view_new(project); diff --git a/pubspec.yaml b/pubspec.yaml index b9bc0cf..6d6f8ce 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,6 +22,10 @@ version: 2.0.0+53 environment: sdk: '>=2.18.1 <3.0.0' +scripts: + build: + linux: "./linux/build-app.sh" + # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions # consider running `flutter pub upgrade --major-versions`. Alternatively, @@ -121,6 +125,7 @@ flutter: - assets/icon/icon-splash.png - assets/icon/icon-macos.png - assets/icon/icon-circle.png + - assets/icon/icon-circle-256.png - assets/icon/icon1024-white-center.png - assets/other/get_google_play.png - assets/resources/github.svg From c8d395396a122d92c874856b862c9fd2ae8a6a48 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 20:23:29 +0200 Subject: [PATCH 077/676] Removed innecesary stuff, updated packages and changed macOS default size --- README.md | 1 - lib/base.dart | 20 +----- lib/main.dart | 1 - lib/screens/connect/connect.dart | 6 +- lib/screens/home/appbar.dart | 20 +----- .../access_settings/add_client_modal.dart | 2 - lib/screens/settings/appbar.dart | 31 --------- macos/Flutter/GeneratedPluginRegistrant.swift | 2 +- macos/Podfile.lock | 12 ++-- macos/Runner.xcodeproj/project.pbxproj | 3 + macos/Runner/Base.lproj/MainMenu.xib | 15 +++-- pubspec.lock | 66 +++---------------- pubspec.yaml | 7 +- 13 files changed, 38 insertions(+), 148 deletions(-) delete mode 100644 lib/screens/settings/appbar.dart diff --git a/README.md b/README.md index 1ee0985..465c945 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,6 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [fl chart](https://pub.dev/packages/fl_chart) - [flutter web browser](https://pub.dev/packages/flutter_web_browser) - [flutter svg](https://pub.dev/packages/flutter_svg) -- [bottom sheet](https://pub.dev/packages/bottom_sheet) - [percent indicator](https://pub.dev/packages/percent_indicator) - [store checker](https://pub.dev/packages/store_checker) - [flutter markdown](https://pub.dev/packages/flutter_markdown) diff --git a/lib/base.dart b/lib/base.dart index c33fce3..c144719 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -5,7 +5,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; -import 'package:flutter_web_browser/flutter_web_browser.dart'; import 'package:provider/provider.dart'; import 'package:store_checker/store_checker.dart'; import 'package:flutter/services.dart'; @@ -17,6 +16,7 @@ import 'package:adguard_home_manager/widgets/navigation_rail.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/github_release.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/app_screen.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; @@ -80,22 +80,6 @@ class _BaseState extends State with WidgetsBindingObserver { return null; } - void download(String link, String version) async { - FlutterWebBrowser.openWebPage( - url: link, - customTabsOptions: const CustomTabsOptions( - instantAppsEnabled: true, - showTitle: true, - urlBarHidingEnabled: false, - ), - safariVCOptions: const SafariViewControllerOptions( - barCollapsingEnabled: true, - dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, - modalPresentationCapturesStatusBarAppearance: true, - ) - ); - } - @override void initState() { WidgetsBinding.instance.addObserver(this); @@ -110,7 +94,7 @@ class _BaseState extends State with WidgetsBindingObserver { context: context, builder: (context) => UpdateModal( gitHubRelease: result, - onDownload: download, + onDownload: (link, version) => openUrl(link), ), ); } diff --git a/lib/main.dart b/lib/main.dart index 6e8f4bf..5efba05 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:provider/provider.dart'; import 'package:dynamic_color/dynamic_color.dart'; diff --git a/lib/screens/connect/connect.dart b/lib/screens/connect/connect.dart index 0e19480..3528718 100644 --- a/lib/screens/connect/connect.dart +++ b/lib/screens/connect/connect.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; import 'package:expandable/expandable.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/connect/fab.dart'; -import 'package:adguard_home_manager/screens/connect/appbar.dart'; import 'package:adguard_home_manager/widgets/servers_list/servers_list.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -58,7 +58,9 @@ class _ConnectState extends State { } return Scaffold( - appBar: const ConnectAppBar(), + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.connect), + ), body: Stack( children: [ ServersList( diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index dc63aff..71933fd 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:flutter_web_browser/flutter_web_browser.dart'; import 'package:adguard_home_manager/screens/servers/servers.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -27,22 +27,6 @@ class HomeAppBar extends StatelessWidget with PreferredSizeWidget { })); } - void openWebAdminPanel() { - FlutterWebBrowser.openWebPage( - url: "${server!.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", - customTabsOptions: const CustomTabsOptions( - instantAppsEnabled: true, - showTitle: true, - urlBarHidingEnabled: false, - ), - safariVCOptions: const SafariViewControllerOptions( - barCollapsingEnabled: true, - dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, - modalPresentationCapturesStatusBarAppearance: true, - ) - ); - } - return AppBar( toolbarHeight: 70, title: Padding( @@ -113,7 +97,7 @@ class HomeAppBar extends StatelessWidget with PreferredSizeWidget { ), ), if (serversProvider.selectedServer != null && serversProvider.serverStatus.loadStatus == 1) PopupMenuItem( - onTap: openWebAdminPanel, + onTap: () => openUrl("${server!.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}"), child: Row( children: [ const Icon(Icons.web_rounded), diff --git a/lib/screens/settings/access_settings/add_client_modal.dart b/lib/screens/settings/access_settings/add_client_modal.dart index c7e4012..14ba98a 100644 --- a/lib/screens/settings/access_settings/add_client_modal.dart +++ b/lib/screens/settings/access_settings/add_client_modal.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; diff --git a/lib/screens/settings/appbar.dart b/lib/screens/settings/appbar.dart deleted file mode 100644 index ca12964..0000000 --- a/lib/screens/settings/appbar.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flutter/material.dart'; - -class SettingsAppBar extends StatelessWidget with PreferredSizeWidget { - const SettingsAppBar({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return AppBar( - toolbarHeight: 80, - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'assets/icon/icon1024-white-center.png', - width: 60, - ), - const SizedBox(width: 20), - const Text( - "AdGuard Home Manager", - style: TextStyle( - fontSize: 22 - ), - ) - ], - ) - ); - } - - @override - Size get preferredSize => const Size.fromHeight(80); -} \ No newline at end of file diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 1c34d3c..3d7ad09 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,7 +7,7 @@ import Foundation import device_info_plus_macos import dynamic_color -import package_info_plus_macos +import package_info_plus import sqflite import sqlite3_flutter_libs import url_launcher_macos diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 9346410..fbc72ee 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -7,7 +7,7 @@ PODS: - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) - - package_info_plus_macos (0.0.1): + - package_info_plus (0.0.1): - FlutterMacOS - sqflite (0.0.2): - FlutterMacOS @@ -36,7 +36,7 @@ DEPENDENCIES: - device_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus_macos/macos`) - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - - package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`) + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) @@ -54,8 +54,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos FlutterMacOS: :path: Flutter/ephemeral - package_info_plus_macos: - :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos sqflite: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos sqlite3_flutter_libs: @@ -67,10 +67,10 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: device_info_plus_macos: 1ad388a1ef433505c4038e7dd9605aadd1e2e9c7 - dynamic_color: 394d6a888650f8534e029b27d2f8bc5c64e44008 + dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - package_info_plus_macos: f010621b07802a241d96d01876d6705f15e77c1c + package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea sqlite3: d31b2b69d59bd1b4ab30e5c92eb18fd8e82fa392 sqlite3_flutter_libs: f20746e4a0245afbee4f20d9afc0072ebff7cc26 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index a0fa417..b5c6a97 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -431,6 +431,7 @@ ); MARKETING_VERSION = 2.0.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; + PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; @@ -563,6 +564,7 @@ ); MARKETING_VERSION = 2.0.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; + PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -589,6 +591,7 @@ ); MARKETING_VERSION = 2.0.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; + PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib index 80e867a..ebf8e43 100644 --- a/macos/Runner/Base.lproj/MainMenu.xib +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -13,7 +13,7 @@ - + @@ -330,14 +330,15 @@
  3. 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 z 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 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png index f4e70fc113f153d9ea520aeb1287115aca976f7c..2f23ec2a102822763c050558b9bf9243f1960782 100644 GIT binary patch literal 6707 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 YsbTHQE)O*`od5s;07*qoM6N<$g6f&~MgRZ+ delta 506 zcmVkLN3{h()CAfj8)J5Np0hLAA!#ED zeK7y;``-87%;@+}(?!=Dg1^HE@@bT}z^&dSdXu-6!r^JsK7YB81pam-SU1wM&!@&c z15c&DZiYEQQV@VqlpJ`B~q$8C>QwGN>YO z*?0g8&`qIG`(q`6;SV@6{D>(R>O^L0yPkS-A`k5Dz zAs+oG_I{Zu5 wBaFK~lQi*}EdCD^fphlTZSF?w4)8yA10|Q>Q)j6p1poj507*qoM6N<$f+e%@M*si- diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png index 61adda5e7d951314a48cd924cc352e5a683e0e4a..5f8cce7620736dba7684af4ce2fa06dbf5e3a353 100644 GIT binary patch literal 20378 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 V7_?-LUz>XXQzI)wg1%?c{{W&CRHpy{ literal 18240 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 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png index fdd4d1a73322e7fb17652afa2364f8c1e08934e7..7856b4ae1264683c462cc508ab97fa29d7ba40c5 100644 GIT binary patch delta 1150 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 DFh}1) literal 84277 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ⅅ`SP#{u5b_6nAI*d^>EslD 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�MV<%l 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 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png index 2f40e5c8948d504df0b12f2eb5587647f6f32261..1a2df1dd20651611b1ede678f7737bd299480ffd 100644 GIT binary patch delta 2653 zcmV-j3ZnJK5#)WmIp25hcfb4n-Me?am^{Pben02uec$u`o%5Xy;UkVvzJCeGH?9aE-vs0vR|Jr6 z0`d(<0d$))9^tDhtdGM~CQ+G4rHV>X=aH5XTBsbP@&_uLs6@>#qyKEg`Dg!V+t5(} z;XxIM468Ihs;9DqN~L{^%L3n~a*WC%DytJug>wTJ6A(sAuJbIFnK>Zvg8)y^Dk?Wq znM0-BO#<#dK!3ISFfnh2LG!HaG(agpeX=8dpjj%w^vq?H{DEozJFxoMN74?+>SQ^84CcS%4g?_aPzNi1^t?Z8h=;6hI}4q9|ODR=sy|DPFDn9)D)9e+oNJ@2B=*-6VuAgbqj{I}=F! zXK#w8hlv0nj9+$itoAXWO)>w~YsTR5iL+@^1CB$M6cpj5ng?+2#^reB@NT6EBB-eB zqzK{a1I&W6m7(>$Y@;*J&W@RHjbdT-R4g1_B7!$W^sqx?uj zNNteL(X0rX*DSd_hg&L~SPh$duu5CMH!~kq%ooNqteo;KOscxxd2|olU41Khk#D$X z(=+5sqR+PrgJWO%NO=g)Ri)BZbZ`3c%Y0WP%gdW4xOA0fnVlTe}cLdi3?6%0I>q z8je?|EyDEQF2(6f7l?TpIAr7s0q2Ct2Ol09;NGc`)*3N>cxhj(sar@P?PH!yWq*om zdkwKA+Z6L-`+fq?-*!Jr3jOVq#zh?e zZM`I~yA~9ZHamw$0|QEX;`JF1Va9KkV)xl2Dmsu5gt3NjGKcJ6#MWe500tBvYqQmfB}dA`vM2Eb%6JG0g-xZq`MbdFXFksZpICLtK@xgq!1sk z=$F<@@9t#?k^tgtqeeO_LzhVDw|?Y!ltzlM^}rsP=mbbm+|~}q-hXdIQ_Fd2cH55p zJ>itKgw|S2AR7%3)+k`U*X?Y6!wQItZR88uFnZuHG|XF?)=xnwf*}?C@$UK4swtK4 zkFLX8rw(DmKXyqcHvQVMxOMRLsDF8>sz7B336tB}VabMH;-xpYLhBMq7PCoNrra%> z`_BVRPEiiVGs^ZH3xCO|AnzT(4(;7HH&NY~ba)3Ek7LD@dvJSmGkTI&U--EiOjx-{ znHT+Iq1;q8(wSf{X2w-DfZkh>--xA48^GaSK}|I4#=d1`}xt9H5gc0fwxZ{!tUb-lyA_T z->Ax=vW+9y+3^H~jj*aEx6f>6yCYG+7RqZ&K?HP-a0$JvHIGid6O)!dNE)u%@ml8I zbw5YDi0RC0(tnh=TdwPrR~W;?*gdvxlw`(#M;1d`^4HkccfqFyT#W_e>hRdMUsF}3 zF;Oj^Y^SHz3&!0p>-vXzTgu|Mj1b;giy>(yru_gfESNYQN1Gb4X7BdYj7_NIYWj$q zuwcS8&wf;!Bn`IA8+AO8{jRVvuutY00b=;++WTn1)PEJrcQqs&Cp*!*Moq?}Q|^>? zJYn{92_d+&>-cv87b46FjSp}N``DM}qMA)&-E#Tt@tV8vWf!k+J9vuVy|mT&m7fC= z4)07vr0$>j0yE6{0i$QP(u~?FxeK)&=w+&KC(R`jbXX3XJ54bI4}8h=ed) ztK~in!ha-r;cpgljT8;k>2R#;{L0TEDd+bojDLUa@7?k6x zl=RHSW(@n`EQq$4T=mICl2I=M*na5J^c5&?et#MpD+OU1S7$q$fpoZ;K#Q+Fc|E|( z(YWf0zu~E6t;qVTwrx8p08RFX_9`&Gi^WU^vX>Gwm_Y|^+lXqmdd^PfGIrsYV8l2mNW&^fhwPJ z-hbls!p#Z3K?w#QJoY{-Xv{=V{U$%y<~lT*mfa~)$90@zqycX@y>xSeQRiTm3g9%1%{$L_@vdP+zJLFT>AG$x8 ziJfY4Z0IO}mWDlckGbR5^zwg!D}ObXZvyg-D+0(j0r|#9UI70CawmGxNKSF%00000 LNkvXXu0mjfmoyxT delta 2235 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 JPDHLkV1oAcSla*q From 060324c9d549c734c8f2d7554c532436fb6ddcbd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 02:25:59 +0200 Subject: [PATCH 071/676] Updated app version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 0edb998..a0fa417 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 52; + CURRENT_PROJECT_VERSION = 53; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.14.1; + MARKETING_VERSION = 2.0.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_NAME = "AdGuard Home Manager"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -553,7 +553,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 52; + CURRENT_PROJECT_VERSION = 53; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -561,7 +561,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.14.1; + MARKETING_VERSION = 2.0.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_NAME = "AdGuard Home Manager"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -579,7 +579,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 52; + CURRENT_PROJECT_VERSION = 53; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -587,7 +587,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.14.1; + MARKETING_VERSION = 2.0.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_NAME = "AdGuard Home Manager"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/pubspec.yaml b/pubspec.yaml index 04d834a..b9bc0cf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.14.1+52 +version: 2.0.0+53 environment: sdk: '>=2.18.1 <3.0.0' From 6630f18cf92f25ae60d1e43dc1b54c64d43a7e57 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 03:10:16 +0200 Subject: [PATCH 072/676] Generated Windows installer --- assets/icon/icon-circle.ico | Bin 0 -> 11482 bytes windows/innosetup_installer_builder.iss | 56 ++++++++++++++++++++++++ windows/runner/resources/app_icon.ico | Bin 1799 -> 2351 bytes 3 files changed, 56 insertions(+) create mode 100644 assets/icon/icon-circle.ico create mode 100644 windows/innosetup_installer_builder.iss diff --git a/assets/icon/icon-circle.ico b/assets/icon/icon-circle.ico new file mode 100644 index 0000000000000000000000000000000000000000..e4da1bd9d78e28e9be232efd2e8d5f89c88a8cee GIT binary patch literal 11482 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 literal 0 HcmV?d00001 diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss new file mode 100644 index 0000000..4887491 --- /dev/null +++ b/windows/innosetup_installer_builder.iss @@ -0,0 +1,56 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "AdGuard Home Manager" +#define MyAppVersion "2.0.0" +#define MyAppPublisher "JGeek00" +#define MyAppURL "https://github.com/JGeek00/adguard-home-manager" +#define MyAppExeName "adguard_home_manager.exe" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{41521D70-0D21-4A9B-8CD4-2760753054C9} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={autopf}\{#MyAppName} +DisableProgramGroupPage=yes +; Remove the following line to run in administrative install mode (install for all users.) +PrivilegesRequired=lowest +OutputDir=C:\Users\Juan\adguard_home_manager\build\windows +OutputBaseFilename=aghm_installer +SetupIconFile=C:\Users\Juan\adguard_home_manager\assets\icon\icon-circle.ico +Compression=lzma +SolidCompression=yes +WizardStyle=modern + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" +Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\dynamic_color_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\window_size_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Icons] +Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent + diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index 2f82038a537862ff2a05645269d432b09c97c5cd..6d25264ca039badd9902bb05e6cc063741250cc5 100644 GIT binary patch delta 2337 zcmV++3EuXH4zCgr000310RS*C00000AOIN&kq{|=2;fOXK~#7F#aanel-Cu$1OLpx zEHDg+pvV#tk=+%9Xo^Ooafus9B8ppcG>1fMET)N-9vh=1mTHV4#~7^}6l=98p0q)Y zrx85LQX@hP0VIe*key**_TKjoGhvv0;rMaxVctJ)x!?QmyYJrjh5|dm3?2>a8Nqy) z8Nt7QVFvre;-eUpi72B{I4BGh2}&zUElRblv8_Z}@#wmw;?Xn7gGKnkW5Q1=HG+33V`*@}-|uzEz@u@jtsg}emb>i8_|H?RL@)gjUO+jWYTZmT-6 z2re^2zl}Q3lLN0i`zdV5zIyMiB;~c1{IfS#q{EEGQ zKHIpp^T5CIWz|oNRy0b$d6XM?X1y^F7wIK1y+B6_9=Ja8ygp8iLJ}Vg-1^aAC4&UW z%nvGG0BR5Nyg;s5q_|e~<(b59q;KPX5fMPh&<&251fHQv1{^`0s z-7?WC&hl2pMTl~Xdo>TW1Q;9^@$+O?eZ$rfh>>K3%!hY^6M?~C=sbUS!pq=)&E`X9 zbs+6FZ#Uwz1(_IrU{VP2E&8(_)%y}r>@RSI6fs661^vytvg*9 z0H>y}ht#_#pid#SWjHn~V%#5pS>b*gq*YC70%-S6IQwte(wmUQrInBK46?XQtS}I+ zB)kP%DsrJl)N0GHYq%?8_alKCngI8;Y4h=4h_$`E!1aQ2Gd4m1$NCo+%J-p3thsv< z$~u3xwmB2S_jho=N~b74PoTzmS-o&4p#tY)H-jgeXKhn0_>>Ero|XoGskkO8x*l8G zJQ+!Br(9--lFe$VrLBmMpXC({Ig?+vOL+|hEDro5?oHTJbp_5nzH3d>QLLE2Sc)AL z5RV0SOIoP#k9d-O;Y)#Xa<)lfLm*DzOZ#Zj0;Vej;d+@W@Q0}${-`iZuPsq}XUIHy!#nuX zHH!#PK7uHU;lhkISCMr3`-$@)ef&!Xm9G^&gF`rTH(Gy$PN~=^K{5#(RDKS++wBwP zK)Bl&T@u)CN65<%!XFJgzP|t>g~Xg{p~MSKFjd3Vi3wj$O{E8aHHKU5wQ%vtJ*^VP zK)&l&%HV3t1KJA>C!oP%-$)pR=0rS{*z{fzNC@~C`?B+rB?< zRfs_dh{4QTFb6Ld55h1=tL|;4%ejqrVfmP7*c-kC*f>XjGMv#X&6V2vL zVJUhInM$31@->L{lkmM^OTdH0v3EEP>L_V-Q!y*d&mp}<3;bYT#8TK*c}dUp5rf%< zsb!Mi6o-sOplIv)A0@49{0<3_h3t@NN%fDV6ZwqFiy&40ntbmLeHFHjpY4btw2;-e z7E_XnM}552@i(x%*ijvmv~mK^8@6J?LKgA<$Yrp9#Mka+HXMDDdkuFel9tI^x=vtV z4V3I70q4h zoVfqnDg{67rPB-+^}$Gu=wKA}6_nBO4NZU?VT+6If5u%jB^@kGZk{8gvf7r6f!j57 zL3=KL)O+T?Eu6WLyD>jFVyd-5Wg<4T6D0XjnuFU(l%0fyt0qE;SWq^osv|Z|~4kYMrxDB%ol1j!D66pJdm*!&{TI zue_^~mXU%9%jJ@RTMzfSZAd)knix(< zYyrnzzmmB7Dn^%o==tJWwV~TcW3cLfw-V%Sbp569nJEAEPHu8sHfK%*Awf>I$!{iX z@m5_ZxsvkwBe(}WB$2VTu<6$-WQMx4uRiTLc5M$kCNPr~=^ueI3-=BZ^iM(wMDYZ* z_tN~_hMcL89k5Q`+<8y>!;@lJbyN93S-n)*X7>EYDE<#q=KNFFNXK*l00008NkvXX Hu0mjfSFCli delta 1780 zcmVR8sF$i9&=QxWo_t0W<}hDk4rf|q(t;2Mp|3NY%-@-N zm=5M0EsfA30KNS-a}G07OQkMgWCppog1L*in#5633^fAG%r}@HG25%DL;>0{XESFo z*D^n0-cyoMserD`-OLeMTBibb=2B)h^F?NVkz58P0v>1XWk%_0nmY7lo?y;mekGMq zP5>sUgK0CQS?T}}hEeZEqDlFMlmIk-CrNvkwgx8pN@gQ-jlTqe1dJuI=XEuHR7_8@ zn9TG``9(d&0IQfcNgRwt1kYer`TW;Cv+N#E4u(+0rQxn zwblT0L9e6ty#XQflgCh};Bb29+(Bw^HfgOQnYoPluKR_z0JzDIwU!)WvC)=+IrLa; z-+*bRBxF!rNF=>du#0M%?rW{;E#_8#W+@)5J|8rN1|4keXlG^~rFTe_O*=9snf48N zm8PBEPL&O{vg!Q*k>>}@JUqAsgfQo7DJ`CRba&><)GItzah`#Z33O=qJj!JeWwjMr zs)dV(h^uY^lbJDUOX=S}j`nclJK4ikw;(ArMi7CKD7<@JZFYFb*O*J)0&>)UmM|#{!U(h4X;)UB z;GOneKdUBd5;Fw?Mv*u%6k$%%NLte8DKfi!yb%a8TWLdTHpQ}={jB7unyjNCAWJrx z3-9+CNAr>%_AF4osH(4};}s=;R9JP5F7xE9tgj<%ydv34bqkHAw1{{b5z|939bcf# z#l4>pzG3BdDr-^(1fg&T?(>Al|L zC?z7Um5A9q!d=+2%`g0h?l(8eHLV{6beBpIW(}q<({s7!k^`p6zkP{+e!lgGTx9~9 zoK6nzifL$6QY!&&jPE=^2tD!&c2ISr z!^8k|j1-2lm)n~)lg6LeER`%80$LlS7xHhH(2csgp67{iX=F3EjIz7fr5A9!*+y#y zJjb^EgXbLx!k1JDcsI5F$2x1`*}!L;by0pa(5J@y_mcmf_8HkYo| zR?^zy!!6QI<*3vkR6sx(GgWU%ljGBAOKCop)RYU)cj{{>_l$$88tSOo%d5lorzT|T ztY0S4HMd)&G4qD+Q(ke62ti!900F0rDlMZ!S6ax8aAohC0`a#cfri!Pw7#yn-LzU9_IWjlHf_`F}t? ziDyFsyaklIK5UfA-Owx@@9RMmPxxl1>{jM;=AZ5dUn9lGDa@gPa%Z2~MzMCIFK9$y z^_JPhz-&JBe&H(sjvJSD1r%UHU#R|D-~#}5HdC3^-Y@;R3B*P?viL5*_Xh#k6)qJ| z`hE!1KpZ1~V?yH$(%g3KQViT;I{bZ*>S3J6yZ!BhxMBj(^UKM{?!6&rA`a$1BrbGq zGjjt2*Q_v`9a4#u*!Yi31n{_ANY~#kMZi47HS1})gi0rAF>?rsH}p%GhU^FZ0KLA6 zM4PWsl0l7^ao-d=NDMh}hbwuap#oT4aTkq$0hFm*$*9Fm-Xd`%aGR4y;<_=A#QQb1 zz{ujy9&i{pHRRXj=kf27^)BLSW;7GK_5LJYPUF78`|mc`Um}Lb5gr!GqvRD5XvKfP Wr<*Wv&Rcl^0000 Date: Thu, 4 May 2023 03:29:03 +0200 Subject: [PATCH 073/676] Updated linux build version --- debian/debian.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index 8bbb6a2..ddc864c 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 1.2.0 + Version: 2.0.0 Architecture: amd64 Essential: no Priority: optional From 3f23e4aa67cdd967b58a223655019d9e7b3e28b3 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 4 May 2023 04:04:38 +0200 Subject: [PATCH 074/676] Updated readme --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/README.md b/README.md index c4df27d..293e8fb 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@

^$czI|XN4fx#SG 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 z zIQnamr+J~rEse|Kkl8ZrwHXccobP%X{9B9|cKhJ}R7HZ8(4z`q zrex!k4R9VlYd&b6|Cn~UP?)S$s<1-QQ`HF!j3?`#rlM~wSn8|Y%EaTy? z-)Hf8C79OU<(y&3X6;qsLQhZakRo*#^7sYu*T!wkuhXM z{dXJVVbI@$-0$;f-eVO^(QiiN&ie6f^~1~7Np4w!Moh+^{H_#tyvPDM(MDY_ydU;C zZR_Al4q8!=!I$wk!dme@6V0Znl{|KOl=*7^%j=-c4Pp6=pTAE|pMOBJ?FXmNb8<}1 z%Ty9NKZXPLn&E0Ya}7Durwubig4$*e4xMvlkPH|NX7(T zu%&y3y&5jFAm~5{nPi0j!ohjqF3DS(+=YiWMjH$Y!JH&z<7S2mM227J#dQ|cgY!DK za^oK7-7(9t#2;6Yz<*Nt2IaoqI|W)OuG9^%CliF{L+8cOIYbRy@*p?5gS|Edsb&MK z$$N^{`L#D9V2fmmz<)qJ7 z8Vf5Cwd85S%uBcynByc4VNF zx35=b@b{ZR_cf+|?;&%p0@Frvwg)kr&!I2ckUHc_AZeK|{X4&6(L6%_<{-WkDA)sV zwq!GukxkC3IW60!YjPbgC@t%~f=OM`(2YM_H@kCD(J$C9CMOb_+Sb^yf{t9q-g%** zfpgu^d4G1IZog|_z#rp@Kc~omBpvWp$lC5ZvaFMYUo_)IiDGbIPRn5Xl>-Ue8>Ty5 zKI!xcMRh;Yz1a@WfmZvaiEMg}@9FdVr)8(W@xn^zzr2r#*e_;eVJHkoLq3R!O~NMa z-W;?g?QP&gg<*pFC$G8a0UZPH>xwh%YW3%`8Gi-HCMHY2L~+{QFEPbP*qyAT}V)AyK{pkQ7uGSkiWWym`xNe<75CBTAX&uiz^`*?}tT>yBs z!-CidDiL%n2HFMkBPn2_VGTlnS+PLN0v!`20}Zb%dJrI;rOy$itv~b6pdE;_abX3r zpRJ6~RK|Bl#P9mcZ}OqPF?o6j(oaFRjDL2&w?>;9^zUPXs1Gt$W=ibcv!K zNnIYFS#%i*!kBSBoniW^`|A}fD5%r$=moZvvPT<}TmKsmYL8htWQjqF<6LfQz6za) zys;p;D)00GC_gE_ljNiC3fUTX^D%OD==>NVBQKdOSj@Ly%oy^{(VtJO8h<_H7iJjp zLv^NG>oL|*1}z-e9(m0iIRu0_cYGY0c5alRpelIh=JAW%alMz45=j~h2$d%5RPrsC8SPt4Pxvp+A$SqTW;|_4J zU^C{oyb+IWoK6xLt08THMLRI4_8luyG^mgRf8WmjK0fW^T>yB&!-2*F?nqohKr+D2 zJ27A!=Lq_Jk$nS6qQM|85Ge1z)P*OceCz+hU@s_aEMQf&1TNO_4}T)!`=a8nM&?gO z#h+qKm&NEaPmmlFqla-PfdH#MJ+?sP-4>@SMpEW00Bml+yDQa97B&xyb^tqVAveo< zPBLsf=sVYG>Yd}J0KDdDrzzA_lN_&dV1m@N_zHalRwrGyVUrUi3cg~JW}}N96AY65 zk+78H2;R>5`Rp47gMW6EudN)1=;Rodu#ju`m=kR5l1dBQqD`;8VmsQ4y%-bnvLNer zxZK+&%Ei8{Ys$pbWW@yyBww4qQx6>S6}vIHNd4WqV-s-E)AZOSn zNl5fEZ6Yd`Z0#PyoAT?>qZ^E4TNox;=d`;pTcBMV&Coe)&KTT2gz*b)fiF%& zPM;6EJ)=ZNgnxX=4qtiqeld{$+6h*(y?s(Y(B~P1g*{9{O|FnXa4%e6&U%K|H_(~`O{7j7Y06{J@k(IFg|QHHAWy-(G2wbHs4h5MWHwt zcCZwWs+3LePo&b%+JcUx>|h3!HVKBBtH-A=7blg#6o1;D`(~ce5`P79D;^Ea(E0Ha z-*XBdin|3M7oU_K{lzR$HBZ&PI&h3WCwgGjK2g<*ICjqX?xUhlI4@mv_|wYz$*lOI ziuk_D_yf?ampmI070LmCyBr@yAoQOsP;*qPn7h9~CM@D*k_S&`qwn(%zuU>($9T_{#?kRmj2(zr+&N(055hBkTMA7a2r*aL(Un&pg|C|K(;IV9E3?u z+9``PMvDhP{Pop24}b(Ap0H~nKp6>4D7bJ-RVNW%OvtF;h={MPh_8r@|L8pKgd6+- zk4h)SO1B@fF?#R}8044USARf1zEV15g`gQGmw%Qkf-GsVAjU+*;v4Xlax48eF9Z{! z4Y{Df&%*+|I_*IovCHwD`s81OcVzKf-aS4#vVSF1%zoNb#e`ed2iX(;MdcEeCB8Ysx-zqDWX*SfVGE!1kO#zzY2h0`o@^Tw!K|lf}?vCYTh`6in_* zG`yR>WpcU-emyF$mD*A^NRk4Hl<9%@m;CuUP9f}!>o{90xs0Bu7$>PDjkutHWW!dp z%n-Wcw_03<}JQZ3t6#hgDN-!-kER0Io3RxEuCgu|vI_Iif~U zVNMX24FZ5MR$*(nJznAC!v-Am%-1wv5`bjalBZtiXb(N~fC;_!$>T>!`n>SWZU*Y~ zUzbxCi!}poe4#I&dsKWa*`@iJfPXbRPN_6+ssIW9DI&fiBEGgVek0u`qlhuYV7F0| z)%njde)x1LyOL`p;||HKi1CQn(t^()R6IF7Aof+;O4Z&mRT5FCNQ#1we5e0GVKq^x zGF`rpmpR@AfEPQ6E5z0r_^*`-0$;e-6Uni<#(2GPJP@cxcO-=IrIrs9K!5F-tuTNv ze$GYPIyd@R#9*=&5&jJ2nRF!Z<>w;evz77H8S%^L*hBgb;FN`dBa@Ykkyw$NLWovu zr@RnEoOcGFb0&3xH+z!BpzZ@P(sJD8zo7DS0kTA z8kZ+z>InewUaV1;o)jP*8Go|3fa5V%(Mww?!4oHb*3IfNP|Qg?$F_dHENMYc9q7nj z#dI1YaS-6LQZ~j!V%$yJG)7WeAfvDOJh@CK?d|Kevc;BGrlzsdLV{+n^?^Z50%N{-*VnEj#zSp_4>UJNZBNIDcEb4>BcF^YfIg zIha`!$7Mf~r(huO?o$&>_#5t|#UFflhDU4QmoO!N;Eh%aQn83I0Xm2)^v^H5eOE48_w8&_P2*cfIG*xmyD zo&SK1i;uv$GcZ<$!Jm7@nM|aOE55J*0P3m}5KLSqeu7C&p;(Bc9bht+!aPo-Qg&G( z9hZ0!PPstMSIj=Z8}5U9%C0jwDTWORg)ZkBeotDUUnvc%{C_CI9k-Fg(LdO~{RQs# zSj=Vc8CKGc=0&lA(Y7V!6!c5yA(z5=@GN|TkMe38)FC+~pA?SmumEQ8_|V+7Q!MIh z3%hM^Pf%p>(QFAOkQKii5nmmZpN)v0JG9M0fq6o35g_r|^bKr8o=jny94G_vGJjec z_~^noSkS|ZqJREpat6a!?&|W)@waJ15h#UA**1BwrRYl^mBQc0r+2&y055hhF#<02 zSx;o(+a6f(htJ`aJF0?qJ%LEyi~xV|L)#HOKia|GL5V>lY|>%Xe2nd@NLGXtIEFwT zc{~C%gVEW~`_mQiB~|&2S@CP007WQ9dvL;KE>aoD6@Td{CX0dO#Q!S++DOh){jfGm zezb}Vpl94|VF~EVCMm6w4yIct0DG^Dk5wq#%%G4Q1H}7ej5-M$ zn2u}0{?TW0;)?hxlcZu>WwJCKatL;7 zb_?4AF@LZ*8jFacucUM=qx8TjxxuDcoPokfesOgNNz7G%D@+#Ej#~|r><0W9?P#n) z7ctqH93q&&@LqugS8AO9AylK=6KN(%uDsIM>d8R1unKYtszNJ+EEM#R2~U-rP$;0i zvoiw0mD;$8Bx#DUb+8!kynr8-`4e<);BXaA%zp={uMGNZI-O}_b%VqCIwtb8~9J~=7uda2f#IR_GW+IW*dXak0V%>-uW#16wx;L~}0 zOzAu(CVZ@{Tz-gmNY-WJlvbHEa`OoL5mqP`$bNti@Lg*K0g+xVSLP3poS0uY( zn}5ofTv#9U+gU^d_Jab*W_DznqyIVXH7|%0!-86Om~fyl#)4yKE-Cv`?HC~J{@W4E zT~Q99aZSf^K8oF9m`RF-lThR4{}gwcN6=PFwP{#duq)H02cki8BA85nvw{_JDmOAy zeHRiO9|Z8QK`zu70gOigqm*CkFkP*c7k}Y&HqGrXB`edeLGUgc62^5~3RSrj3Q62$ z2zr6{6~UjjEEHeIg3f=>h;NLjFUhE%j)*_!?F3;+rES}0^~`5MEOlx^8gf|hYS$Gb zfcNH&bUfK17h%deX+B5XrmC!6Io@08H_gn!rq zmH|8_$9xVC=WTUQ{V4$e;2~gXg+h~CpNtMl9bY0?=_M$61~Z5)yB<7mxZQsrR^!6K zE+eacKO+8BMf{bD_|C}q6-_$q9*(UcY;kJvc8U!R&zNj@fVX6Uc|dhr3*N+F%BH2x zfI6$a$|)=yCax@q=z00Qi!pX2Y5ORbCm{d zz?&BlvLu_OsFM^Z$sTWywiPGZrQ14WQXL5Uo@zRH4<iW)~Fup!)r!T}M>kjVQf@(cepw}@tCCF^&>!m(P;m=I!Y zByE_Oz@{dYrS&O{#aBEhUQKtBr=x7&7E3xNw^Ro80$NFs7e0Cf7^%|=`hcoKRY_mv zCE!5cTXqAnPb3_Tn!2*>&wpRIHwsPxpGne&LgdjQ@K-#Z$tZNMNpKBb8hZ+K%bo>N zradDX&nRQkKmBvA#&WAYWD5WCyD0M+KPWfYBpvYxfiLJXxe5OoKT$4)?I~Rr0amXfZr^zYuw7_g$4ho8AJnmVt)efQtp0GtRo(? zn{0m5Y{_hFQ0#bNg~5S6hS78sUkC09H*lnjkF2@ay(fO_UTD19uC^#_nT9wr=hP@} zv`m2mCVKK)qLn;Q2iA6}4OmNmiiwpYC`QK*4H22LneBTK(6O*q#Rct30nQx1SPKIK zz+BSuL3T;00_VkeMSuNDWqfBu{N*}1=kMDd0^{0>Ss@o3KGpVC{0x62g8>_ohRw(j^-nY6i!$@OqT;{lGUVB`G;Qg`UWo{j2(hBB%I*zKQd3}iXjNh~ z15#*W?&BfRnj*Iw=a#J^4ISJIG?aoF`)$B?bVo#u8WU6mkiiR*aYgaL558fQO)u9% zfXYt%j^kw)$~uNXVs?ZaC>AB!+%O<_480Q5-I(R z4-)MnU(-Hn=!}!Hu*4-!66UMeS1|0T3Ss+NR8SC zw1`55Zmd>Cq$zfxE-Nlv-Dx49NLT*AA`(Pm)d*T*(Fm#VG%>LcXcN=$ zSix~|otb&h`P^COUc6o*-{-!s>+?B3X6DSyne(}>yL?X-LDhY$|LvlU-9M+I+w@C% z;qUt9tbf*n`?l7F+3#d3k?J2gIYp8F@kce(9?<|@UWhUNq_d&Bf9NR}h8 zY&5P`YRw+)x)18BRv}Kk>G6}Kc7xJoH`RyEhBzjk8B++-8i!Qtu1=qH?P+8CT(=0b zb$|N8+aB3jq4Z^teez#Eadc2Ib!>Z#+7)xwl7HDuSzi0tb4|yTkd4%AGs;_yUs=8< z$|uYVueBDo;W%x%FIRT#hz>rr(qA370VSDLz zVBJmH|3)U|S7Np8F=p0O`H@usEE{W?#^@sFwf-_k)P7}+a_$@rh&1+e$gC@$N!wS{YjP@L!BDiKw3u~Im*sL@{cgM zm2O#_RxKE1AetNvB&{_RwC)alPH{s%(T&%y59I^VZPWpG7RR8%dKcUu@JlN^a z$g5tsQoD}-c0!<8AAUOFwH^zlmVfk*%sdsE4Pf-L?B^%a*XAT+qx?xwtoa(fX0?@y z#t1qD_wAQ#!nSQ^NA|K^D-evKoViSb+k;q%Opfr*`1+{~8+^6h2Rl`8iL~y@a$Lb@ z3@J-`vo{k`cF|^ZY#WD87^mG%c*1+FyyMK)>}IcM_0t3Gxw^AS%GSE9b$=cs&u+Ko zaRv|({dC1^%|zSc+!ylCdoR_z1~~eO@ugE>ng9DqQ=JNTQKqadeV*fkUxmB2>~rnf z%JkZQ*?Y*purrpp!Rg%Vf8NfwdJi92>ve4s%_sM$y#JAOoiO%L zD;QQHo>Q=>9##>)a3bl^U7$iaGwuPU?EyS-aj(+e*D}#a1A4|R*L(N8uQ$LGv;abNH2KgTbgxp}c>wCjbB8T!m=+OZYf zZF+%RnlV+O!i(-Do5TD8uw+RIcPT@I$NioSB3Ql9>#K3%Vq3wcoP-L}?(pX9?f z$K}i`=-0TT(}~mm1YvVQleo4+ncy?dt4@ZFqo2z^jMUGk^ndA8{o;|Pdd9{q&0B24)<5?!!L11ikq!p9ov;@xGXS3ud!RsVIQz&a$ zWZDUM6<|hqU4L*fJ-MDsKK-|sQ|pAf?6zC5!0v%}lu!v`C5xli-bHHKef76PbSGTB zGs-ceF*fV76q`q?ueCpkc-ST@+l{>De`Ff!P0)RE=9|$TpRMm#V(Mwq=)YxOr~H%7 z*g8D(F`;*BWq&H09fPa2Q+iWhzv(5enSX5r>~Q?$1Ai}<>wZh}4Nm#5>M~qF-D&$- zUF{yf`Fj0%{#CD!2+q&3PZ{0c);*Kh#>l?(VS`yNDr?=A>@9igzURbkHip-lFY7Pc zvjT5zRF?gXqi>J66lcXe*F!CaT2f`RtNpbuTr%FqwA0eB{?^H{S*nf4XWbGtUG#r* zykN<6t$+HdsvUjI`dgc$(VEG9UQ-n|+RnX*QKQK|O@8&^aXDoZII_%S!bkU-jXkYC|t(D_n=Z;xJt-F#&nm%l^=f#bh(_>@P(`rTAFppl+ zUmWA+&BTTfSoAHu|373w*^uCFU&Y`*Mo1pV!hK9`E0 zPUTOe;^(FKa6}t3cC)18B-|^>C)X0MHE2G(ggxb?5q0#aw{Dhy(585##rfw6+ApVIl~+5E=-a=Ugqb$vP9N(i!h=~<*^ydE?n?rt>2jY??D zDTaO{6u*#}pN`Z|rS#cUezix`GVvO>`hUG~_8Nz}j_yPAXIipfPUW1`o(yT9W4t!F zw^#Qvf~OUenq4PPp|Ob?;|fC)=H_6?Y(k|5Gn#ce7yWX%^B!?V`~DRW)Qws)-68S1 zy6kN>j-3={op8K0o3Pubjh#qZV7pF$R|xDjc0y=U>G^mGzaO!dtI_VsR|4|*bAMem zo?Zi6uU_$~^*7_FBqp!@>q{ z(QPzJfP00^#Yx*7 zX$l{4U*{Xbl1CL*yZ}=2o!9!mu7A&p7ctVV)++#X;weky$2|6W>0*_wh8!Q=DfgJI z8^NrI9_Z2YI5KwwZEdw7D}{9ttEKi_Cp9?he&#uoGilW3W&G=WJNXn1eVt8V-Nw@e zn2|^ISvngDPPuc&m~)2}2qLZ)qb*eH&ePG$zOubUtR5%QwhWJpc{OFuumpSDZalW>-| zY#oe!d9mji&*%5D>G30PXtoRI6W6EpT1gW>qWjgX>+J-8h&2z~TJifmzV{V*&wuqh#g`qKy8UYN@)zz0`->#I(41dY=(AG(R7#(g@)soi zMsL2Y$u8d9`pUIkw^7d++dBG5uzJ;F{OH3a;PGikVfQjea%Ezd^?Po$?6@BRo;K&n zF^|2k0Jie^%imq)&0D+hj`;20?E%1(SU*f+87CU84Rs|uc0%E?DSx{fYi^>w{JFy` z=Y6v~&IvSk7_A>BX{!o-ofuYPP|m$xJjI8oq$lO^w}V)y=X)n!_m^eGaZa^w-Oe(U z(&rWWd}RD^N`FPtU(C!uSIKDRmSD-OOC(2@eWK90z$6?Mcw4;Z_19izlD7%2BgeI= zExFaHmqjcP+-3j(Ab$W!L_t(Q|MH{>?6M$ybUk^}b*-IXnNH{6>FCRhspr-Gr0Vb0 zx1-OIn`~TuD(~{B`H#tY1w1N^JA>&*!H@2uH5L7+c+I)xQTLBlH6PD-hSr`( zC4#>3G(FX$(DOxIVR>||)zNLO0ofRJf^H`Rwx;JXz&t-+c7If-{C0Xe2}Sf%J!M1d zi?uRL8a+(2tL*;$6ua(S=|!*S)8-7&Bs|j1HtvyikLKLh*0WAdE7{BT4I|{z&z$`D zJ^RWuop@F`wr0J_6SxxSPKLB(+44JYmT#(#+IDib0rS+0+s3lS)ol5q)^FK(h9%=W zQ8Xpbtoli;V}CUz2OHZxkOm%m3(utH8JK_Yh#@{Et@#^ zwN3e$WMh!oZp?{yud0&uk=pU!wWdclcL8n2v3z0Of95!XJMpmMKTyiy@*Mm}bk-G0R zKRIpn+a|Y(2R>G#yr`WGI{A z_<+1xv47(7k>}CXzY66)mEs>N^<^nF-#6qw*ygT~4XDSnVy4Pw_S&~$_SNGrJaXLY zv8Ljsk+@{$|1OPM`{(DSbem7NFk|l3TWiGwjoe1=XtjlOj|jf|Pyl#$l!JQxT#r*# z=IDW77QY3ja;SMu5A1YWmZVvT(|l2hzdDt~dw(gn1HXz7vvKqawE9un3F5JQvxn9S z`rX&s#93$vYh$G&wIR3yrpoE3Qt{=G{zfYQb}0UQD*sX_{#r!*-bq|MZL@xR<6G~X z#4zr8dElwUY+T{%c25^I$yo=7>BpZjpW?{qtv10s+~*q3=(r-hC!?0wwGExwMJ1lc zGJh%_)v&DHo!CsfW<9U#c2;4slG#r67cKLy37EWg^7IP&41$qUxk&UMeAzMBGenGmVE5KteV(9wscf8 zAE(-L?0(9(wY(l4XylS3&oUD)a9YD_!(Q4b8{6~oOUA}t{p~g0HqhfKo86w>yzbFa z9v^e3rX!J=>5-i!tZ$Vs;+k8_-2F&ia_O}-x@ZZyPcy$+opt=kk*!%ow>y68^?&bd zs`Z?A&RE)A+lpTFgLHvBfu@g=S$TSHf`+g|qer{p=8OdM)^=z@2wwr7Of zr+4h_xw(~l&#UBR9^$^*^E#751%Exe-*XF(4Uet9>A8zWEtt#kJVsPH8Jo-2$1UGI zt7jR)bvAKs`%UjXyPeVal(pl!ZrO1Aidb!2PWFFF`B^FciKKs-ijR6M*W+1l>1(;L zb%MY9+L2%v{zgLM8?49{7z0g^L1;OoPSO^{kh+F zT|QUL%z3X3cn?qjc!%7l6p}Q5)@n{gJXkps?Cl@o8-U)RG#_PXWf^>sm=EZMqYWYjaXjJ$4{xR0R2%ae^H@dROZj6^k<~_ zOiF(`B0oOkJNh^Y!aU(-sej!%K{BWA8?~0n4l+I7cFN;6TW&oR-=J8)Nb4a&e%euE z-G3(UN(`;vd1s%#ctyLe*e7!yylgAGPFIc=mSLW8*+!<7)kE4={#JtSLT-JZHYV^@ zFshqFv#KUczKS;0(&Yo&^ImE6}>uGdbFByAaa@x-NQDSu+wp^gIly-L2* zH;tZTjF4QTT}#O6&7U@ywy*+57o-`Kp~#Y29gKymUO9 z=^F4(Dz~lI8X29e^nWjXwzE-_{oCuHtynMfVAHTldn{{TT(TA_` z+4hrGc}cm~_LhCFmPevnLcSJVgEQ{udb+oM)9<#rQJKfI+kY~4nW9EIuk@-&x3=*o zk9$UM)?kCoIUGsaCE&I+XZo3Yj z-ufQfoh$f%?-t_G{?31g+Z&8jwx4uqq*C#Xlzu6ce^1iCmg0k5y3~@{)=>59kk3HWp`w1)9*#TWk)IJWTHQH+V_Jn&)-F`?ZrB&p* z_3O|9zWY!BcxQMh?4X;zs4JOC%@JJGh2|B?aaTfnRls|*wcUuU|K&sKU%Pw)l?52v zFdt7KcN3GAd$Mw;b75^8+Dm50E>N znSXUmYF;xl>;!N&C%HBXML!;$*9#|zy+oG%p7*1YT~)JB(z2g4*lXqfh`obvIE$o)hZ}(tjs1u1`Q$b3=Q?0e0t2aTJRO{wASYe@qd-+x<7Hg1GZ;mPaop;Ju~$Y?e+aEAneuD z_nH3c$-p>)AX<+j>$-c-)vd}UysfX_Sxdm=ydVF9cK`)|cSfHU_-j%-#k}5F)op(? zEHB5ZS-CK3(!jb?~~k$6MPo&KjQw==olN z()mvOe6y|^i}zGEV~?NipyM__x_|eutR=1NqJ*ra`%Gc(k&R1pkIlo+eSAIbtilQi zE{}CjuNGe=EBwwrWv45TR_ATiM_*iHKAQ>oC5byJP0dp!<5yx|VIz6#ifip_Hn6+Y zVltK|GxOW?{Kr?!yn3fgli18=@VQ1>Y_EIlbKoZ3~LF=bd2gd4JuB*42Xb zH!E>;yzQ=AN!P%!sk|-p9<%$0>ha7t=eO@vvf88Gn^BkT z_Ealcw6w+>+#X=3_jmh#r53$EwpBinu5?d*HE z2a&gNL{}%RA?dER`5J$0FzaJFZ_WD+@6cba+`WBgd-VQx)Y-Pb^>E}7{z|U*eUsP4 z+_*tjl(VYK=dk@PWP3ohmdBrsHn>!~D)Z2AA?Z*01Neix7 zDM|aC{^$O3nhx@BEr0m_T;OqN{yD{*`(IW4sTg+vTc2}%{r>tBCztRP^KoNM=-h>s zmPsiseoBfT4dstX@fW20@s^%#j#`hQNyO4xx8!^h?3Iem@LESc z%UrLnww9bd;oPa{PA+=*76fIR`dh*sYI@FhmH4hv-^rbS-+w`LTWLMq$%*3u``R$C zg2hP2!>oUfeYdwm@*NCi{k$cOT=&TonEkVdO}9{=>01f=*sRNblCswMSrdx%TIJ4@FnjNBl?ck(-Tu6fU1B&%^Odak z8nIKsJ&UKmeENinbCs0eEB3^kx-zBud*Hh?cTw$RHGeVo)f%i2quFTa8r!YA_Hy&( zDLoeV6>f2T?aLnA5HNMTl?C!g*#f6jMBbtqIA4<+2g4k zr`LgNT7PmG%&_ujQ2HqX5?K`bfYSShPW$9P9Gy zt3Ovt`2+veBn$5g3IOkp*#E9aP_J~L*6{gvTz^8?g4+&eR~OG~=X1)Q=A~}O^bAr{ zczE_beeG0mJh-QY9x|>VT>s|f#(VC$?wYXS+f#KszY`3f-3kq<4%#N$4^sLd75_+~ zzopb4h{!*c89yP#pOx~Hsr>%xb-uwkyxHz?Z=g#Ty1o!zeduM}o>t(Hl@+sHjKrM$( zv}asC8tJUrd-Nw+3+=U(x@B~)j~dT@*ERXraG$>BhP@T?SmIXRE&Il@3ep9$wQ&T|LR&o2Fed@mFvWhb`$k?8zrFBj=yVn@`KXQPzL71`M_V;$Qn7O~@ z@0N|6PS)y~&j{U~>8Z^T0CQ{wgxy~ZD&#(x)*tu$Mq%hl|)ImIB?v)^#Vwz#9Oj_=)TYp-Zq zIj@Cx@V~NhX?@m8G7~R{xw4Zz&dCk=l#nd-K@r}&< z&r<$fDZW?IAJOZJ1pj18KYuFe2PFNzkiO>%tFo}aWoW;wO`1lB_f~txWJ#$tIH{M* z?e$y8=RCi=y|@lmkWTeS2g0u2DY98$pL$u!Iyu~2cLl0>b)+#p?Igp;=X3Vag#EC$ zI-`$WavNK&!Or~jN*rQlHH_r9UT&F!R-*89lX-?PLoV@5e^bo{8>W!fvXaqYxjI)x0s{*0uu*_fR3WNn7?j3edmmCW+mn3x~vC0&cl{E_xJmlAuPHuBo+XkDh>Bpp5Wclr1R z_1Z-G2Jl{UuenM7Wnd;fD-eudam#6ozaHoB4c*bv*pC-1N`Hadf67`~GilvO>Tzv9 zzM{l9kD2x5Ygd6GJSIjz!e685F|IgR15!Vde$s;m~XtA8eI)p~*($hNAAJbzC#`-aE07vymr8@AVy(8!9Wrj}c z_u*~e8!Aj@6+Uf(+u5r9zm4m4XYv#v<`{^z72H$5NlN&$eyaQCV~+eJ$mnd3sR&4qxHR zD{sWIm;`ad0j+x!`|3Wn_tb;PV$6B@@4DP zm5m}rWSF#|vE?>RmjT@E;y|Kb`3&aqknLCRid0teZQ1gr9U!`SL zx=b8e?su)dxXd5_h>2opQ^$WvZV`t6*!U!EhGKdt4a zDwFN}iYQwGYYa3|p%@14oK+s#r2|a77N)EbeS&VTDj_Q}ZxgUz`bZSLLilk|6Y1kf z_z{a@!+31)*go(NRxxUNEp}$#Q;ZSXOd;qyfgb$%gf0+r<^Zw3AtWZ^tYd+$hFU9{ z{xWh1;6v74IGXW}2K1Cavu}ZaNcmT2<3Mxj3&@i=UYh{nPMztfd{MV`&fBg+OK#L}k0UMy)3LnXvXHoi(} zJ5oLw{fy9q@LruzmoA=(I}_7==N{&@-r(Z)(nwr?{}+m2T(^V#&O`Mkp(mAIV> zy$((qpn)C`Z||B&%YC5PxZ#fGq266Tq|bK&JN@5_wym-X_v*zq$u1mSHVzFcG%ATG z&k(nIeV1qCN>7xf7Tvh&$6OkpDPm!o?)h|8Lqvs6^uH{bhi7ZI%wpH<()t}d1wBBm z_iiILhD0*YTAvW9NT}&~-6~mo3g&D+m1(N`5d|DDrlQ86=DJg`L`2u8oM2*&lW6Yy z*}g*B=vaa5>A&4QLxQV}(oqQw17y7St#?K>;9o4A8G=|3tp8O8csNAGMlXaH6B*=2 z&-XWKW-n19@VCTsUTWJF$JSNEKv-8jWI?~HBq8?AA$p%@ z!0WG-*6|ynT8evnty@tk&42Vhs)`;<=i&vGa%G~qmypM1cC6UrNK?&Rj>QO=zP>x| zud`iRnBUd0JE&n~_4P$=z;F&~;I{uP5!u7Zes_+VHFoUqCsx$A-bMhN5PMoMN?-@J z^id|)|K(!LuOo<62l%Y=Z~h#F23O63MJ8hP_e!S3*9s(pCQWy_L)*rcZZ`4#6Y z=|*w^zU;t%Vn7F}Ce{Ki8&WIZfw&#$?lJwmwzrJ=XT9mdu~H^NX$zu zHg-lgNnxOwU5%0{uNNshZOk>k?d0n@IY(3)8IUDvF&_<0av`I8+37LYJl)*^uDYK9J zHCH}rkaH3<5``u`=D(B~(*Ll0J`mI>L3*DhjJ+&PV60@lvG>>ew$PUz!aLL*$Ik2r zOQueSXbQg8U~>!2s{BEO;o`*3XM@FH~4iEOr2Ao6ipn686S@7xeeo7lb7Mk96&9_ z$tL_beZsA}cZkyqcCSxZI>k7-9Vgi$wjG1U=VGFmU^uvozbThn;S++a%ioiC+k-d* zx2;Y(PDzw7x+a=pB+x8Cu|GrqAOD|C!2c%x+iFT3 q*Zm0p%q94H{viII`WJtJ7uO^PB3|(0JI6npBF|ko%Q*ehz5fF1h<2g? delta 339804 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�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

- + - + From ac4dc2c7740f1373b221d52c5cbbc782e8f4217a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 6 May 2023 02:46:29 +0200 Subject: [PATCH 082/676] Removed context snackbar --- lib/functions/snackbar.dart | 1 - lib/screens/clients/added_list.dart | 4 ---- lib/screens/clients/fab.dart | 2 -- lib/screens/clients/search_clients.dart | 4 ---- lib/screens/filters/add_button.dart | 7 ------- lib/screens/filters/blocked_services_screen.dart | 2 -- lib/screens/filters/filters.dart | 11 +---------- lib/screens/logs/logs.dart | 4 ---- .../settings/access_settings/clients_list.dart | 4 ---- lib/screens/settings/dhcp/dhcp.dart | 6 ------ lib/screens/settings/dhcp/dhcp_leases.dart | 6 ------ lib/screens/settings/dns/bootstrap_dns.dart | 3 --- lib/screens/settings/dns/cache_config.dart | 5 ----- lib/screens/settings/dns/dns.dart | 2 -- lib/screens/settings/dns/dns_server_settings.dart | 3 --- lib/screens/settings/dns/private_reverse_servers.dart | 3 --- lib/screens/settings/dns/upstream_dns.dart | 3 --- lib/screens/settings/dns_rewrites/dns_rewrites.dart | 4 ---- lib/screens/settings/encryption/encryption.dart | 2 -- lib/screens/settings/safe_search_settings.dart | 2 -- lib/screens/settings/update_server/update.dart | 2 -- lib/widgets/servers_list/delete_modal.dart | 2 -- lib/widgets/servers_list/servers_list_item.dart | 3 --- lib/widgets/servers_list/servers_tile_item.dart | 3 --- 24 files changed, 1 insertion(+), 87 deletions(-) diff --git a/lib/functions/snackbar.dart b/lib/functions/snackbar.dart index be636e5..123ef3f 100644 --- a/lib/functions/snackbar.dart +++ b/lib/functions/snackbar.dart @@ -6,7 +6,6 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/config/globals.dart'; void showSnacbkar({ - required BuildContext context, required AppConfigProvider appConfigProvider, required String label, required Color color, diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 87cae35..f68b026 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -111,7 +111,6 @@ class _AddedListState extends State { serversProvider.setClientsData(clientsData); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientUpdatedSuccessfully, color: Colors.green @@ -121,7 +120,6 @@ class _AddedListState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotUpdated, color: Colors.red @@ -147,7 +145,6 @@ class _AddedListState extends State { } showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientDeletedSuccessfully, color: Colors.green @@ -157,7 +154,6 @@ class _AddedListState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotDeleted, color: Colors.red diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 83cf864..3c05c7e 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -50,7 +50,6 @@ class ClientsFab extends StatelessWidget { serversProvider.setClientsData(clientsData); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAddedSuccessfully, color: Colors.green @@ -60,7 +59,6 @@ class ClientsFab extends StatelessWidget { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotAdded, color: Colors.red diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index e22e238..c9e72d8 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -121,7 +121,6 @@ class _SearchClientsWidgetState extends State { search(searchController.text); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientDeletedSuccessfully, color: Colors.green @@ -131,7 +130,6 @@ class _SearchClientsWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotDeleted, color: Colors.red @@ -168,7 +166,6 @@ class _SearchClientsWidgetState extends State { search(searchController.text); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientUpdatedSuccessfully, color: Colors.green @@ -178,7 +175,6 @@ class _SearchClientsWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotUpdated, color: Colors.red diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index f2ba43e..1a86671 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -51,7 +51,6 @@ class AddFiltersButton extends StatelessWidget { serversProvider.setFilteringData(filteringData); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleAddedSuccessfully, color: Colors.green @@ -61,7 +60,6 @@ class AddFiltersButton extends StatelessWidget { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleNotAdded, color: Colors.red @@ -120,7 +118,6 @@ class AddFiltersButton extends StatelessWidget { processModal.close(); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: "${AppLocalizations.of(context)!.listAdded} $items.", color: Colors.green @@ -130,7 +127,6 @@ class AddFiltersButton extends StatelessWidget { processModal.close(); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listNotAdded, color: Colors.red @@ -142,7 +138,6 @@ class AddFiltersButton extends StatelessWidget { appConfigProvider.addLog(result1['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listUrlInvalid, color: Colors.red @@ -153,7 +148,6 @@ class AddFiltersButton extends StatelessWidget { appConfigProvider.addLog(result1['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listAlreadyAdded, color: Colors.red @@ -164,7 +158,6 @@ class AddFiltersButton extends StatelessWidget { appConfigProvider.addLog(result1['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listNotAdded, color: Colors.red diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/blocked_services_screen.dart index 2c0912e..e389878 100644 --- a/lib/screens/filters/blocked_services_screen.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -104,7 +104,6 @@ class _BlockedServicesScreenStateWidget extends State { widget.serversProvider.setFilteringData(result2['data']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: "${result['data']['updated']} ${AppLocalizations.of(context)!.listsUpdated}", color: Colors.green @@ -113,7 +112,6 @@ class _FiltersWidgetState extends State { widget.appConfigProvider.addLog(result2['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listsNotLoaded, color: Colors.red @@ -127,7 +125,6 @@ class _FiltersWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listsNotUpdated, color: Colors.red @@ -177,7 +174,6 @@ class _FiltersWidgetState extends State { serversProvider.setFilteringProtectionStatus(!serversProvider.serverStatus.data!.filteringEnabled); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.filteringStatusUpdated, color: Colors.green @@ -185,7 +181,6 @@ class _FiltersWidgetState extends State { } else { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.filteringStatusNotUpdated, color: Colors.red @@ -208,7 +203,6 @@ class _FiltersWidgetState extends State { serversProvider.setFiltersUpdateFrequency(value); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.updateFrequencyChanged, color: Colors.green @@ -216,7 +210,6 @@ class _FiltersWidgetState extends State { } else { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.updateFrequencyNotChanged, color: Colors.red @@ -262,8 +255,7 @@ class _FiltersWidgetState extends State { filteringData.userRules = newRules; serversProvider.setFilteringData(filteringData); - showSnacbkar( - context: context, + showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleRemovedSuccessfully, color: Colors.green @@ -273,7 +265,6 @@ class _FiltersWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleNotRemoved, color: Colors.red diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 45494e6..bcdb50b 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -211,7 +211,6 @@ class _LogsWidgetState extends State { if (result['result'] == 'success') { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsConfigUpdated, color: Colors.green @@ -221,7 +220,6 @@ class _LogsWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsConfigNotUpdated, color: Colors.red @@ -239,7 +237,6 @@ class _LogsWidgetState extends State { if (result['result'] == 'success') { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsCleared, color: Colors.green @@ -249,7 +246,6 @@ class _LogsWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsNotCleared, color: Colors.red diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 5b495a1..bc3646f 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -107,7 +107,6 @@ class _ClientsListState extends State { } else if (result['result'] == 'error' && result['message'] == 'client_another_list') { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, color: Colors.red @@ -117,7 +116,6 @@ class _ClientsListState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotRemoved, color: Colors.red @@ -160,7 +158,6 @@ class _ClientsListState extends State { } else if (result['result'] == 'error' && result['message'] == 'client_another_list') { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, color: Colors.red @@ -170,7 +167,6 @@ class _ClientsListState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: type == 'allowed' || type == 'blocked' ? AppLocalizations.of(context)!.clientNotRemoved diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index a12fe81..c45dfd7 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -242,7 +242,6 @@ class _DhcpWidgetState extends State { if (result['result'] == 'success') { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsSaved, color: Colors.green @@ -252,7 +251,6 @@ class _DhcpWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsNotSaved, color: Colors.red @@ -273,7 +271,6 @@ class _DhcpWidgetState extends State { clearAll(); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.configRestored, color: Colors.green @@ -283,7 +280,6 @@ class _DhcpWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.configNotRestored, color: Colors.red @@ -308,7 +304,6 @@ class _DhcpWidgetState extends State { serversProvider.setDhcpData(data); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.leasesRestored, color: Colors.green @@ -318,7 +313,6 @@ class _DhcpWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.leasesNotRestored, color: Colors.red diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index 79f478a..39a3303 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -52,7 +52,6 @@ class DhcpLeases extends StatelessWidget { serversProvider.setDhcpData(data); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseDeleted, color: Colors.green @@ -61,7 +60,6 @@ class DhcpLeases extends StatelessWidget { else { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseNotDeleted, color: Colors.red @@ -87,7 +85,6 @@ class DhcpLeases extends StatelessWidget { serversProvider.setDhcpData(data); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseCreated, color: Colors.green @@ -96,7 +93,6 @@ class DhcpLeases extends StatelessWidget { else if (result['result'] == 'error' && result['message'] == 'already_exists' ) { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseExists, color: Colors.red @@ -105,7 +101,6 @@ class DhcpLeases extends StatelessWidget { else if (result['result'] == 'error' && result['message'] == 'server_not_configured' ) { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverNotConfigured, color: Colors.red @@ -114,7 +109,6 @@ class DhcpLeases extends StatelessWidget { else { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseNotCreated, color: Colors.red diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index 7658c4d..fa538dd 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -87,7 +87,6 @@ class _BootstrapDnsScreenState extends State { serversProvider.setDnsInfoData(data); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green @@ -97,7 +96,6 @@ class _BootstrapDnsScreenState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, color: Colors.red @@ -107,7 +105,6 @@ class _BootstrapDnsScreenState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, color: Colors.red diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index 713f837..32ae872 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -95,7 +95,6 @@ class _CacheConfigDnsScreenState extends State { serversProvider.setDnsInfoData(data); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green @@ -105,7 +104,6 @@ class _CacheConfigDnsScreenState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, color: Colors.red @@ -115,7 +113,6 @@ class _CacheConfigDnsScreenState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, color: Colors.red @@ -155,7 +152,6 @@ class _CacheConfigDnsScreenState extends State { final result = await clearDnsCache(context, serversProvider.selectedServer!); if (result == true) { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheCleared, color: Colors.green @@ -163,7 +159,6 @@ class _CacheConfigDnsScreenState extends State { } else { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheNotCleared, color: Colors.red diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 55cfa19..be7eb79 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -205,7 +205,6 @@ class _DnsSettingsWidgetState extends State { final result = await clearDnsCache(context, serversProvider.selectedServer!); if (result == true) { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheCleared, color: Colors.green @@ -213,7 +212,6 @@ class _DnsSettingsWidgetState extends State { } else { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheNotCleared, color: Colors.red diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index f8165d0..d0d3ecd 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -131,7 +131,6 @@ class _DnsServerSettingsScreenState extends State { serversProvider.setDnsInfoData(data); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green @@ -141,7 +140,6 @@ class _DnsServerSettingsScreenState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, color: Colors.red @@ -151,7 +149,6 @@ class _DnsServerSettingsScreenState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, color: Colors.red diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index a4f8131..6081278 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -120,7 +120,6 @@ class _PrivateReverseDnsServersScreenState extends State { serversProvider.setDnsInfoData(data); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green @@ -170,7 +169,6 @@ class _UpstreamDnsScreenState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, color: Colors.red @@ -180,7 +178,6 @@ class _UpstreamDnsScreenState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, color: Colors.red diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index d9fe68f..203c068 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -91,7 +91,6 @@ class _DnsRewritesWidgetState extends State { serversProvider.setRewriteRulesData(data); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleDeleted, color: Colors.green @@ -100,7 +99,6 @@ class _DnsRewritesWidgetState extends State { else { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleNotDeleted, color: Colors.red @@ -125,7 +123,6 @@ class _DnsRewritesWidgetState extends State { serversProvider.setRewriteRulesData(data); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleAdded, color: Colors.green @@ -134,7 +131,6 @@ class _DnsRewritesWidgetState extends State { else { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleNotAdded, color: Colors.red diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 2392287..5ed088e 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -258,7 +258,6 @@ class _EncryptionSettingsWidgetState extends State { if (result['result'] == 'success') { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.encryptionConfigSaved, color: Colors.green @@ -268,7 +267,6 @@ class _EncryptionSettingsWidgetState extends State { appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.encryptionConfigNotSaved, color: Colors.red diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index fe428fa..7dbbbfc 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -130,7 +130,6 @@ class _SafeSearchSettingsScreenWidgetState extends State with SingleTickerProv process.close(); appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.cannotConnect, color: Colors.red @@ -150,7 +149,6 @@ class _ServersListItemState extends State with SingleTickerProv final result = await serversProvider.setDefaultServer(server); if (result == null) { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, color: Colors.green @@ -165,7 +163,6 @@ class _ServersListItemState extends State with SingleTickerProv ) ); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionDefaultFailed, color: Colors.red diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index bf67b6f..8f6db23 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -104,7 +104,6 @@ class _ServersTileItemState extends State with SingleTickerProv process.close(); appConfigProvider.addLog(result['log']); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.cannotConnect, color: Colors.red @@ -116,7 +115,6 @@ class _ServersTileItemState extends State with SingleTickerProv final result = await serversProvider.setDefaultServer(server); if (result == null) { showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, color: Colors.green @@ -131,7 +129,6 @@ class _ServersTileItemState extends State with SingleTickerProv ) ); showSnacbkar( - context: context, appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionDefaultFailed, color: Colors.red From dd8583a168f5569b268dbba4dc902b4490b41b3b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 6 May 2023 03:38:26 +0200 Subject: [PATCH 083/676] Added context menus and other improvements --- lib/l10n/app_en.arb | 5 +- lib/l10n/app_es.arb | 5 +- lib/screens/filters/filters.dart | 4 +- lib/screens/filters/filters_list.dart | 35 +- .../filters/filters_triple_column.dart | 82 ++-- lib/screens/filters/list_details_screen.dart | 352 +++++++++--------- lib/screens/filters/list_functions.dart | 141 +++++++ lib/screens/filters/list_options_menu.dart | 120 ++++++ 8 files changed, 507 insertions(+), 237 deletions(-) create mode 100644 lib/screens/filters/list_functions.dart create mode 100644 lib/screens/filters/list_options_menu.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f6beb3f..9caaaae 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -614,5 +614,8 @@ "enableList": "Enable list", "screens": "Screens", "copiedClipboard": "Copied to clipboard", - "seeDetails": "See details" + "seeDetails": "See details", + "listNotAvailable": "List not available", + "copyListUrl": "Copy list URL", + "listUrlCopied": "List URL copied to the clipboard" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 88940fd..068f8db 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -614,5 +614,8 @@ "enableList": "Habilitar lista", "screens": "Pantallas", "copiedClipboard": "Copiado al portapapeles", - "seeDetails": "Ver los detalles" + "seeDetails": "Ver los detalles", + "listNotAvailable": "Lista no disponible", + "copyListUrl": "Copiar URL de lista", + "listUrlCopied": "URL de la lista copiada al portapapeles" } \ No newline at end of file diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 8ad0268..ce7e858 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -286,7 +286,7 @@ class _FiltersWidgetState extends State { showDialog( context: context, builder: (context) => ListDetailsScreen( - list: filter, + listId: filter.id, type: type, dialog: true, ), @@ -297,7 +297,7 @@ class _FiltersWidgetState extends State { Navigator.of(context).push( MaterialPageRoute( builder: (context) => ListDetailsScreen( - list: filter, + listId: filter.id, type: type, dialog: false, ) diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index be4ff75..8f87b34 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_button.dart'; +import 'package:adguard_home_manager/screens/filters/list_options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; @@ -87,22 +88,26 @@ class _FiltersListState extends State { ), ), itemsCount: widget.data.length, - contentWidget: (index) => CustomListTile( - title: widget.data[index].name, - subtitle: "${intFormat(widget.data[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", - trailing: Icon( - widget.data[index].enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - color: widget.data[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red + contentWidget: (index) => ListOptionsMenu( + list: widget.data[index], + listType: widget.type, + child: CustomListTile( + title: widget.data[index].name, + subtitle: "${intFormat(widget.data[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + widget.data[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: widget.data[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => widget.onOpenDetailsScreen(widget.data[index], widget.type), ), - onTap: () => widget.onOpenDetailsScreen(widget.data[index], widget.type), ), noData: Container( width: double.maxFinite, diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 337a1e8..d8bc00a 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'dart:io'; import 'package:flutter/material.dart'; @@ -6,6 +8,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_button.dart'; +import 'package:adguard_home_manager/screens/filters/list_options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; @@ -128,8 +131,9 @@ class FiltersTripleColumn extends StatelessWidget { type: 'whitelist', widget: (fn) => IconButton( onPressed: fn, - icon: const Icon(Icons.add_rounded) - ) + icon: const Icon(Icons.add_rounded), + tooltip: AppLocalizations.of(context)!.addWhitelist, + ), ) ], ), @@ -137,22 +141,26 @@ class FiltersTripleColumn extends StatelessWidget { Expanded( child: ListView.builder( itemCount: serversProvider.filtering.data!.whitelistFilters.length, - itemBuilder: (context, index) => CustomListTile( - title: serversProvider.filtering.data!.whitelistFilters[index].name, - subtitle: "${intFormat(serversProvider.filtering.data!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", - trailing: Icon( - serversProvider.filtering.data!.whitelistFilters[index].enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - color: serversProvider.filtering.data!.whitelistFilters[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red + itemBuilder: (context, index) => ListOptionsMenu( + list: serversProvider.filtering.data!.whitelistFilters[index], + listType: 'whitelist', + child: CustomListTile( + title: serversProvider.filtering.data!.whitelistFilters[index].name, + subtitle: "${intFormat(serversProvider.filtering.data!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + serversProvider.filtering.data!.whitelistFilters[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: serversProvider.filtering.data!.whitelistFilters[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.whitelistFilters[index], 'whitelist'), ), - onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.whitelistFilters[index], 'whitelist'), ), ), ) @@ -179,7 +187,8 @@ class FiltersTripleColumn extends StatelessWidget { type: 'blacklist', widget: (fn) => IconButton( onPressed: fn, - icon: const Icon(Icons.add_rounded) + icon: const Icon(Icons.add_rounded), + tooltip: AppLocalizations.of(context)!.addBlacklist, ) ) ], @@ -188,22 +197,26 @@ class FiltersTripleColumn extends StatelessWidget { Expanded( child: ListView.builder( itemCount: serversProvider.filtering.data!.filters.length, - itemBuilder: (context, index) => CustomListTile( - title: serversProvider.filtering.data!.filters[index].name, - subtitle: "${intFormat(serversProvider.filtering.data!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", - trailing: Icon( - serversProvider.filtering.data!.filters[index].enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - color: serversProvider.filtering.data!.filters[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red + itemBuilder: (context, index) => ListOptionsMenu( + list: serversProvider.filtering.data!.filters[index], + listType: 'blacklist', + child: CustomListTile( + title: serversProvider.filtering.data!.filters[index].name, + subtitle: "${intFormat(serversProvider.filtering.data!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + serversProvider.filtering.data!.filters[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: serversProvider.filtering.data!.filters[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.filters[index], 'blacklist'), ), - onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.filters[index], 'blacklist'), ), ), ) @@ -230,7 +243,8 @@ class FiltersTripleColumn extends StatelessWidget { type: '', widget: (fn) => IconButton( onPressed: fn, - icon: const Icon(Icons.add_rounded) + icon: const Icon(Icons.add_rounded), + tooltip: AppLocalizations.of(context)!.addCustomRule, ) ) ], diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 92ae4e0..0117390 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -9,25 +9,23 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart'; +import 'package:adguard_home_manager/screens/filters/list_functions.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/filtering.dart'; class ListDetailsScreen extends StatefulWidget { - final Filter list; + final int listId; final String type; final bool dialog; const ListDetailsScreen({ Key? key, - required this.list, + required this.listId, required this.type, required this.dialog }) : super(key: key); @@ -38,15 +36,10 @@ class ListDetailsScreen extends StatefulWidget { class _ListDetailsScreenState extends State { final ScrollController scrollController = ScrollController(); - String name = ""; - bool enabled = true; bool fabVisible = true; @override void initState() { - name = widget.list.name; - enabled = widget.list.enabled; - scrollController.addListener(() { if (scrollController.position.userScrollDirection == ScrollDirection.reverse) { if (mounted && fabVisible == true) { @@ -72,152 +65,15 @@ class _ListDetailsScreenState extends State { final width = MediaQuery.of(context).size.width; - void enableDisableList(Filter list, bool newStatus) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open( - enabled == true - ? AppLocalizations.of(context)!.disablingList - : AppLocalizations.of(context)!.enablingList, - ); - - final result = await updateFilterList(server: serversProvider.selectedServer!, data: { - "data": { - "enabled": newStatus, - "name": list.name, - "url": list.url - }, - "url": list.url, - "whitelist": widget.type == 'whitelist' ? true : false - }); - - processModal.close(); - - if (result['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - setState(() => enabled = newStatus); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - appConfigProvider.addLog(result['log']); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - } - - void confirmEditList({required Filter list, required String type}) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.updatingListData); - - final result1 = await updateFilterList(server: serversProvider.selectedServer!, data: { - "data": { - "enabled": list.enabled, - "name": list.name, - "url": list.url - }, - "url": list.url, - "whitelist": type == 'whitelist' ? true : false - }); - - if (result1['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - processModal.close(); - - setState(() => name = list.name); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - } - - void deleteList(Filter list, String type) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.deletingList); - - final result1 = await deleteFilterList(server: serversProvider.selectedServer!, data: { - "url": list.url, - "whitelist": type == 'whitelist' ? true : false - }); - - if (result1['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.loading, true); - } - - processModal.close(); - - Navigator.pop(context); // Closes the screen - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDeleted, - color: Colors.green - ); - } - else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - - showSnacbkar( - context: context, - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listNotDeleted, - color: Colors.red - ); - } + Filter? list; + try { + list = serversProvider.filtering.data != null + ? widget.type == 'whitelist' + ? serversProvider.filtering.data!.whitelistFilters.firstWhere((l) => l.id == widget.listId) + : serversProvider.filtering.data!.filters.firstWhere((l) => l.id == widget.listId) + : null; + } catch (e) { + // ------- // } List content() { @@ -226,11 +82,11 @@ class _ListDetailsScreenState extends State { icon: Icons.shield_rounded, title: AppLocalizations.of(context)!.currentStatus, subtitleWidget: Text( - enabled == true + list!.enabled == true ? AppLocalizations.of(context)!.enabled : AppLocalizations.of(context)!.disabled, style: TextStyle( - color: enabled == true + color: list.enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -250,7 +106,7 @@ class _ListDetailsScreenState extends State { CustomListTile( icon: Icons.badge_rounded, title: AppLocalizations.of(context)!.name, - subtitle: name, + subtitle: list.name, padding: widget.dialog == true ? const EdgeInsets.symmetric( horizontal: 24, @@ -261,7 +117,7 @@ class _ListDetailsScreenState extends State { CustomListTile( icon: Icons.link_rounded, title: "URL", - subtitle: widget.list.url, + subtitle: list.url, padding: widget.dialog == true ? const EdgeInsets.symmetric( horizontal: 24, @@ -272,7 +128,7 @@ class _ListDetailsScreenState extends State { CustomListTile( icon: Icons.list_rounded, title: AppLocalizations.of(context)!.rules, - subtitle: widget.list.rulesCount.toString(), + subtitle: list.rulesCount.toString(), padding: widget.dialog == true ? const EdgeInsets.symmetric( horizontal: 24, @@ -293,10 +149,10 @@ class _ListDetailsScreenState extends State { ) : null, ), - if (widget.list.lastUpdated != null) CustomListTile( + if (list.lastUpdated != null) CustomListTile( icon: Icons.schedule_rounded, title: AppLocalizations.of(context)!.latestUpdate, - subtitle: convertTimestampLocalTimezone(widget.list.lastUpdated!, 'dd-MM-yyyy HH:mm'), + subtitle: convertTimestampLocalTimezone(list.lastUpdated!, 'dd-MM-yyyy HH:mm'), padding: widget.dialog == true ? const EdgeInsets.symmetric( horizontal: 24, @@ -316,9 +172,31 @@ class _ListDetailsScreenState extends State { showDialog( context: context, builder: (ctx) => AddListModal( - list: widget.list, + list: list, type: widget.type, - onEdit: confirmEditList, + onEdit: ({required Filter list, required String type}) async { + final result = await editList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list, + type: widget.type + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + }, dialog: true, ), ) @@ -327,9 +205,31 @@ class _ListDetailsScreenState extends State { showModalBottomSheet( context: context, builder: (ctx) => AddListModal( - list: widget.list, + list: list, type: widget.type, - onEdit: confirmEditList, + onEdit: ({required Filter list, required String type}) async { + final result = await editList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list, + type: widget.type + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + }, dialog: false, ), isScrollControlled: true, @@ -344,8 +244,31 @@ class _ListDetailsScreenState extends State { onPressed: () { showDialog( context: context, - builder: (context) => DeleteListModal( - onConfirm: () => deleteList(widget.list, widget.type), + builder: (c) => DeleteListModal( + onConfirm: () async { + final result = await deleteList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list!, + type: widget.type, + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDeleted, + color: Colors.green + ); + Navigator.pop(context); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listNotDeleted, + color: Colors.red + ); + } + } ) ); }, @@ -386,16 +309,38 @@ class _ListDetailsScreenState extends State { ) ], ), - Row( + if (list != null) Row( children: [ IconButton( - onPressed: () => enableDisableList(widget.list, !enabled), + onPressed: () async { + final result = await enableDisableList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list!, + listType: widget.type, + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + }, icon: Icon( - enabled == true + list.enabled == true ? Icons.gpp_bad_rounded : Icons.verified_user_rounded, ), - tooltip: enabled == true + tooltip: list.enabled == true ? AppLocalizations.of(context)!.disableList : AppLocalizations.of(context)!.enableList, ), @@ -406,11 +351,20 @@ class _ListDetailsScreenState extends State { ), ), Flexible( - child: SingleChildScrollView( - child: Wrap( - children: content(), - ), - ) + child: list != null + ? SingleChildScrollView( + child: Wrap( + children: content(), + ), + ) + : Center( + child: Text( + AppLocalizations.of(context)!.listNotAvailable, + style: const TextStyle( + fontSize: 24, + ), + ), + ), ) ], ), @@ -421,14 +375,22 @@ class _ListDetailsScreenState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.listDetails), - actions: actions(), + actions: list != null ? actions() : null, ), body: Stack( children: [ - ListView( + if (list != null) ListView( children: content(), ), - AnimatedPositioned( + if (list == null) Center( + child: Text( + AppLocalizations.of(context)!.listNotAvailable, + style: const TextStyle( + fontSize: 24, + ), + ), + ), + if (list != null) AnimatedPositioned( duration: const Duration(milliseconds: 100), curve: Curves.easeInOut, bottom: fabVisible ? @@ -437,9 +399,31 @@ class _ListDetailsScreenState extends State { : -70, right: 20, child: FloatingActionButton( - onPressed: () => enableDisableList(widget.list, !enabled), + onPressed: () async { + final result = await enableDisableList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list!, + listType: widget.type, + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + }, child: Icon( - enabled == true + list.enabled == true ? Icons.gpp_bad_rounded : Icons.verified_user_rounded, ), diff --git a/lib/screens/filters/list_functions.dart b/lib/screens/filters/list_functions.dart new file mode 100644 index 0000000..7db194f --- /dev/null +++ b/lib/screens/filters/list_functions.dart @@ -0,0 +1,141 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; + +Future enableDisableList({ + required BuildContext context, + required ServersProvider serversProvider, + required AppConfigProvider appConfigProvider, + required Filter list, + required String listType, +}) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open( + list.enabled == true + ? AppLocalizations.of(context)!.disablingList + : AppLocalizations.of(context)!.enablingList, + ); + + final result = await updateFilterList(server: serversProvider.selectedServer!, data: { + "data": { + "enabled": !list.enabled, + "name": list.name, + "url": list.url + }, + "url": list.url, + "whitelist": listType == 'whitelist' ? true : false + }); + + processModal.close(); + + if (result['result'] == 'success') { + final result2 = await getFiltering(server: serversProvider.selectedServer!); + + if (result2['result'] == 'success') { + serversProvider.setFilteringData(result2['data']); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + } + else { + appConfigProvider.addLog(result2['log']); + serversProvider.setFilteringLoadStatus(LoadStatus.error, true); + } + + return true; + } + else { + appConfigProvider.addLog(result['log']); + + return false; + } +} + +Future editList({ + required BuildContext context, + required ServersProvider serversProvider, + required AppConfigProvider appConfigProvider, + required Filter list, + required String type +}) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.updatingListData); + + final result1 = await updateFilterList(server: serversProvider.selectedServer!, data: { + "data": { + "enabled": list.enabled, + "name": list.name, + "url": list.url + }, + "url": list.url, + "whitelist": type == 'whitelist' ? true : false + }); + + if (result1['result'] == 'success') { + final result2 = await getFiltering(server: serversProvider.selectedServer!); + + if (result2['result'] == 'success') { + serversProvider.setFilteringData(result2['data']); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + } + else { + appConfigProvider.addLog(result2['log']); + serversProvider.setFilteringLoadStatus(LoadStatus.error, true); + } + + processModal.close(); + + return true; + } + else { + processModal.close(); + appConfigProvider.addLog(result1['log']); + + return false; + } +} + +Future deleteList({ + required BuildContext context, + required ServersProvider serversProvider, + required AppConfigProvider appConfigProvider, + required Filter list, + required String type +}) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.deletingList); + + final result1 = await deleteFilterList(server: serversProvider.selectedServer!, data: { + "url": list.url, + "whitelist": type == 'whitelist' ? true : false + }); + + if (result1['result'] == 'success') { + final result2 = await getFiltering(server: serversProvider.selectedServer!); + + if (result2['result'] == 'success') { + serversProvider.setFilteringData(result2['data']); + serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + } + else { + appConfigProvider.addLog(result2['log']); + serversProvider.setFilteringLoadStatus(LoadStatus.loading, true); + } + + processModal.close(); + + return true; + } + else { + processModal.close(); + appConfigProvider.addLog(result1['log']); + + return false; + } +} \ No newline at end of file diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart new file mode 100644 index 0000000..f052890 --- /dev/null +++ b/lib/screens/filters/list_options_menu.dart @@ -0,0 +1,120 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:contextmenu/contextmenu.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/filters/list_functions.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/widgets/options_modal.dart'; + +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/functions/copy_clipboard.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class ListOptionsMenu extends StatelessWidget { + final Filter list; + final Widget child; + final String listType; + + const ListOptionsMenu({ + Key? key, + required this.list, + required this.child, + required this.listType, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void enableDisable() async { + final result = await enableDisableList( + context: context, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + list: list, + listType: listType, + ); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + } + + return ContextMenuArea( + builder: (context) => [ + CustomListTile( + title: list.enabled == true + ? AppLocalizations.of(context)!.disable + : AppLocalizations.of(context)!.enable, + icon: list.enabled == true + ? Icons.gpp_bad_rounded + : Icons.verified_user_rounded, + onTap: () { + Navigator.pop(context); // Closes the context menu + enableDisable(); + } + ), + CustomListTile( + title: AppLocalizations.of(context)!.copyListUrl, + icon: Icons.copy_rounded, + onTap: () { + Navigator.pop(context); // Closes the context menu + copyToClipboard( + context: context, + value: list.url, + successMessage: AppLocalizations.of(context)!.listUrlCopied + ); + } + ), + ], + child: Material( + color: Colors.transparent, + child: InkWell( + onLongPress: () => showDialog( + context: context, + builder: (context) => OptionsModal( + options: [ + MenuOption( + title: list.enabled == true + ? AppLocalizations.of(context)!.disable + : AppLocalizations.of(context)!.enable, + icon: list.enabled == true + ? Icons.gpp_bad_rounded + : Icons.verified_user_rounded, + action: enableDisable + ), + MenuOption( + title: AppLocalizations.of(context)!.copyListUrl, + icon: Icons.copy_rounded, + action: () => copyToClipboard( + context: context, + value: list.url, + successMessage: AppLocalizations.of(context)!.listUrlCopied + ) + ), + ] + ) + ), + child: child + ), + ), + ); + } +} \ No newline at end of file From d9f68484e046e63198783156f48e238b41d3eba8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 6 May 2023 04:16:24 +0200 Subject: [PATCH 084/676] Fixed small issues --- README.md | 1 + lib/screens/clients/active_client_tile.dart | 23 +++++++++ lib/screens/clients/logs_list_client.dart | 55 ++++++++++++--------- pubspec.lock | 2 +- pubspec.yaml | 1 + 5 files changed, 59 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 465c945..656e95c 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [sqflite common ffi](https://pub.dev/packages/sqflite_common_ffi) - [window size](https://github.com/google/flutter-desktop-embedding) - [flutter split view](https://github.com/JGeek00/flutter_split_view) (forked from [here](https://pub.dev/packages/flutter_split_view)) +- [async](https://pub.dev/packages/async)
diff --git a/lib/screens/clients/active_client_tile.dart b/lib/screens/clients/active_client_tile.dart index 975ddbf..f9b598f 100644 --- a/lib/screens/clients/active_client_tile.dart +++ b/lib/screens/clients/active_client_tile.dart @@ -3,7 +3,9 @@ import 'package:contextmenu/contextmenu.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/widgets/options_modal.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/clients.dart'; @@ -49,6 +51,27 @@ class ActiveClientTile extends StatelessWidget { child: InkWell( borderRadius: BorderRadius.circular(28), onTap: () => onTap(client), + onLongPress: () => showDialog( + context: context, + builder: (context) => OptionsModal( + options: [ + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: () { + copyToClipboard( + context: context, + value: client.name != '' + ? client.name! + : client.ip, + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ); + Navigator.pop(context); + }, + ) + ] + ), + ), child: Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/logs_list_client.dart index 99b0891..d88d7a1 100644 --- a/lib/screens/clients/logs_list_client.dart +++ b/lib/screens/clients/logs_list_client.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:async/async.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; @@ -44,6 +45,8 @@ class _LogsListClientState extends State { bool showDivider = true; + CancelableOperation? cancelableRequest; + Future fetchLogs({ int? inOffset, bool? loadingMore, @@ -56,34 +59,42 @@ class _LogsListClientState extends State { setState(() => isLoadingMore = true); } - final result = await getLogs( - server: widget.serversProvider.selectedServer!, - count: logsQuantity, - offset: offst, - search: '"${widget.ip}"' + if (cancelableRequest != null) cancelableRequest!.cancel(); + + cancelableRequest = CancelableOperation.fromFuture( + getLogs( + server: widget.serversProvider.selectedServer!, + count: logsQuantity, + offset: offst, + search: '"${widget.ip}"' + ) ); - if (loadingMore != null && loadingMore == true) { - setState(() => isLoadingMore = false); - } + final result = await cancelableRequest?.value; - if (mounted) { - if (result['result'] == 'success') { - setState(() => offset = inOffset != null ? inOffset+logsQuantity : offset+logsQuantity); - if (loadingMore != null && loadingMore == true && logsData != null) { - LogsData newLogsData = result['data']; - newLogsData.data = [...logsData!.data, ...result['data'].data]; - setState(() => logsData = newLogsData); + if (result != null) { + if (loadingMore != null && loadingMore == true) { + setState(() => isLoadingMore = false); + } + + if (mounted) { + if (result['result'] == 'success') { + setState(() => offset = inOffset != null ? inOffset+logsQuantity : offset+logsQuantity); + if (loadingMore != null && loadingMore == true && logsData != null) { + LogsData newLogsData = result['data']; + newLogsData.data = [...logsData!.data, ...result['data'].data]; + setState(() => logsData = newLogsData); + } + else { + LogsData newLogsData = result['data']; + setState(() => logsData = newLogsData); + } + setState(() => loadStatus = 1); } else { - LogsData newLogsData = result['data']; - setState(() => logsData = newLogsData); + setState(() => loadStatus = 2); + widget.appConfigProvider.addLog(result['log']); } - setState(() => loadStatus = 1); - } - else { - setState(() => loadStatus = 2); - widget.appConfigProvider.addLog(result['log']); } } } diff --git a/pubspec.lock b/pubspec.lock index 421a3d4..f3ce0cf 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -34,7 +34,7 @@ packages: source: hosted version: "2.3.2" async: - dependency: transitive + dependency: "direct main" description: name: async sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 diff --git a/pubspec.yaml b/pubspec.yaml index ab4be31..76e787d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -69,6 +69,7 @@ dependencies: ref: master-alt url_launcher: ^6.1.10 contextmenu: ^3.0.0 + async: ^2.10.0 dev_dependencies: flutter_test: From aa403dedd880f49f3b12e1d9c7e55e8bea88eb62 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 6 May 2023 04:19:53 +0200 Subject: [PATCH 085/676] Small issue fixed --- lib/screens/clients/active_client_tile.dart | 49 ++++++++++++--------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/lib/screens/clients/active_client_tile.dart b/lib/screens/clients/active_client_tile.dart index f9b598f..c3e55cf 100644 --- a/lib/screens/clients/active_client_tile.dart +++ b/lib/screens/clients/active_client_tile.dart @@ -25,6 +25,29 @@ class ActiveClientTile extends StatelessWidget { @override Widget build(BuildContext context) { + void openOptionsModal() { + showDialog( + context: context, + builder: (context) => OptionsModal( + options: [ + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: () { + copyToClipboard( + context: context, + value: client.name != '' + ? client.name! + : client.ip, + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ); + }, + ) + ] + ), + ); + } + if (splitView == true) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), @@ -51,27 +74,10 @@ class ActiveClientTile extends StatelessWidget { child: InkWell( borderRadius: BorderRadius.circular(28), onTap: () => onTap(client), - onLongPress: () => showDialog( - context: context, - builder: (context) => OptionsModal( - options: [ - MenuOption( - title: AppLocalizations.of(context)!.copyClipboard, - icon: Icons.copy_rounded, - action: () { - copyToClipboard( - context: context, - value: client.name != '' - ? client.name! - : client.ip, - successMessage: AppLocalizations.of(context)!.copiedClipboard, - ); - Navigator.pop(context); - }, - ) - ] - ), - ), + onLongPress: () { + Navigator.pop(context); + openOptionsModal(); + }, child: Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), @@ -155,6 +161,7 @@ class ActiveClientTile extends StatelessWidget { ), ), onTap: () => onTap(client), + onLongPress: openOptionsModal, ), ); } From 60488f41a6798288207f9a93ee6b3f8f684e3534 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 6 May 2023 04:45:30 +0200 Subject: [PATCH 086/676] Updated Android and macOS version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index b5c6a97..30b8ef4 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 53; + CURRENT_PROJECT_VERSION = 54; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.0.0; + MARKETING_VERSION = 2.1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 53; + CURRENT_PROJECT_VERSION = 54; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.0.0; + MARKETING_VERSION = 2.1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 53; + CURRENT_PROJECT_VERSION = 54; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.0.0; + MARKETING_VERSION = 2.1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; diff --git a/pubspec.yaml b/pubspec.yaml index 76e787d..efe9f87 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.0.0+53 +version: 2.1.0+54 environment: sdk: '>=2.18.1 <3.0.0' From 8edacab1ef776024463e54812839262e6756dab1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 6 May 2023 04:51:38 +0200 Subject: [PATCH 087/676] Updated windows version --- windows/innosetup_installer_builder.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 4887491..2e9fc48 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AdGuard Home Manager" -#define MyAppVersion "2.0.0" +#define MyAppVersion "2.1.0" #define MyAppPublisher "JGeek00" #define MyAppURL "https://github.com/JGeek00/adguard-home-manager" #define MyAppExeName "adguard_home_manager.exe" From 92c8e4d1035612f975ad7d77ed0113285eb9ab9d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 6 May 2023 05:00:17 +0200 Subject: [PATCH 088/676] Updated linux version --- debian/debian.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index df64eae..a0f9afe 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.0.0 + Version: 2.1.0 Architecture: amd64 Essential: no Priority: optional From 6196cd369a36167a022e0a6b67e6c06da18e709c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 8 May 2023 21:41:43 +0200 Subject: [PATCH 089/676] Fixed crash version check --- lib/functions/compare_versions.dart | 148 +++++++++++++++------------- 1 file changed, 80 insertions(+), 68 deletions(-) diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index 39b78cd..b99bd8f 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -2,19 +2,23 @@ bool compareVersions({ required String currentVersion, required String newVersion }) { - final currentSplit = currentVersion.split('.').map((e) => int.parse(e)).toList(); - final newSplit = newVersion.split('.').map((e) => int.parse(e)).toList(); + try { + final currentSplit = currentVersion.split('.').map((e) => int.parse(e)).toList(); + final newSplit = newVersion.split('.').map((e) => int.parse(e)).toList(); - if (newSplit[0] > currentSplit[0]) { - return true; - } - else if (newSplit[1] > currentSplit[1]) { - return true; - } - else if (newSplit[2] > currentSplit[2]) { - return true; - } - else { + if (newSplit[0] > currentSplit[0]) { + return true; + } + else if (newSplit[1] > currentSplit[1]) { + return true; + } + else if (newSplit[2] > currentSplit[2]) { + return true; + } + else { + return false; + } + } catch (e) { return false; } } @@ -23,25 +27,29 @@ bool compareBetaVersions({ required String currentVersion, required String newVersion }) { - final currentSplit = currentVersion.split('-')[0].split('.').map((e) => int.parse(e)).toList(); - final newSplit = newVersion.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + try { + final currentSplit = currentVersion.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + final newSplit = newVersion.split('-')[0].split('.').map((e) => int.parse(e)).toList(); - final currentBeta = int.parse(currentVersion.split('-')[1].replaceAll('b.', '')); - final newBeta = int.parse(newVersion.split('-')[1].replaceAll('b.', '')); - - if (newSplit[0] > currentSplit[0]) { - return true; - } - else if (newSplit[1] > currentSplit[1]) { - return true; - } - else if (newSplit[2] > currentSplit[2]) { - return true; - } - else if (newBeta > currentBeta) { - return true; - } - else { + final currentBeta = int.parse(currentVersion.split('-')[1].replaceAll('b.', '')); + final newBeta = int.parse(newVersion.split('-')[1].replaceAll('b.', '')); + + if (newSplit[0] > currentSplit[0]) { + return true; + } + else if (newSplit[1] > currentSplit[1]) { + return true; + } + else if (newSplit[2] > currentSplit[2]) { + return true; + } + else if (newBeta > currentBeta) { + return true; + } + else { + return false; + } + } catch (e) { return false; } } @@ -51,19 +59,47 @@ bool serverVersionIsAhead({ required String referenceVersion, String? referenceVersionBeta }) { - final current = currentVersion.replaceAll('v', ''); - final reference = referenceVersion.replaceAll('v', ''); - final referenceBeta = referenceVersionBeta?.replaceAll('v', ''); + try { + final current = currentVersion.replaceAll('v', ''); + final reference = referenceVersion.replaceAll('v', ''); + final referenceBeta = referenceVersionBeta?.replaceAll('v', ''); - if (current.contains('beta')) { - if (referenceBeta != null) { - final currentSplit = current.split('-')[0].split('.').map((e) => int.parse(e)).toList(); - final newSplit = referenceBeta.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + if (current.contains('b')) { + if (referenceBeta != null) { + final currentSplit = current.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + final newSplit = referenceBeta.split('-')[0].split('.').map((e) => int.parse(e)).toList(); - final currentBeta = int.parse(current.split('-')[1].replaceAll('b.', '')); - final newBeta = int.parse(referenceBeta.split('-')[1].replaceAll('b.', '')); - - if (newSplit[0] == currentSplit[0] && newSplit[1] == currentSplit[1] && newSplit[2] == currentSplit[2] && newBeta == currentBeta) { + final currentBeta = int.parse(current.split('-')[1].replaceAll('b.', '')); + final newBeta = int.parse(referenceBeta.split('-')[1].replaceAll('b.', '')); + + if (newSplit[0] == currentSplit[0] && newSplit[1] == currentSplit[1] && newSplit[2] == currentSplit[2] && newBeta == currentBeta) { + return true; + } + else if (newSplit[0] < currentSplit[0]) { + return true; + } + else if (newSplit[1] < currentSplit[1]) { + return true; + } + else if (newSplit[2] < currentSplit[2]) { + return true; + } + else if (newBeta < currentBeta) { + return true; + } + else { + return false; + } + } + else { + return false; + } + } + else { + final currentSplit = current.split('.').map((e) => int.parse(e)).toList(); + final newSplit = reference.split('.').map((e) => int.parse(e)).toList(); + + if (newSplit[0] == currentSplit[0] && newSplit[1] == currentSplit[1] && newSplit[2] == currentSplit[2]) { return true; } else if (newSplit[0] < currentSplit[0]) { @@ -74,36 +110,12 @@ bool serverVersionIsAhead({ } else if (newSplit[2] < currentSplit[2]) { return true; - } - else if (newBeta < currentBeta) { - return true; - } + } else { return false; } } - else { - return false; - } - } - else { - final currentSplit = current.split('.').map((e) => int.parse(e)).toList(); - final newSplit = reference.split('.').map((e) => int.parse(e)).toList(); - - if (newSplit[0] == currentSplit[0] && newSplit[1] == currentSplit[1] && newSplit[2] == currentSplit[2]) { - return true; - } - else if (newSplit[0] < currentSplit[0]) { - return true; - } - else if (newSplit[1] < currentSplit[1]) { - return true; - } - else if (newSplit[2] < currentSplit[2]) { - return true; - } - else { - return false; - } + } catch (e) { + return false; } } \ No newline at end of file From 885d01fa1af62e1d9b1036e4458b929c3012fdd9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 8 May 2023 22:05:06 +0200 Subject: [PATCH 090/676] Implemented sentry --- .env.sample | 2 + .gitignore | 3 + lib/main.dart | 69 +++++++++++++++---- lib/screens/clients/logs_list_client.dart | 1 - linux/flutter/generated_plugin_registrant.cc | 4 ++ linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile.lock | 15 ++++ pubspec.lock | 24 +++++++ pubspec.yaml | 3 + .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 12 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 .env.sample diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..db332bb --- /dev/null +++ b/.env.sample @@ -0,0 +1,2 @@ +SENTRY_DSN= +ENABLE_SENTRY=false \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0bc0e3e..429a1bd 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ .svn/ migrate_working_dir/ +# Env +.env + # IntelliJ related *.iml *.ipr diff --git a/lib/main.dart b/lib/main.dart index 62d4acc..3e8ae84 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,14 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:provider/provider.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:window_size/window_size.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -34,6 +37,8 @@ void main() async { sqfliteFfiInit(); databaseFactory = databaseFactoryFfi; } + + await dotenv.load(fileName: '.env'); AppConfigProvider appConfigProvider = AppConfigProvider(); ServersProvider serversProvider = ServersProvider(); @@ -62,22 +67,56 @@ void main() async { PackageInfo appInfo = await PackageInfo.fromPlatform(); appConfigProvider.setAppInfo(appInfo); - runApp( - MultiProvider( - providers: [ - ChangeNotifierProvider( - create: ((context) => serversProvider) - ), - ChangeNotifierProvider( - create: ((context) => appConfigProvider) - ), - ChangeNotifierProvider( - create: ((context) => logsProvider) - ), - ], - child: const Main(), + if ( + ( + kReleaseMode && + (dotenv.env['SENTRY_DSN'] != null && dotenv.env['SENTRY_DSN'] != "") + ) || ( + dotenv.env['ENABLE_SENTRY'] == "true" && + (dotenv.env['SENTRY_DSN'] != null && dotenv.env['SENTRY_DSN'] != "") ) - ); + ) { + SentryFlutter.init( + (options) { + options.dsn = dotenv.env['SENTRY_DSN']; + options.sendDefaultPii = false; + }, + appRunner: () => runApp( + MultiProvider( + providers: [ + ChangeNotifierProvider( + create: ((context) => serversProvider) + ), + ChangeNotifierProvider( + create: ((context) => appConfigProvider) + ), + ChangeNotifierProvider( + create: ((context) => logsProvider) + ), + ], + child: const Main(), + ) + ) + ); + } + else { + runApp( + MultiProvider( + providers: [ + ChangeNotifierProvider( + create: ((context) => serversProvider) + ), + ChangeNotifierProvider( + create: ((context) => appConfigProvider) + ), + ChangeNotifierProvider( + create: ((context) => logsProvider) + ), + ], + child: const Main(), + ) + ); + } } class Main extends StatefulWidget { diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/logs_list_client.dart index d88d7a1..dd731c4 100644 --- a/lib/screens/clients/logs_list_client.dart +++ b/lib/screens/clients/logs_list_client.dart @@ -126,7 +126,6 @@ class _LogsListClientState extends State { if (widget.ip != previousIp) { setState(() => loadStatus = 0); - if (scrollController.hasClients) scrollController.animateTo(0, duration: const Duration(milliseconds: 1), curve: Curves.ease); fetchLogs(inOffset: 0); setState(() => previousIp = widget.ip); } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index cb9d874..1786709 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -15,6 +16,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) dynamic_color_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); + g_autoptr(FlPluginRegistrar) sentry_flutter_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin"); + sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar); g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index da06542..59ac090 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color + sentry_flutter sqlite3_flutter_libs url_launcher_linux window_size diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 3d7ad09..24bbeae 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,6 +8,7 @@ import Foundation import device_info_plus_macos import dynamic_color import package_info_plus +import sentry_flutter import sqflite import sqlite3_flutter_libs import url_launcher_macos @@ -17,6 +18,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) + SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index fbc72ee..d38e653 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -9,6 +9,13 @@ PODS: - FMDB/standard (2.7.5) - package_info_plus (0.0.1): - FlutterMacOS + - Sentry/HybridSDK (8.5.0): + - SentryPrivate (= 8.5.0) + - sentry_flutter (0.0.1): + - Flutter + - FlutterMacOS + - Sentry/HybridSDK (= 8.5.0) + - SentryPrivate (8.5.0) - sqflite (0.0.2): - FlutterMacOS - FMDB (>= 2.7.5) @@ -37,6 +44,7 @@ DEPENDENCIES: - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) + - sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) @@ -45,6 +53,8 @@ DEPENDENCIES: SPEC REPOS: trunk: - FMDB + - Sentry + - SentryPrivate - sqlite3 EXTERNAL SOURCES: @@ -56,6 +66,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral package_info_plus: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos + sentry_flutter: + :path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos sqflite: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos sqlite3_flutter_libs: @@ -71,6 +83,9 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce + Sentry: 3be3f42e40e5a552935552e115744d5810a216d9 + sentry_flutter: c75806c304706163b2c129394c4621a786ad84e9 + SentryPrivate: 8c9463280e282527f938d1a5d1d60f8e10ff279b sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea sqlite3: d31b2b69d59bd1b4ab30e5c92eb18fd8e82fa392 sqlite3_flutter_libs: f20746e4a0245afbee4f20d9afc0072ebff7cc26 diff --git a/pubspec.lock b/pubspec.lock index f3ce0cf..d2db277 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -246,6 +246,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.1" + flutter_dotenv: + dependency: "direct main" + description: + name: flutter_dotenv + sha256: d9283d92059a22e9834bc0a31336658ffba77089fb6f3cc36751f1fc7c6661a3 + url: "https://pub.dev" + source: hosted + version: "5.0.2" flutter_html: dependency: "direct main" description: @@ -518,6 +526,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.5" + sentry: + dependency: transitive + description: + name: sentry + sha256: "8f2ff67c168c640567093f9f80f6cdfa34c009b89fb81732e896b9e95c3b87e8" + url: "https://pub.dev" + source: hosted + version: "7.5.1" + sentry_flutter: + dependency: "direct main" + description: + name: sentry_flutter + sha256: "4de19f8b353eac472609f6c42b2bb0dd38d5a128c3e4a6ac6c0a9574b85fde47" + url: "https://pub.dev" + source: hosted + version: "7.5.1" sky_engine: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index efe9f87..8b5e06e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -70,6 +70,8 @@ dependencies: url_launcher: ^6.1.10 contextmenu: ^3.0.0 async: ^2.10.0 + sentry_flutter: ^7.5.1 + flutter_dotenv: ^5.0.2 dev_dependencies: flutter_test: @@ -131,6 +133,7 @@ flutter: - assets/other/get_google_play.png - assets/resources/github.svg - assets/resources/google-play.svg + - .env # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 3d0e948..50bb1c8 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -14,6 +15,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { DynamicColorPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); + SentryFlutterPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SentryFlutterPlugin")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 8ca2ff7..71f5fcf 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color + sentry_flutter sqlite3_flutter_libs url_launcher_windows window_size From 7ddc08d10904a130885b96e3218175bd8859cebe Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 8 May 2023 22:11:09 +0200 Subject: [PATCH 091/676] Updated readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 656e95c..d8e05f3 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@

â–¶ Responsive UI adapted for landscape displays.

## Privacy policy -AdGuard Home Manager does not collect any personal user data. All data stored into the application is kept on the user's device. +Check the privacy policy [here](https://github.com/JGeek00/adguard-home-manager/wiki/Privacy-policy). ## Disclaimer This is an unofficial application. The AdGuard Home team and the development of the AdGuard Home software is not related in any way with this application. @@ -117,6 +117,8 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [window size](https://github.com/google/flutter-desktop-embedding) - [flutter split view](https://github.com/JGeek00/flutter_split_view) (forked from [here](https://pub.dev/packages/flutter_split_view)) - [async](https://pub.dev/packages/async) +- [sentry flutter](https://pub.dev/packages/sentry_flutter) +- [flutter dotenv](https://pub.dev/packages/flutter_dotenv)
From e10b53338b42c21e73e56deac44c59c32e66f965 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 8 May 2023 22:19:32 +0200 Subject: [PATCH 092/676] Added handlers --- lib/functions/compare_versions.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index b99bd8f..a732f1e 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -1,3 +1,5 @@ +import 'package:sentry_flutter/sentry_flutter.dart'; + bool compareVersions({ required String currentVersion, required String newVersion @@ -19,6 +21,7 @@ bool compareVersions({ return false; } } catch (e) { + Sentry.captureException(e); return false; } } @@ -50,6 +53,7 @@ bool compareBetaVersions({ return false; } } catch (e) { + Sentry.captureException(e); return false; } } @@ -116,6 +120,7 @@ bool serverVersionIsAhead({ } } } catch (e) { + Sentry.captureException(e); return false; } } \ No newline at end of file From 7aea6ec4250aaec1a6795dc664d3c1f6878f4dce Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 8 May 2023 22:33:09 +0200 Subject: [PATCH 093/676] Updated app version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 30b8ef4..afc725d 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 54; + CURRENT_PROJECT_VERSION = 55; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.0; + MARKETING_VERSION = 2.1.1; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 54; + CURRENT_PROJECT_VERSION = 55; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.0; + MARKETING_VERSION = 2.1.1; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 54; + CURRENT_PROJECT_VERSION = 55; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.0; + MARKETING_VERSION = 2.1.1; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; diff --git a/pubspec.yaml b/pubspec.yaml index 8b5e06e..cc5c789 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.1.0+54 +version: 2.1.1+55 environment: sdk: '>=2.18.1 <3.0.0' From 852fc3efacced0f5253450a9c08e44d125653d79 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 8 May 2023 22:44:51 +0200 Subject: [PATCH 094/676] Updated linux version --- debian/debian.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index a0f9afe..d84c34b 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.1.0 + Version: 2.1.1 Architecture: amd64 Essential: no Priority: optional From aca78bf89af0156b947cc441f982ed0f1a4c0fbf Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 8 May 2023 22:55:48 +0200 Subject: [PATCH 095/676] Updated windows version --- windows/innosetup_installer_builder.iss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 2e9fc48..e6c5f5c 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AdGuard Home Manager" -#define MyAppVersion "2.1.0" +#define MyAppVersion "2.1.1" #define MyAppPublisher "JGeek00" #define MyAppURL "https://github.com/JGeek00/adguard-home-manager" #define MyAppExeName "adguard_home_manager.exe" @@ -40,6 +40,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\dynamic_color_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion From e795050a95028c11e1812025317c4d0339621520 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 9 May 2023 15:31:00 +0200 Subject: [PATCH 096/676] Fixed some issues --- lib/base.dart | 7 +++++++ lib/functions/compare_versions.dart | 19 ++++++++++++++++--- lib/widgets/process_dialog.dart | 10 ++++++---- .../servers_list/servers_list_item.dart | 3 +-- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/lib/base.dart b/lib/base.dart index c144719..a0ad7e4 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -3,9 +3,12 @@ import 'dart:async'; import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:provider/provider.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:store_checker/store_checker.dart'; import 'package:flutter/services.dart'; @@ -112,6 +115,10 @@ class _BaseState extends State with WidgetsBindingObserver { ? screensServerConnected : screensSelectServer; + if (kDebugMode && dotenv.env['ENABLE_SENTRY'] == "true") { + Sentry.captureMessage("Debug mode"); + } + return CustomMenuBar( child: AnnotatedRegion( value: SystemUiOverlayStyle( diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index a732f1e..7c0274e 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -21,7 +21,11 @@ bool compareVersions({ return false; } } catch (e) { - Sentry.captureException(e); + Sentry.captureException(e, hint: Hint.withMap({ + "fn": "compareVersions", + "currentVersion": currentVersion, + "newVersion": newVersion, + })); return false; } } @@ -53,7 +57,11 @@ bool compareBetaVersions({ return false; } } catch (e) { - Sentry.captureException(e); + Sentry.captureException(e, hint: Hint.withMap({ + "fn": "compareBetaVersions", + "currentVersion": currentVersion, + "newVersion": newVersion, + })); return false; } } @@ -120,7 +128,12 @@ bool serverVersionIsAhead({ } } } catch (e) { - Sentry.captureException(e); + Sentry.captureException(e, hint: Hint.withMap({ + "fn": "serverVersionIsAhead", + "currentVersion": currentVersion, + "referenceVersion": referenceVersion, + "referenceVersionBeta": referenceVersionBeta ?? "" + })); return false; } } \ No newline at end of file diff --git a/lib/widgets/process_dialog.dart b/lib/widgets/process_dialog.dart index d8794d8..e821696 100644 --- a/lib/widgets/process_dialog.dart +++ b/lib/widgets/process_dialog.dart @@ -24,10 +24,12 @@ class ProcessDialog extends StatelessWidget { children: [ const CircularProgressIndicator(), const SizedBox(width: 40), - Text( - message, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface + Expanded( + child: Text( + message, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), ), ) ], diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 17a1205..abd625e 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -53,8 +53,7 @@ class _ServersListItemState extends State with SingleTickerProv animationController = AnimationController( duration: const Duration(milliseconds: 200), vsync: this, - ) - ..addListener(() => setState(() => {})); + ); animation = Tween( begin: 0.0, end: 0.5, From ad27d0c24e8b3a44663b5267594608d5d9eacdf2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 12 May 2023 23:11:38 +0200 Subject: [PATCH 097/676] Bug fixes --- lib/base.dart | 4 ++- lib/functions/compare_versions.dart | 41 +++++++++++++--------- lib/screens/clients/added_client_tile.dart | 9 ++--- lib/screens/clients/added_list.dart | 1 + lib/screens/home/home.dart | 10 +++--- lib/screens/home/management_modal.dart | 2 +- lib/screens/logs/log_details_screen.dart | 2 +- lib/screens/logs/log_tile.dart | 4 +-- lib/screens/logs/logs.dart | 2 ++ lib/screens/logs/logs_config_modal.dart | 13 ++++--- lib/screens/settings/dns/upstream_dns.dart | 2 +- lib/screens/top_items/top_items.dart | 9 +++-- lib/services/http_requests.dart | 4 ++- lib/widgets/add_server_modal.dart | 9 +++-- 14 files changed, 69 insertions(+), 43 deletions(-) diff --git a/lib/base.dart b/lib/base.dart index a0ad7e4..561b115 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -116,7 +116,9 @@ class _BaseState extends State with WidgetsBindingObserver { : screensSelectServer; if (kDebugMode && dotenv.env['ENABLE_SENTRY'] == "true") { - Sentry.captureMessage("Debug mode"); + Sentry.captureException("Debug mode", stackTrace: { + "aaa": "aaa" + }); } return CustomMenuBar( diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index 7c0274e..e1b8fca 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -21,11 +21,14 @@ bool compareVersions({ return false; } } catch (e) { - Sentry.captureException(e, hint: Hint.withMap({ - "fn": "compareVersions", - "currentVersion": currentVersion, - "newVersion": newVersion, - })); + Sentry.captureException(e); + Sentry.captureMessage("compareVersions error", params: [ + { + "fn": "compareVersions", + "currentVersion": currentVersion, + "newVersion": newVersion, + }.toString() + ]); return false; } } @@ -57,11 +60,14 @@ bool compareBetaVersions({ return false; } } catch (e) { - Sentry.captureException(e, hint: Hint.withMap({ - "fn": "compareBetaVersions", - "currentVersion": currentVersion, - "newVersion": newVersion, - })); + Sentry.captureException(e); + Sentry.captureMessage("compareBetaVersions error", params: [ + { + "fn": "compareBetaVersions", + "currentVersion": currentVersion, + "newVersion": newVersion, + }.toString() + ]); return false; } } @@ -128,12 +134,15 @@ bool serverVersionIsAhead({ } } } catch (e) { - Sentry.captureException(e, hint: Hint.withMap({ - "fn": "serverVersionIsAhead", - "currentVersion": currentVersion, - "referenceVersion": referenceVersion, - "referenceVersionBeta": referenceVersionBeta ?? "" - })); + Sentry.captureException(e); + Sentry.captureMessage("serverVersionIsAhead error", params: [ + { + "fn": "serverVersionIsAhead", + "currentVersion": currentVersion, + "referenceVersion": referenceVersion, + "referenceVersionBeta": referenceVersionBeta ?? "" + }.toString() + ]); return false; } } \ No newline at end of file diff --git a/lib/screens/clients/added_client_tile.dart b/lib/screens/clients/added_client_tile.dart index fcf2ac8..5827c85 100644 --- a/lib/screens/clients/added_client_tile.dart +++ b/lib/screens/clients/added_client_tile.dart @@ -18,6 +18,7 @@ class AddedClientTile extends StatelessWidget { final void Function(Client) onEdit; final Client? selectedClient; final bool? splitView; + final String serverVersion; const AddedClientTile({ Key? key, @@ -26,12 +27,12 @@ class AddedClientTile extends StatelessWidget { required this.onLongPress, required this.onEdit, this.selectedClient, - required this.splitView + required this.splitView, + required this.serverVersion }) : super(key: key); @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); if (splitView == true) { @@ -138,7 +139,7 @@ class AddedClientTile extends StatelessWidget { Icons.search_rounded, size: 19, color: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true @@ -253,7 +254,7 @@ class AddedClientTile extends StatelessWidget { Icons.search_rounded, size: 19, color: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index f68b026..43f3a44 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -240,6 +240,7 @@ class _AddedListState extends State { onLongPress: openOptionsModal, onEdit: openClientModal, splitView: widget.splitView, + serverVersion: serversProvider.serverStatus.data!.serverVersion, ), noData: SizedBox( width: double.maxFinite, diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 20eff68..9cd9411 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -2,6 +2,7 @@ import 'dart:io'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; @@ -270,11 +271,10 @@ class _HomeState extends State { } else { appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.serverStatusNotRefreshed), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.serverStatusNotRefreshed, + color: Colors.red ); } }, diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 15eac57..46f94e5 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -135,7 +135,7 @@ class _ManagementModalState extends State with SingleTickerProv ); if (result != null) { if (result != false) { - appConfigProvider.addLog(result['log']); + appConfigProvider.addLog(result); } ScaffoldMessenger.of(context).showSnackBar( SnackBar( diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 5ee50b7..8662b8d 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -297,7 +297,7 @@ class LogDetailsScreen extends StatelessWidget { appBar: AppBar( title: Text(AppLocalizations.of(context)!.logDetails), actions: [ - IconButton( + if (serversProvider.filteringStatus != null) IconButton( onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), icon: Icon( getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index a3c25f9..fbdee24 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -175,7 +175,7 @@ class LogTile extends StatelessWidget { ) ], ), - if (appConfigProvider.showNameTimeLogs == true && log.clientInfo!.name != '') ...[ + if (appConfigProvider.showNameTimeLogs == true && log.clientInfo != null && log.clientInfo!.name != '') ...[ const SizedBox(height: 10), Row( children: [ @@ -350,7 +350,7 @@ class LogTile extends StatelessWidget { ) ], ), - if (appConfigProvider.showNameTimeLogs == true && log.clientInfo!.name != '') ...[ + if (appConfigProvider.showNameTimeLogs == true && log.clientInfo != null && log.clientInfo!.name != '') ...[ const SizedBox(height: 10), Row( children: [ diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index bcdb50b..74a7869 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -439,6 +439,7 @@ class _LogsWidgetState extends State { onConfirm: updateConfig, onClear: clearQueries, dialog: true, + serverVersion: serversProvider.serverStatus.data!.serverVersion, ), barrierDismissible: false ) @@ -450,6 +451,7 @@ class _LogsWidgetState extends State { onConfirm: updateConfig, onClear: clearQueries, dialog: false, + serverVersion: serversProvider.serverStatus.data!.serverVersion, ), backgroundColor: Colors.transparent, isScrollControlled: true diff --git a/lib/screens/logs/logs_config_modal.dart b/lib/screens/logs/logs_config_modal.dart index a540559..26ef299 100644 --- a/lib/screens/logs/logs_config_modal.dart +++ b/lib/screens/logs/logs_config_modal.dart @@ -13,12 +13,14 @@ class LogsConfigModal extends StatelessWidget { final void Function(Map) onConfirm; final void Function() onClear; final bool dialog; + final String serverVersion; const LogsConfigModal({ Key? key, required this.onConfirm, required this.onClear, - required this.dialog + required this.dialog, + required this.serverVersion }) : super(key: key); @override @@ -33,6 +35,7 @@ class LogsConfigModal extends StatelessWidget { onConfirm: onConfirm, onClear: onClear, dialog: dialog, + serverVersion: serverVersion, ); } } @@ -44,6 +47,7 @@ class LogsConfigModalWidget extends StatefulWidget { final void Function(Map) onConfirm; final void Function() onClear; final bool dialog; + final String serverVersion; const LogsConfigModalWidget({ Key? key, @@ -52,7 +56,8 @@ class LogsConfigModalWidget extends StatefulWidget { required this.context, required this.onConfirm, required this.onClear, - required this.dialog + required this.dialog, + required this.serverVersion }) : super(key: key); @override @@ -70,7 +75,7 @@ class _LogsConfigModalWidgetState extends State { void loadData() async { final result = serverVersionIsAhead( - currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, + currentVersion: widget.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true @@ -95,7 +100,7 @@ class _LogsConfigModalWidgetState extends State { @override void initState() { retentionItems = serverVersionIsAhead( - currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, + currentVersion: widget.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true ? [ diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 89ebe58..9ce5962 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -51,7 +51,7 @@ class _UpstreamDnsScreenState extends State { @override void initState() { for (var item in widget.serversProvider.dnsInfo.data!.upstreamDns) { - if (item[0] == '#') { + if (item == '#') { dnsServers.add({ 'comment': item }); diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 8f7fd9e..d8608a9 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -137,11 +137,10 @@ class _TopItemsScreenState extends State { } else { appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.serverStatusNotRefreshed), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.serverStatusNotRefreshed, + color: Colors.red ); } }, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 041368e..4e2358b 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -865,7 +865,9 @@ Future getFiltering({ 'result': 'success', 'data': FilteringData.fromJson({ ...jsonDecode(result[0]['body']), - "blocked_services": jsonDecode(result[1]['body']), + "blocked_services": result[1]['body'] != null + ? jsonDecode(result[1]['body']) + : [] }) }; } diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index a332c58..b850b7a 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -239,8 +239,6 @@ class _AddServerModalState extends State { ? await loginHA(serverObj) : await login(serverObj); - setState(() => isConnecting = false); - if (result['result'] == 'success') { if (serverObj.user != null && serverObj.password != null) { serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); @@ -260,6 +258,7 @@ class _AddServerModalState extends State { Navigator.pop(context); } else { + setState(() => isConnecting = false); appConfigProvider.addLog( AppLog( type: 'save_connection_db', @@ -276,6 +275,7 @@ class _AddServerModalState extends State { } } else if (result['result'] == 'invalid_username_password') { + setState(() => isConnecting = false); appConfigProvider.addLog(result['log']); ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -285,6 +285,7 @@ class _AddServerModalState extends State { ); } else if (result['result'] == 'many_attempts') { + setState(() => isConnecting = false); appConfigProvider.addLog(result['log']); ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -294,6 +295,7 @@ class _AddServerModalState extends State { ); } else if (result['result'] == 'no_connection') { + setState(() => isConnecting = false); appConfigProvider.addLog(result['log']); ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -303,6 +305,7 @@ class _AddServerModalState extends State { ); } else if (result['result'] == 'ssl_error') { + setState(() => isConnecting = false); appConfigProvider.addLog(result['log']); ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -312,6 +315,7 @@ class _AddServerModalState extends State { ); } else if (result['result'] == 'server_error') { + setState(() => isConnecting = false); appConfigProvider.addLog(result['log']); ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -321,6 +325,7 @@ class _AddServerModalState extends State { ); } else { + setState(() => isConnecting = false); appConfigProvider.addLog(result['log']); ScaffoldMessenger.of(context).showSnackBar( SnackBar( From 016d9b392ad1ac76c0519ae1f77131aaf58aeeb5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 13 May 2023 01:33:24 +0200 Subject: [PATCH 098/676] Bug fixed --- lib/models/logs.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/models/logs.dart b/lib/models/logs.dart index f48a6b7..f25b8e3 100644 --- a/lib/models/logs.dart +++ b/lib/models/logs.dart @@ -73,7 +73,7 @@ class Log { factory Log.fromJson(Map json) => Log( answerDnssec: json["answer_dnssec"], - cached: json["cached"], + cached: json["cached"] ?? false, client: json["client"], clientInfo: json["client_info"] != null ? ClientInfo.fromJson(json["client_info"]) : null, clientProto: json["client_proto"], From 6459eeb7b324f2e9578c4f4150c8bc57717ceec2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 13 May 2023 01:47:15 +0200 Subject: [PATCH 099/676] Updated android and macos version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index afc725d..f3c2c76 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.1; + MARKETING_VERSION = 2.1.2; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.1; + MARKETING_VERSION = 2.1.2; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.1; + MARKETING_VERSION = 2.1.2; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; diff --git a/pubspec.yaml b/pubspec.yaml index cc5c789..8f8ec73 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.1.1+55 +version: 2.1.2+56 environment: sdk: '>=2.18.1 <3.0.0' From f01d595ce2467366ab353b5310b11ef1bbef2c77 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 13 May 2023 01:58:19 +0200 Subject: [PATCH 100/676] Updated Windows version --- windows/innosetup_installer_builder.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index e6c5f5c..5044207 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AdGuard Home Manager" -#define MyAppVersion "2.1.1" +#define MyAppVersion "2.1.2" #define MyAppPublisher "JGeek00" #define MyAppURL "https://github.com/JGeek00/adguard-home-manager" #define MyAppExeName "adguard_home_manager.exe" From b27fc7eb0f1fc6385619aa20dded32fcbeffaa6e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 13 May 2023 02:07:45 +0200 Subject: [PATCH 101/676] Updated linux version --- debian/debian.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index d84c34b..6adef77 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.1.1 + Version: 2.1.2 Architecture: amd64 Essential: no Priority: optional From 2d0b71720e053c82f880475925237987189ec3d5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 13 May 2023 14:50:19 +0200 Subject: [PATCH 102/676] Bug fixes --- lib/base.dart | 4 +- lib/l10n/app_en.arb | 2 +- lib/l10n/app_es.arb | 2 +- lib/widgets/add_server_modal.dart | 85 ++++++++++++++++--------------- 4 files changed, 47 insertions(+), 46 deletions(-) diff --git a/lib/base.dart b/lib/base.dart index 561b115..a0ad7e4 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -116,9 +116,7 @@ class _BaseState extends State with WidgetsBindingObserver { : screensSelectServer; if (kDebugMode && dotenv.env['ENABLE_SENTRY'] == "true") { - Sentry.captureException("Debug mode", stackTrace: { - "aaa": "aaa" - }); + Sentry.captureMessage("Debug mode"); } return CustomMenuBar( diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 9caaaae..f3f93c8 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -23,7 +23,7 @@ "invalidUsernamePassword": "Invalid username or password", "tooManyAttempts": "Too many attempts. Try again later.", "cantReachServer": "Can't reach server. Check connection data.", - "sslError": "SSL error", + "sslError": "SSL error. Go to Settings > Advanced settings and enable Override SSL validation.", "unknownError": "Unknown error", "connectionNotCreated": "Connection couldn't be created", "connecting": "Connecting...", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 068f8db..2f8ddc4 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -23,7 +23,7 @@ "invalidUsernamePassword": "Usuario o contraseña no válidos.", "tooManyAttempts": "Demasiados intentos. Prueba de nuevo más tarde.", "cantReachServer": "No se puede alcanzar el servidor. Comprueba los datos de conexión.", - "sslError": "Error de SSL", + "sslError": "Error de SSL. Ve a Ajustes > Ajustes avanzados y activa No comprobar SSL.", "unknownError": "Error desconocido", "connectionNotCreated": "No se pudo crear la conexión", "connecting": "Conectando...", diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index b850b7a..6d97343 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -6,6 +6,7 @@ import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/base64.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/app_log.dart'; @@ -218,6 +219,15 @@ class _AddServerModalState extends State { final mediaQuery = MediaQuery.of(context); + void cancelConnecting() { + if (mounted) { + setState(() => isConnecting = false); + } + else { + isConnecting = false; + } + } + void connect() async { Server serverObj = Server( id: uuid.v4(), @@ -266,72 +276,65 @@ class _AddServerModalState extends State { message: serverCreated.toString() ) ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.connectionNotCreated), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionNotCreated, + color: Colors.red ); } } else if (result['result'] == 'invalid_username_password') { - setState(() => isConnecting = false); + cancelConnecting(); appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.invalidUsernamePassword), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.invalidUsernamePassword, + color: Colors.red ); } else if (result['result'] == 'many_attempts') { - setState(() => isConnecting = false); + cancelConnecting(); appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.tooManyAttempts), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.tooManyAttempts, + color: Colors.red ); } else if (result['result'] == 'no_connection') { - setState(() => isConnecting = false); + cancelConnecting(); appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.cantReachServer), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.cantReachServer, + color: Colors.red ); } else if (result['result'] == 'ssl_error') { - setState(() => isConnecting = false); + cancelConnecting(); appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.sslError), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.sslError, + color: Colors.red ); } else if (result['result'] == 'server_error') { - setState(() => isConnecting = false); + cancelConnecting(); appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.serverError), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.serverError, + color: Colors.red ); } else { - setState(() => isConnecting = false); + cancelConnecting(); appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.unknownError), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.unknownError, + color: Colors.red ); } } From 3e281095cd045572c937cb7478e07705888d281f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 13 May 2023 14:54:22 +0200 Subject: [PATCH 103/676] Added horizontal padding --- lib/screens/filters/blocked_services_screen.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/blocked_services_screen.dart index e389878..85d2d23 100644 --- a/lib/screens/filters/blocked_services_screen.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -121,7 +121,8 @@ class _BlockedServicesScreenStateWidget extends State Date: Sat, 13 May 2023 18:33:09 +0200 Subject: [PATCH 104/676] Added unsupported version warning and handle alpha versions --- lib/functions/compare_versions.dart | 104 +++++++++--------- lib/l10n/app_en.arb | 5 +- lib/l10n/app_es.arb | 5 +- lib/providers/servers_provider.dart | 13 +-- lib/screens/connect/fab.dart | 22 +++- lib/screens/servers/servers.dart | 19 +++- lib/services/http_requests.dart | 34 ++++++ lib/widgets/add_server_modal.dart | 28 ++++- .../servers_list/servers_list_item.dart | 15 +++ .../servers_list/servers_tile_item.dart | 15 +++ lib/widgets/version_warning_modal.dart | 46 ++++++++ 11 files changed, 234 insertions(+), 72 deletions(-) create mode 100644 lib/widgets/version_warning_modal.dart diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index e1b8fca..a50a309 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -5,20 +5,54 @@ bool compareVersions({ required String newVersion }) { try { - final currentSplit = currentVersion.split('.').map((e) => int.parse(e)).toList(); - final newSplit = newVersion.split('.').map((e) => int.parse(e)).toList(); + if (currentVersion.contains('a')) { // alpha + return true; + } + else if (currentVersion.contains('b')) { // beta + final current = currentVersion.replaceAll('v', ''); + final newV = currentVersion.replaceAll('v', ''); - if (newSplit[0] > currentSplit[0]) { - return true; + final currentSplit = current.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + final newSplit = newV.split('-')[0].split('.').map((e) => int.parse(e)).toList(); + + final currentBeta = int.parse(current.split('-')[1].replaceAll('b.', '')); + final newBeta = int.parse(newV.split('-')[1].replaceAll('b.', '')); + + if (newSplit[0] > currentSplit[0]) { + return true; + } + else if (newSplit[1] > currentSplit[1]) { + return true; + } + else if (newSplit[2] > currentSplit[2]) { + return true; + } + else if (newBeta > currentBeta) { + return true; + } + else { + return false; + } } - else if (newSplit[1] > currentSplit[1]) { - return true; - } - else if (newSplit[2] > currentSplit[2]) { - return true; - } - else { - return false; + else { // stable + final current = currentVersion.replaceAll('v', ''); + final newV = currentVersion.replaceAll('v', ''); + + final currentSplit = current.split('.').map((e) => int.parse(e)).toList(); + final newSplit = newV.split('.').map((e) => int.parse(e)).toList(); + + if (newSplit[0] > currentSplit[0]) { + return true; + } + else if (newSplit[1] > currentSplit[1]) { + return true; + } + else if (newSplit[2] > currentSplit[2]) { + return true; + } + else { + return false; + } } } catch (e) { Sentry.captureException(e); @@ -33,45 +67,6 @@ bool compareVersions({ } } -bool compareBetaVersions({ - required String currentVersion, - required String newVersion -}) { - try { - final currentSplit = currentVersion.split('-')[0].split('.').map((e) => int.parse(e)).toList(); - final newSplit = newVersion.split('-')[0].split('.').map((e) => int.parse(e)).toList(); - - final currentBeta = int.parse(currentVersion.split('-')[1].replaceAll('b.', '')); - final newBeta = int.parse(newVersion.split('-')[1].replaceAll('b.', '')); - - if (newSplit[0] > currentSplit[0]) { - return true; - } - else if (newSplit[1] > currentSplit[1]) { - return true; - } - else if (newSplit[2] > currentSplit[2]) { - return true; - } - else if (newBeta > currentBeta) { - return true; - } - else { - return false; - } - } catch (e) { - Sentry.captureException(e); - Sentry.captureMessage("compareBetaVersions error", params: [ - { - "fn": "compareBetaVersions", - "currentVersion": currentVersion, - "newVersion": newVersion, - }.toString() - ]); - return false; - } -} - bool serverVersionIsAhead({ required String currentVersion, required String referenceVersion, @@ -82,7 +77,10 @@ bool serverVersionIsAhead({ final reference = referenceVersion.replaceAll('v', ''); final referenceBeta = referenceVersionBeta?.replaceAll('v', ''); - if (current.contains('b')) { + if (currentVersion.contains('a')) { // alpha + return true; + } + else if (current.contains('b')) { // beta if (referenceBeta != null) { final currentSplit = current.split('-')[0].split('.').map((e) => int.parse(e)).toList(); final newSplit = referenceBeta.split('-')[0].split('.').map((e) => int.parse(e)).toList(); @@ -113,7 +111,7 @@ bool serverVersionIsAhead({ return false; } } - else { + else { // stable final currentSplit = current.split('.').map((e) => int.parse(e)).toList(); final newSplit = reference.split('.').map((e) => int.parse(e)).toList(); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f3f93c8..07d97b4 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -617,5 +617,8 @@ "seeDetails": "See details", "listNotAvailable": "List not available", "copyListUrl": "Copy list URL", - "listUrlCopied": "List URL copied to the clipboard" + "listUrlCopied": "List URL copied to the clipboard", + "unsupportedVersion": "Unsupported version", + "unsupprtedVersionMessage": "The support for your server version {version} is not guaranteed. This application may have some issues working with that server version.\n\nAdGuard Home Manager is designed to work with the stable releases of the AdGuard Home server. It may work with alpha and beta releases, but the compatibility is not guaranteed and the app may have some issues working with that versions.", + "iUnderstand": "I understand" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 2f8ddc4..3b8674f 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -617,5 +617,8 @@ "seeDetails": "Ver los detalles", "listNotAvailable": "Lista no disponible", "copyListUrl": "Copiar URL de lista", - "listUrlCopied": "URL de la lista copiada al portapapeles" + "listUrlCopied": "URL de la lista copiada al portapapeles", + "unsupportedVersion": "Versión no soportada", + "unsupprtedVersionMessage": "El soporte para la versión del servidor {version} no está garantizada. Esta aplicación puede tener problemas al trabajar con esa versión del servidor.\n\nAdGuard Home Manager está diseñado para trabajar con las versiones estables del servidor AdGuard Home. Puede funcionar con versiones alpha y beta, pero la compatibilidad no está asegurada y la aplicación puede tener problemas para trabajar con esas versiones.", + "iUnderstand": "Lo entiendo" } \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index e59d8ae..6d8500c 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -535,15 +535,10 @@ class ServersProvider with ChangeNotifier { data.changelog = gitHubResult['body']; } data.updateAvailable = data.newVersion != null - ? data.newVersion!.contains('b') - ? compareBetaVersions( - currentVersion: data.currentVersion.replaceAll('v', ''), - newVersion: data.newVersion!.replaceAll('v', ''), - ) - : compareVersions( - currentVersion: data.currentVersion.replaceAll('v', ''), - newVersion: data.newVersion!.replaceAll('v', ''), - ) + ? compareVersions( + currentVersion: data.currentVersion, + newVersion: data.newVersion!, + ) : false; setUpdateAvailableData(data); setUpdateAvailableLoadStatus(LoadStatus.loaded, true); diff --git a/lib/screens/connect/fab.dart b/lib/screens/connect/fab.dart index c20cafc..47cb65e 100644 --- a/lib/screens/connect/fab.dart +++ b/lib/screens/connect/fab.dart @@ -1,6 +1,8 @@ -import 'package:adguard_home_manager/widgets/add_server_modal.dart'; import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/widgets/add_server_modal.dart'; +import 'package:adguard_home_manager/widgets/version_warning_modal.dart'; + class FabConnect extends StatelessWidget { const FabConnect({Key? key}) : super(key: key); @@ -14,16 +16,30 @@ class FabConnect extends StatelessWidget { showDialog( context: context, barrierDismissible: false, - builder: (context) => const AddServerModal( + builder: (context) => AddServerModal( window: true, + onUnsupportedVersion: (version) => showDialog( + context: context, + builder: (ctx) => VersionWarningModal( + version: version + ), + barrierDismissible: false + ), ), ) } else { Navigator.push(context, MaterialPageRoute( fullscreenDialog: true, - builder: (BuildContext context) => const AddServerModal( + builder: (BuildContext context) => AddServerModal( window: false, + onUnsupportedVersion: (version) => showDialog( + context: context, + builder: (ctx) => VersionWarningModal( + version: version + ), + barrierDismissible: false + ), ) )) } diff --git a/lib/screens/servers/servers.dart b/lib/screens/servers/servers.dart index ba1e7b3..8a557fb 100644 --- a/lib/screens/servers/servers.dart +++ b/lib/screens/servers/servers.dart @@ -6,6 +6,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:adguard_home_manager/widgets/version_warning_modal.dart'; import 'package:adguard_home_manager/widgets/servers_list/servers_list.dart'; import 'package:adguard_home_manager/widgets/add_server_modal.dart'; @@ -72,16 +73,30 @@ class _ServersState extends State { showDialog( context: context, barrierDismissible: false, - builder: (context) => const AddServerModal( + builder: (context) => AddServerModal( window: true, + onUnsupportedVersion: (version) => showDialog( + context: context, + builder: (ctx) => VersionWarningModal( + version: version + ), + barrierDismissible: false + ), ), ) } else { Navigator.push(context, MaterialPageRoute( fullscreenDialog: true, - builder: (BuildContext context) => const AddServerModal( + builder: (BuildContext context) => AddServerModal( window: false, + onUnsupportedVersion: (version) => showDialog( + context: context, + builder: (ctx) => VersionWarningModal( + version: version + ), + barrierDismissible: false + ), ) )) } diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 4e2358b..bc312ea 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -263,6 +263,40 @@ Future loginHA(Server server) async { } } +Future getServerVersion(Server server) async { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/status', + type: 'get_server_version' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200 && result['body'] != null) { + print( result['body']['version']); + return { + 'result': 'success', + 'data': result['body']['version'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_version', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } +} + Future getServerStatus(Server server) async { final result = await Future.wait([ apiRequest(server: server, method: 'get', urlPath: '/stats', type: 'server_status'), diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 6d97343..72e67e5 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -18,11 +18,13 @@ enum ConnectionType { http, https} class AddServerModal extends StatefulWidget { final Server? server; final bool window; + final void Function(String version) onUnsupportedVersion; const AddServerModal({ Key? key, this.server, - required this.window + required this.window, + required this.onUnsupportedVersion }) : super(key: key); @override @@ -256,16 +258,25 @@ class _AddServerModalState extends State { final serverCreated = await serversProvider.createServer(serverObj); if (serverCreated == null) { serversProvider.setServerStatusLoad(0); + final serverStatus = await getServerStatus(serverObj); + if (serverStatus['result'] == 'success') { serversProvider.setServerStatusData(serverStatus['data']); serversProvider.setServerStatusLoad(1); + if (serverStatus['data'].serverVersion.contains('a') || serverStatus['data'].serverVersion.contains('b')) { + Navigator.pop(context); + widget.onUnsupportedVersion(serverStatus['data'].serverVersion); + } + else { + Navigator.pop(context); + } } else { appConfigProvider.addLog(serverStatus['log']); serversProvider.setServerStatusLoad(2); + Navigator.pop(context); } - Navigator.pop(context); } else { setState(() => isConnecting = false); @@ -364,8 +375,19 @@ class _AddServerModalState extends State { serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); } final serverSaved = await serversProvider.editServer(serverObj); + if (serverSaved == null) { - Navigator.pop(context); + final version = await getServerVersion(serverObj);; + if ( + version['result'] == 'success' && + (version['data'].contains('a') || version['data'].contains('b')) // alpha or beta + ) { + Navigator.pop(context); + widget.onUnsupportedVersion(version); + } + else { + Navigator.pop(context); + } } else { appConfigProvider.addLog( diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index abd625e..614c2ca 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -5,6 +5,7 @@ import 'package:expandable/expandable.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/version_warning_modal.dart'; import 'package:adguard_home_manager/widgets/add_server_modal.dart'; import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; @@ -93,6 +94,13 @@ class _ServersListItemState extends State with SingleTickerProv builder: (context) => AddServerModal( server: server, window: true, + onUnsupportedVersion: (version) => showDialog( + context: context, + builder: (ctx) => VersionWarningModal( + version: version + ), + barrierDismissible: false + ), ), ) } @@ -102,6 +110,13 @@ class _ServersListItemState extends State with SingleTickerProv builder: (BuildContext context) => AddServerModal( server: server, window: false, + onUnsupportedVersion: (version) => showDialog( + context: context, + builder: (ctx) => VersionWarningModal( + version: version + ), + barrierDismissible: false + ), ) )) } diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index 8f6db23..8145b5e 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/version_warning_modal.dart'; import 'package:adguard_home_manager/widgets/add_server_modal.dart'; import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; @@ -60,6 +61,13 @@ class _ServersTileItemState extends State with SingleTickerProv builder: (context) => AddServerModal( server: server, window: true, + onUnsupportedVersion: (version) => showDialog( + context: context, + builder: (ctx) => VersionWarningModal( + version: version + ), + barrierDismissible: false + ), ), ) } @@ -69,6 +77,13 @@ class _ServersTileItemState extends State with SingleTickerProv builder: (BuildContext context) => AddServerModal( server: server, window: false, + onUnsupportedVersion: (version) => showDialog( + context: context, + builder: (ctx) => VersionWarningModal( + version: version + ), + barrierDismissible: false + ), ) )) } diff --git a/lib/widgets/version_warning_modal.dart b/lib/widgets/version_warning_modal.dart new file mode 100644 index 0000000..f2230b0 --- /dev/null +++ b/lib/widgets/version_warning_modal.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class VersionWarningModal extends StatelessWidget { + final String version; + + const VersionWarningModal({ + Key? key, + required this.version, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return AlertDialog( + scrollable: true, + title: Column( + children: [ + Icon( + Icons.warning_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.unsupportedVersion, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: Text(AppLocalizations.of(context)!.unsupprtedVersionMessage(version)), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.iUnderstand) + ) + ], + ) + ], + ); + } +} \ No newline at end of file From 5452c83743ab7cc5baf4c638d6bb4609e24dd768 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 14 May 2023 16:19:08 +0200 Subject: [PATCH 105/676] Bugs fixed --- lib/providers/app_config_provider.dart | 2 +- lib/widgets/add_server_modal.dart | 63 ++++++++++++-------------- 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index caa7dff..ddb0bd6 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -192,7 +192,7 @@ class AppConfigProvider with ChangeNotifier { Future setHideZeroValues(bool status) async { final updated = await updateConfigQuery( db: _dbInstance!, - column: 'overrideSslCheck', + column: 'hideZeroValues', value: status == true ? 1 : 0 ); if (updated == true) { diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 72e67e5..4eba693 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -397,66 +397,59 @@ class _AddServerModalState extends State { message: serverSaved.toString() ) ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.connectionNotCreated), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionNotCreated, + color: Colors.red ); } } else if (result['result'] == 'invalid_username_password') { appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.invalidUsernamePassword), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.invalidUsernamePassword, + color: Colors.red ); } else if (result['result'] == 'many_attempts') { appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.tooManyAttempts), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.tooManyAttempts, + color: Colors.red ); } else if (result['result'] == 'no_connection') { appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.cantReachServer), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.cantReachServer, + color: Colors.red ); } else if (result['result'] == 'ssl_error') { appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.sslError), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.sslError, + color: Colors.red ); } else if (result['result'] == 'server_error') { appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.serverError), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.serverError, + color: Colors.red ); } else { appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.unknownError), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.unknownError, + color: Colors.red ); } } From b06a44f1973e6b4bc13feae1a8f5e726891e5c8d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 14 May 2023 17:18:38 +0200 Subject: [PATCH 106/676] Fixed minor issue --- .../settings/encryption/encryption.dart | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 5ed088e..6af29ab 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -155,24 +155,26 @@ class _EncryptionSettingsWidgetState extends State { if (privateKeyOption == 0) "private_key_path": privateKeyPathController.text, }); - if (result['result'] == 'success') { - setState(() { - if (result['data']['warning_validation'] != null && result['data']['warning_validation'] != '') { - certKeyValidApi = 2; - validDataError = result['data']['warning_validation']; - } - else { - certKeyValidApi = 1; - validDataError = null; - } - certKeyValid = result['data']; - }); - } - else { - if (result['log'].resBody != null) { - setState(() => validDataError = result['log'].resBody); + if (mounted) { + if (result['result'] == 'success') { + setState(() { + if (result['data']['warning_validation'] != null && result['data']['warning_validation'] != '') { + certKeyValidApi = 2; + validDataError = result['data']['warning_validation']; + } + else { + certKeyValidApi = 1; + validDataError = null; + } + certKeyValid = result['data']; + }); + } + else { + if (result['log'].resBody != null) { + setState(() => validDataError = result['log'].resBody); + } + setState(() => certKeyValidApi = 2); } - setState(() => certKeyValidApi = 2); } } From bea4d521289f9edcbf47da02afe7d967ad2431ce Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 14 May 2023 23:54:47 +0200 Subject: [PATCH 107/676] Updated android and macos version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index f3c2c76..2cec350 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 56; + CURRENT_PROJECT_VERSION = 57; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.2; + MARKETING_VERSION = 2.1.3; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 56; + CURRENT_PROJECT_VERSION = 57; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.2; + MARKETING_VERSION = 2.1.3; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 56; + CURRENT_PROJECT_VERSION = 57; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.2; + MARKETING_VERSION = 2.1.3; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; diff --git a/pubspec.yaml b/pubspec.yaml index 8f8ec73..bbe80f2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.1.2+56 +version: 2.1.3+57 environment: sdk: '>=2.18.1 <3.0.0' From 3662b7b3cb8999e3a73c6a6159ccf777375e22d7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 15 May 2023 00:01:21 +0200 Subject: [PATCH 108/676] Updated Windows version --- windows/innosetup_installer_builder.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 5044207..704a820 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AdGuard Home Manager" -#define MyAppVersion "2.1.2" +#define MyAppVersion "2.1.3" #define MyAppPublisher "JGeek00" #define MyAppURL "https://github.com/JGeek00/adguard-home-manager" #define MyAppExeName "adguard_home_manager.exe" From a0a1b0b93b07577c4354fe0eb1dc06a56df8ecda Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 15 May 2023 00:08:03 +0200 Subject: [PATCH 109/676] Updated linux version --- debian/debian.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index 6adef77..69e2b8e 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.1.2 + Version: 2.1.3 Architecture: amd64 Essential: no Priority: optional From 7bd59fef1106e2d207fc2723fae951477be2a3ee Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 15 May 2023 22:31:22 +0200 Subject: [PATCH 110/676] Removed print --- lib/services/http_requests.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index bc312ea..4526f3e 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -273,7 +273,6 @@ Future getServerVersion(Server server) async { if (result['hasResponse'] == true) { if (result['statusCode'] == 200 && result['body'] != null) { - print( result['body']['version']); return { 'result': 'success', 'data': result['body']['version'] From e0ecac5415ca1626d77dc0ce9017cc02c148d2f6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 17 May 2023 20:48:43 +0200 Subject: [PATCH 111/676] Minor fixes --- lib/models/encryption.dart | 4 ++-- lib/models/logs.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/models/encryption.dart b/lib/models/encryption.dart index e0e0a4d..6187faf 100644 --- a/lib/models/encryption.dart +++ b/lib/models/encryption.dart @@ -27,7 +27,7 @@ class EncryptionData { final bool validPair; final bool enabled; final String? serverName; - final bool forceHttps; + final bool? forceHttps; final int? portHttps; final int? portDnsOverTls; final int? portDnsOverQuic; @@ -81,7 +81,7 @@ class EncryptionData { validPair: json["valid_pair"], enabled: json["enabled"], serverName: json["server_name"], - forceHttps: json["force_https"], + forceHttps: json["force_https"] ?? false, portHttps: json["port_https"], portDnsOverTls: json["port_dns_over_tls"], portDnsOverQuic: json["port_dns_over_quic"], diff --git a/lib/models/logs.dart b/lib/models/logs.dart index f25b8e3..c6122e5 100644 --- a/lib/models/logs.dart +++ b/lib/models/logs.dart @@ -39,7 +39,7 @@ class Log { final bool cached; final String client; final ClientInfo? clientInfo; - final String clientProto; + final String? clientProto; final String elapsedMs; final Question question; final String reason; From 71a7908da52e3ba28046670faa577bac8e0688ff Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 17 May 2023 21:50:13 +0200 Subject: [PATCH 112/676] Added option to recheck app updates --- lib/base.dart | 30 +++---- lib/functions/app_update_download_link.dart | 21 +++++ lib/functions/compare_versions.dart | 18 +++++ lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/main.dart | 4 + lib/providers/app_config_provider.dart | 24 ++++++ lib/screens/settings/general_settings.dart | 90 ++++++++++++++++++++- lib/widgets/update_modal.dart | 23 +----- 9 files changed, 171 insertions(+), 47 deletions(-) create mode 100644 lib/functions/app_update_download_link.dart diff --git a/lib/base.dart b/lib/base.dart index a0ad7e4..c43b106 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -18,6 +18,7 @@ import 'package:adguard_home_manager/widgets/update_modal.dart'; import 'package:adguard_home_manager/widgets/navigation_rail.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/github_release.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -40,36 +41,23 @@ class Base extends StatefulWidget { class _BaseState extends State with WidgetsBindingObserver { int selectedScreen = 0; - bool updateExists(String appVersion, String gitHubVersion) { - final List appVersionSplit = List.from(appVersion.split('.').map((e) => int.parse(e))); - final List gitHubVersionSplit = List.from(gitHubVersion.split('.').map((e) => int.parse(e))); - if (gitHubVersionSplit[0] > appVersionSplit[0]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] > appVersionSplit[1]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] > appVersionSplit[2]) { - return true; - } - else { - return false; - } - } Future checkInstallationSource() async { final result = await checkAppUpdatesGitHub(); if (result['result'] == 'success') { - final update = updateExists(widget.appConfigProvider.getAppInfo!.version, result['body'].tagName); + final update = gitHubUpdateExists(widget.appConfigProvider.getAppInfo!.version, result['body'].tagName); if (update == true) { + widget.appConfigProvider.setAppUpdatesAvailable(result['body']); if (Platform.isAndroid) { - Source installationSource = await StoreChecker.getSource; - if (installationSource == Source.IS_INSTALLED_FROM_PLAY_STORE) { - return null; + if ( + widget.appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || + widget.appConfigProvider.installationSource == Source.UNKNOWN + ) { + return result['body']; } else { - return result['body']; + return null; } } else if (Platform.isIOS) { diff --git a/lib/functions/app_update_download_link.dart b/lib/functions/app_update_download_link.dart new file mode 100644 index 0000000..76c1a2d --- /dev/null +++ b/lib/functions/app_update_download_link.dart @@ -0,0 +1,21 @@ +import 'dart:io'; + +import 'package:adguard_home_manager/models/github_release.dart'; + +String? getAppUpdateDownloadLink(GitHubRelease gitHubRelease) { + if (Platform.isAndroid) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('apk')).browserDownloadUrl; + } + else if (Platform.isMacOS) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('macOS')).browserDownloadUrl; // macOS package is a zip + } + else if (Platform.isWindows) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('exe')).browserDownloadUrl; + } + else if (Platform.isLinux) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('deb')).browserDownloadUrl; + } + else { + return null; + } +} \ No newline at end of file diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index a50a309..df299b3 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -143,4 +143,22 @@ bool serverVersionIsAhead({ ]); return false; } +} + +bool gitHubUpdateExists(String appVersion, String gitHubVersion) { + final List appVersionSplit = List.from(appVersion.split('.').map((e) => int.parse(e))); + final List gitHubVersionSplit = List.from(gitHubVersion.split('.').map((e) => int.parse(e))); + + if (gitHubVersionSplit[0] > appVersionSplit[0]) { + return true; + } + else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] > appVersionSplit[1]) { + return true; + } + else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] > appVersionSplit[2]) { + return true; + } + else { + return false; + } } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 07d97b4..7ad8a7b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -620,5 +620,7 @@ "listUrlCopied": "List URL copied to the clipboard", "unsupportedVersion": "Unsupported version", "unsupprtedVersionMessage": "The support for your server version {version} is not guaranteed. This application may have some issues working with that server version.\n\nAdGuard Home Manager is designed to work with the stable releases of the AdGuard Home server. It may work with alpha and beta releases, but the compatibility is not guaranteed and the app may have some issues working with that versions.", - "iUnderstand": "I understand" + "iUnderstand": "I understand", + "appUpdates": "Application updates", + "usingLatestVersion": "You are using the latest version" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 3b8674f..e8c8477 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -620,5 +620,7 @@ "listUrlCopied": "URL de la lista copiada al portapapeles", "unsupportedVersion": "Versión no soportada", "unsupprtedVersionMessage": "El soporte para la versión del servidor {version} no está garantizada. Esta aplicación puede tener problemas al trabajar con esa versión del servidor.\n\nAdGuard Home Manager está diseñado para trabajar con las versiones estables del servidor AdGuard Home. Puede funcionar con versiones alpha y beta, pero la compatibilidad no está asegurada y la aplicación puede tener problemas para trabajar con esas versiones.", - "iUnderstand": "Lo entiendo" + "iUnderstand": "Lo entiendo", + "appUpdates": "Actualizaciones de la app", + "usingLatestVersion": "Estás usando la última versión" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 3e8ae84..24f7bc2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; +import 'package:store_checker/store_checker.dart'; import 'package:window_size/window_size.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -60,6 +61,9 @@ void main() async { HttpOverrides.global = MyHttpOverrides(); } + Source installationSource = await StoreChecker.getSource; + appConfigProvider.setInstallationSource(installationSource); + serversProvider.setDbInstance(dbData['dbInstance']); appConfigProvider.saveFromDb(dbData['dbInstance'], dbData['appConfig']); serversProvider.saveFromDb(dbData['servers']); diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index ddb0bd6..7c1ae85 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/scheduler.dart'; +import 'package:store_checker/store_checker.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sqflite/sqlite_api.dart'; +import 'package:adguard_home_manager/models/github_release.dart'; import 'package:adguard_home_manager/services/db/queries.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/models/app_log.dart'; @@ -39,6 +41,10 @@ class AppConfigProvider with ChangeNotifier { String? _doNotRememberVersion; + GitHubRelease? _appUpdatesAvailable; + + Source _installationSource = Source.UNKNOWN; + PackageInfo? get getAppInfo { return _appInfo; } @@ -125,6 +131,14 @@ class AppConfigProvider with ChangeNotifier { return _selectedSettingsScreen; } + GitHubRelease? get appUpdatesAvailable { + return _appUpdatesAvailable; + } + + Source get installationSource { + return _installationSource; + } + void setDbInstance(Database db) { _dbInstance = db; } @@ -173,6 +187,16 @@ class AppConfigProvider with ChangeNotifier { } } + void setAppUpdatesAvailable(GitHubRelease value) { + _appUpdatesAvailable = value; + notifyListeners(); + } + + void setInstallationSource(Source value) { + _installationSource = value; + notifyListeners(); + } + Future setOverrideSslCheck(bool status) async { final updated = await updateConfigQuery( db: _dbInstance!, diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index fed1be1..18957d7 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -1,16 +1,32 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:store_checker/store_checker.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; +import 'package:adguard_home_manager/functions/app_update_download_link.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; -class GeneralSettings extends StatelessWidget { +class GeneralSettings extends StatefulWidget { const GeneralSettings({Key? key}) : super(key: key); + @override + State createState() => _GeneralSettingsState(); +} + +enum AppUpdatesStatus { available, checking, recheck } + +class _GeneralSettingsState extends State { + AppUpdatesStatus appUpdatesStatus = AppUpdatesStatus.recheck; + @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); @@ -55,6 +71,60 @@ class GeneralSettings extends StatelessWidget { } } + Future checkUpdatesAvailable() async { + setState(() => appUpdatesStatus = AppUpdatesStatus.checking); + final result = await checkAppUpdatesGitHub(); + if (result['result'] == 'success') { + final update = gitHubUpdateExists(appConfigProvider.getAppInfo!.version, result['body'].tagName); + if (update == true) { + appConfigProvider.setAppUpdatesAvailable(result['body']); + setState(() => appUpdatesStatus = AppUpdatesStatus.available); + } + else { + setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); + } + } + else { + setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); + } + } + + Widget generateAppUpdateStatus() { + if (appUpdatesStatus == AppUpdatesStatus.available) { + return IconButton( + onPressed: appConfigProvider.appUpdatesAvailable != null + ? () async { + final link = getAppUpdateDownloadLink(appConfigProvider.appUpdatesAvailable!); + if (link != null) { + openUrl(link); + } + } + : null, + icon: const Icon(Icons.download_rounded), + tooltip: AppLocalizations.of(context)!.downloadUpdate, + ); + } + else if (appUpdatesStatus == AppUpdatesStatus.checking) { + return const Padding( + padding: EdgeInsets.only(right: 16), + child: SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator( + strokeWidth: 3, + ) + ), + ); + } + else { + return IconButton( + onPressed: checkUpdatesAvailable, + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.checkUpdates, + ); + } + } + return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.generalSettings), @@ -74,7 +144,7 @@ class GeneralSettings extends StatelessWidget { padding: const EdgeInsets.only( top: 10, bottom: 10, - left: 20, + left: 16, right: 10 ) ), @@ -90,10 +160,24 @@ class GeneralSettings extends StatelessWidget { padding: const EdgeInsets.only( top: 10, bottom: 10, - left: 20, + left: 16, right: 10 ) ), + if ( + !(Platform.isAndroid || Platform.isIOS) || + (Platform.isAndroid && ( + appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE) || + appConfigProvider.installationSource == Source.UNKNOWN + ) + ) CustomListTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.appUpdates, + subtitle: appConfigProvider.appUpdatesAvailable != null + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.usingLatestVersion, + trailing: generateAppUpdateStatus() + ) ], ), ); diff --git a/lib/widgets/update_modal.dart b/lib/widgets/update_modal.dart index a6f456a..d8f164f 100644 --- a/lib/widgets/update_modal.dart +++ b/lib/widgets/update_modal.dart @@ -1,9 +1,8 @@ -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/functions/app_update_download_link.dart'; import 'package:adguard_home_manager/models/github_release.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -24,29 +23,11 @@ class UpdateModal extends StatefulWidget { class _UpdateModalState extends State { bool doNotRemember = false; - String? getDownloadLink() { - if (Platform.isAndroid) { - return widget.gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('apk')).browserDownloadUrl; - } - else if (Platform.isMacOS) { - return widget.gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('macOS')).browserDownloadUrl; // macOS package is a zip - } - else if (Platform.isWindows) { - return widget.gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('exe')).browserDownloadUrl; - } - else if (Platform.isLinux) { - return widget.gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('deb')).browserDownloadUrl; - } - else { - return null; - } - } - @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - final downloadLink = getDownloadLink(); + final downloadLink = getAppUpdateDownloadLink(widget.gitHubRelease); return AlertDialog( scrollable: true, From 105a6facf3c5d06da8b4e1c3689185a108cb6a70 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 17 May 2023 22:02:05 +0200 Subject: [PATCH 113/676] Small fix --- lib/base.dart | 2 -- lib/main.dart | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/base.dart b/lib/base.dart index c43b106..932d635 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -41,8 +41,6 @@ class Base extends StatefulWidget { class _BaseState extends State with WidgetsBindingObserver { int selectedScreen = 0; - - Future checkInstallationSource() async { final result = await checkAppUpdatesGitHub(); if (result['result'] == 'success') { diff --git a/lib/main.dart b/lib/main.dart index 24f7bc2..135685f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -61,8 +61,10 @@ void main() async { HttpOverrides.global = MyHttpOverrides(); } - Source installationSource = await StoreChecker.getSource; - appConfigProvider.setInstallationSource(installationSource); + if (Platform.isAndroid || Platform.isIOS) { + Source installationSource = await StoreChecker.getSource; + appConfigProvider.setInstallationSource(installationSource); + } serversProvider.setDbInstance(dbData['dbInstance']); appConfigProvider.saveFromDb(dbData['dbInstance'], dbData['appConfig']); From 6ee6a5c8b562efa518c4c1015871c5e1c342cfce Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 17 May 2023 22:14:24 +0200 Subject: [PATCH 114/676] Updated app version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 2cec350..1406889 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 57; + CURRENT_PROJECT_VERSION = 58; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.3; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 57; + CURRENT_PROJECT_VERSION = 58; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.3; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 57; + CURRENT_PROJECT_VERSION = 58; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.1.3; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; diff --git a/pubspec.yaml b/pubspec.yaml index bbe80f2..62642df 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.1.3+57 +version: 2.2.0+58 environment: sdk: '>=2.18.1 <3.0.0' From 3a73422758ae1aa96ead46a6319e8b029dadad62 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 17 May 2023 22:25:58 +0200 Subject: [PATCH 115/676] Updated linux version --- debian/debian.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index 69e2b8e..6c23be8 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.1.3 + Version: 2.2.0 Architecture: amd64 Essential: no Priority: optional From dcca75e228c3d228e2dd1bead3efb465c4a93822 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 17 May 2023 22:32:09 +0200 Subject: [PATCH 116/676] Updated windows version --- windows/innosetup_installer_builder.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 704a820..79b9261 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AdGuard Home Manager" -#define MyAppVersion "2.1.3" +#define MyAppVersion "2.2.0" #define MyAppPublisher "JGeek00" #define MyAppURL "https://github.com/JGeek00/adguard-home-manager" #define MyAppExeName "adguard_home_manager.exe" From 64e526b20ea012c5b6fddcde05e86dc7f692d7c5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 18 May 2023 01:32:52 +0200 Subject: [PATCH 117/676] Support Flutter 3.10 --- android/build.gradle | 2 +- lib/screens/connect/appbar.dart | 16 -- lib/screens/home/appbar.dart | 2 +- .../settings/update_server/update.dart | 2 +- pubspec.lock | 178 +++++++++--------- 5 files changed, 92 insertions(+), 108 deletions(-) delete mode 100644 lib/screens/connect/appbar.dart diff --git a/android/build.gradle b/android/build.gradle index 61a47e7..f546a89 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/lib/screens/connect/appbar.dart b/lib/screens/connect/appbar.dart deleted file mode 100644 index a75540f..0000000 --- a/lib/screens/connect/appbar.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -class ConnectAppBar extends StatelessWidget with PreferredSizeWidget { - const ConnectAppBar({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return AppBar( - title: Text(AppLocalizations.of(context)!.connect), - ); - } - - @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight); -} \ No newline at end of file diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 71933fd..1ed4ed1 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -9,7 +9,7 @@ import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class HomeAppBar extends StatelessWidget with PreferredSizeWidget { +class HomeAppBar extends StatelessWidget implements PreferredSizeWidget { const HomeAppBar({Key? key}) : super(key: key); @override diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index 8643195..5e88a2e 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -191,7 +191,7 @@ class UpdateScreen extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 16), child: Html( data: html.parse(md.markdownToHtml(serversProvider.updateAvailable.data!.changelog!)).outerHtml, - onLinkTap: (url, context, attributes, element) => url != null ? openUrl(url) : null, + onLinkTap: (url, context, attributes) => url != null ? openUrl(url) : null, ) ) ], diff --git a/pubspec.lock b/pubspec.lock index d2db277..3c02255 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,26 +21,26 @@ packages: dependency: transitive description: name: archive - sha256: ed7cc591a948744994714375caf9a2ce89e1d82e8243997c8a2994d57181c212 + sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" url: "https://pub.dev" source: hosted - version: "3.3.5" + version: "3.3.7" args: dependency: transitive description: name: args - sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" async: dependency: "direct main" description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" boolean_selector: dependency: transitive description: @@ -53,18 +53,18 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: name: checked_yaml - sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" cli_util: dependency: transitive description: @@ -85,10 +85,10 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" contextmenu: dependency: "direct main" description: @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" csslib: dependency: transitive description: @@ -181,10 +181,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: bbebb1b7ebed819e0ec83d4abdc2a8482d934f6a85289ffc1c6acf7589fa2aad + sha256: "74dff1435a695887ca64899b8990004f8d1232b0e84bfc4faa1fdda7c6f57cc1" url: "https://pub.dev" source: hosted - version: "1.6.3" + version: "1.6.5" equatable: dependency: transitive description: @@ -213,10 +213,10 @@ packages: dependency: transitive description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" file: dependency: transitive description: @@ -258,10 +258,10 @@ packages: dependency: "direct main" description: name: flutter_html - sha256: "342c7908f0a67bcec62b6e0f7cf23e23bafe7f64693665dd35be98d5e783bdfd" + sha256: "850c07bc6c1ed060d3eb3e88469a598260a13eb45d8978b197c1348e0a2b101f" url: "https://pub.dev" source: hosted - version: "3.0.0-alpha.6" + version: "3.0.0-beta.1" flutter_launcher_icons: dependency: "direct dev" description: @@ -295,10 +295,10 @@ packages: dependency: "direct dev" description: name: flutter_native_splash - sha256: "048bd1f1dc0e5ea25899f702815934d9a9e916fe23451c320e7dd94d5e3ad933" + sha256: "02df24aec455c26428dadc637f20d4c548bda23ee2179479a8e8c39f1ecb75b3" url: "https://pub.dev" source: hosted - version: "2.2.17" + version: "2.3.0" flutter_split_view: dependency: "direct main" description: @@ -338,18 +338,18 @@ packages: dependency: "direct main" description: name: html - sha256: "79d498e6d6761925a34ee5ea8fa6dfef38607781d2fa91e37523474282af55cb" + sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" url: "https://pub.dev" source: hosted - version: "0.15.2" + version: "0.15.3" http: dependency: transitive description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "0.13.6" http_parser: dependency: transitive description: @@ -362,58 +362,66 @@ packages: dependency: transitive description: name: image - sha256: "73964e3609fb96e01e69b0924b939967c556e46c7ff05db2ea9e31019000f4ef" + sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf url: "https://pub.dev" source: hosted - version: "4.0.16" + version: "4.0.17" intl: dependency: "direct main" description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.0" js: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: name: json_annotation - sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.8.1" lints: dependency: transitive description: name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" + list_counter: + dependency: transitive + description: + name: list_counter + sha256: c447ae3dfcd1c55f0152867090e67e219d42fe6d4f2807db4bbe8b8d69912237 + url: "https://pub.dev" + source: hosted + version: "1.0.2" markdown: dependency: "direct main" description: name: markdown - sha256: d95a9d12954aafc97f984ca29baaa7690ed4d9ec4140a23ad40580bcdb6c87f5 + sha256: "8e332924094383133cee218b676871f42db2514f1f6ac617b6cf6152a7faab8e" url: "https://pub.dev" source: hosted - version: "7.0.2" + version: "7.1.0" matcher: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -426,10 +434,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" nested: dependency: transitive description: @@ -438,14 +446,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" - numerus: - dependency: transitive - description: - name: numerus - sha256: "436759d84f233b40107d0cc31cfa92d24e0960afeb2e506be70926d4cddffd9e" - url: "https://pub.dev" - source: hosted - version: "2.0.0" package_info_plus: dependency: "direct main" description: @@ -466,10 +466,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_drawing: dependency: transitive description: @@ -490,34 +490,34 @@ packages: dependency: "direct main" description: name: percent_indicator - sha256: cec41f67181fbd5322aa68b355621d1a4eea827426b8eeb613f6cbe195ff7b4a + sha256: c37099ad833a883c9d71782321cb65c3a848c21b6939b6185f0ff6640d05814c url: "https://pub.dev" source: hosted - version: "4.2.2" + version: "4.2.3" petitparser: dependency: transitive description: name: petitparser - sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.4.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" pointycastle: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.3" provider: dependency: "direct main" description: @@ -530,18 +530,18 @@ packages: dependency: transitive description: name: sentry - sha256: "8f2ff67c168c640567093f9f80f6cdfa34c009b89fb81732e896b9e95c3b87e8" + sha256: "01f8fc950b6a5f3daf8c2d2b0ae5c38812e63d703c19c56cb68524c0597660bc" url: "https://pub.dev" source: hosted - version: "7.5.1" + version: "7.6.1" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "4de19f8b353eac472609f6c42b2bb0dd38d5a128c3e4a6ac6c0a9574b85fde47" + sha256: "9583ebcdbbba6907e555a8eeaf42380021baff57db1e399a3a31e80ce1f1cbe5" url: "https://pub.dev" source: hosted - version: "7.5.1" + version: "7.6.1" sky_engine: dependency: transitive description: flutter @@ -559,10 +559,10 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "8453780d1f703ead201a39673deb93decf85d543f359f750e2afc4908b55533f" + sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 url: "https://pub.dev" source: hosted - version: "2.2.8" + version: "2.2.8+4" sqflite_common: dependency: transitive description: @@ -583,18 +583,18 @@ packages: dependency: transitive description: name: sqlite3 - sha256: a3ba4b66a7ab170ce7aa3f5ac43c19ee8d6637afbe7b7c95c94112b4f4d91566 + sha256: "2cef47b59d310e56f8275b13734ee80a9cf4a48a43172020cb55a620121fbf66" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: "02f80aea54a19a36b347dedf6d4181ecd9107f5831ea6139cfd0376a3de197ba" + sha256: "1e20a88d5c7ae8400e009f38ddbe8b001800a6dffa37832481a86a219bc904c7" url: "https://pub.dev" source: hosted - version: "0.5.13" + version: "0.5.15" stack_trace: dependency: transitive description: @@ -631,10 +631,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.0" term_glyph: dependency: transitive description: @@ -647,42 +647,42 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" typed_data: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" universal_io: dependency: transitive description: name: universal_io - sha256: "79f78ddad839ee3aae3ec7c01eb4575faf0d5c860f8e5223bc9f9c17f7f03cef" + sha256: "06866290206d196064fd61df4c7aea1ffe9a4e7c4ccaa8fcded42dd41948005d" url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.2.0" url_launcher: dependency: "direct main" description: name: url_launcher - sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 url: "https://pub.dev" source: hosted - version: "6.1.10" + version: "6.1.11" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "22f8db4a72be26e9e3a4aa3f194b1f7afbc76d20ec141f84be1d787db2155cbd" + sha256: "1a5848f598acc5b7d8f7c18b8cb834ab667e59a13edc3c93e9d09cf38cc6bc87" url: "https://pub.dev" source: hosted - version: "6.0.31" + version: "6.0.34" url_launcher_ios: dependency: transitive description: @@ -751,10 +751,10 @@ packages: dependency: transitive description: name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4 url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.4" window_size: dependency: "direct main" description: @@ -768,18 +768,18 @@ packages: dependency: transitive description: name: xml - sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.0" yaml: dependency: transitive description: name: yaml - sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0-417 <4.0.0" flutter: ">=3.4.0-17.0.pre" From f6254fe8a3918f841c1c2fedd0f2628f1277a0fb Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 18 May 2023 02:14:01 +0200 Subject: [PATCH 118/676] Updated some packages --- macos/Podfile.lock | 32 ++++++++++++++++---------------- pubspec.lock | 8 ++++---- pubspec.yaml | 8 ++++---- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index d38e653..0075110 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -9,28 +9,28 @@ PODS: - FMDB/standard (2.7.5) - package_info_plus (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.5.0): - - SentryPrivate (= 8.5.0) + - Sentry/HybridSDK (8.7.1): + - SentryPrivate (= 8.7.1) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.5.0) - - SentryPrivate (8.5.0) + - Sentry/HybridSDK (= 8.7.1) + - SentryPrivate (8.7.1) - sqflite (0.0.2): - FlutterMacOS - FMDB (>= 2.7.5) - - sqlite3 (3.41.0): - - sqlite3/common (= 3.41.0) - - sqlite3/common (3.41.0) - - sqlite3/fts5 (3.41.0): + - sqlite3 (3.41.2): + - sqlite3/common (= 3.41.2) + - sqlite3/common (3.41.2) + - sqlite3/fts5 (3.41.2): - sqlite3/common - - sqlite3/perf-threadsafe (3.41.0): + - sqlite3/perf-threadsafe (3.41.2): - sqlite3/common - - sqlite3/rtree (3.41.0): + - sqlite3/rtree (3.41.2): - sqlite3/common - sqlite3_flutter_libs (0.0.1): - FlutterMacOS - - sqlite3 (~> 3.41.0) + - sqlite3 (~> 3.41.2) - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree @@ -83,12 +83,12 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - Sentry: 3be3f42e40e5a552935552e115744d5810a216d9 - sentry_flutter: c75806c304706163b2c129394c4621a786ad84e9 - SentryPrivate: 8c9463280e282527f938d1a5d1d60f8e10ff279b + Sentry: 11776f6a25a128808d793d0d41bb7ad873b5ae4f + sentry_flutter: 886dbeb2674ba1232f540c54311a774bb50fda42 + SentryPrivate: b3c448eacdabe9eab7679a2e0af609c608f91572 sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea - sqlite3: d31b2b69d59bd1b4ab30e5c92eb18fd8e82fa392 - sqlite3_flutter_libs: f20746e4a0245afbee4f20d9afc0072ebff7cc26 + sqlite3: fd89671d969f3e73efe503ce203e28b016b58f68 + sqlite3_flutter_libs: 00a50503d69f7ab0fe85a5ff25b33082f4df4ce9 url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451 window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 diff --git a/pubspec.lock b/pubspec.lock index 3c02255..3bb15f5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -229,10 +229,10 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: "749b3342ea3e95cbf61a0fec31a62606e837377b8b6d0caa7367a7ef80f38b7d" + sha256: "48a1b69be9544e2b03d9a8e843affd89e43f3194c9248776222efcb4206bb1ec" url: "https://pub.dev" source: hosted - version: "0.55.2" + version: "0.62.0" flutter: dependency: "direct main" description: flutter @@ -242,10 +242,10 @@ packages: dependency: "direct main" description: name: flutter_displaymode - sha256: fdeaceb35d84ed000625ae0666bbec5b015407d1f90135cdd1bbfdb4ca73de1a + sha256: "42c5e9abd13d28ed74f701b60529d7f8416947e58256e6659c5550db719c57ef" url: "https://pub.dev" source: hosted - version: "0.4.1" + version: "0.6.0" flutter_dotenv: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 62642df..9982de9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -42,13 +42,13 @@ dependencies: provider: ^6.0.3 sqflite: ^2.2.5 package_info_plus: ^3.1.2 - flutter_displaymode: ^0.4.0 - dynamic_color: ^1.5.4 + flutter_displaymode: ^0.6.0 + dynamic_color: ^1.6.5 animations: ^2.0.5 device_info_plus: ^4.1.2 uuid: ^3.0.6 expandable: ^5.0.1 - fl_chart: ^0.55.2 + fl_chart: ^0.62.0 flutter_web_browser: ^0.17.1 flutter_svg: ^1.1.5 percent_indicator: ^4.2.2 @@ -70,7 +70,7 @@ dependencies: url_launcher: ^6.1.10 contextmenu: ^3.0.0 async: ^2.10.0 - sentry_flutter: ^7.5.1 + sentry_flutter: ^7.5.2 flutter_dotenv: ^5.0.2 dev_dependencies: From 1d7c269aa01164b559bee925318888772346998e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 18 May 2023 02:14:19 +0200 Subject: [PATCH 119/676] New appbar on homescreen --- lib/functions/conversions.dart | 2 - lib/screens/home/appbar.dart | 165 ++++++++++++++++----------------- lib/screens/home/home.dart | 66 ++++++++----- 3 files changed, 120 insertions(+), 113 deletions(-) diff --git a/lib/functions/conversions.dart b/lib/functions/conversions.dart index 37fcf4b..4eeceac 100644 --- a/lib/functions/conversions.dart +++ b/lib/functions/conversions.dart @@ -1,5 +1,3 @@ -import 'package:intl/intl.dart'; - bool? convertFromIntToBool(int value) { if (value == 1) { return true; diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 1ed4ed1..ea519f9 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -9,11 +9,16 @@ import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class HomeAppBar extends StatelessWidget implements PreferredSizeWidget { - const HomeAppBar({Key? key}) : super(key: key); +class HomeAppBar extends StatelessWidget { + final bool innerBoxScrolled; + + const HomeAppBar({ + Key? key, + required this.innerBoxScrolled + }) : super(key: key); @override - PreferredSizeWidget build(BuildContext context) { + Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -27,93 +32,81 @@ class HomeAppBar extends StatelessWidget implements PreferredSizeWidget { })); } - return AppBar( - toolbarHeight: 70, - title: Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Row( - children: [ - Icon( - serversProvider.selectedServer != null && serversProvider.serverStatus.data != null - ? serversProvider.serverStatus.data!.generalEnabled == true - ? Icons.gpp_good_rounded - : Icons.gpp_bad_rounded - : Icons.shield, - size: 30, - color: serversProvider.selectedServer != null && serversProvider.serverStatus.data != null - ? serversProvider.serverStatus.data!.generalEnabled == true - ? appConfigProvider.useThemeColorForStatus - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - : Colors.red - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - ), - const SizedBox(width: 20), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (serversProvider.selectedServer != null) ...[ - Text( - server!.name, - style: const TextStyle( - fontSize: 20 - ), - ), - const SizedBox(height: 5), - Text( - "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).listTileTheme.textColor - ), - ) - ], - if (serversProvider.selectedServer == null) Text( - AppLocalizations.of(context)!.noServerSelected, - style: const TextStyle( - fontSize: 20 - ), - ), - ], - ), - ], + return SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxScrolled, + leading: Icon( + serversProvider.selectedServer != null && serversProvider.serverStatus.data != null + ? serversProvider.serverStatus.data!.generalEnabled == true + ? Icons.gpp_good_rounded + : Icons.gpp_bad_rounded + : Icons.shield, + size: 30, + color: serversProvider.selectedServer != null && serversProvider.serverStatus.data != null + ? serversProvider.serverStatus.data!.generalEnabled == true + ? appConfigProvider.useThemeColorForStatus + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + : Colors.red + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + ), + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (serversProvider.selectedServer != null) ...[ + Text( + server!.name, + style: const TextStyle( + fontSize: 20 + ), ), - PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - onTap: navigateServers, - child: Row( - children: [ - const Icon(Icons.storage_rounded), - const SizedBox(width: 10), - Text(AppLocalizations.of(context)!.servers) - ], - ), - ), - if (serversProvider.selectedServer != null && serversProvider.serverStatus.loadStatus == 1) PopupMenuItem( - onTap: () => openUrl("${server!.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}"), - child: Row( - children: [ - const Icon(Icons.web_rounded), - const SizedBox(width: 10), - Text(AppLocalizations.of(context)!.webAdminPanel) - ], - ), - ) - ] + const SizedBox(height: 5), + Text( + "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).listTileTheme.textColor + ), ) ], - ), + if (serversProvider.selectedServer == null) Text( + AppLocalizations.of(context)!.noServerSelected, + style: const TextStyle( + fontSize: 20 + ), + ), + ], ), + actions: [ + PopupMenuButton( + itemBuilder: (context) => [ + PopupMenuItem( + onTap: navigateServers, + child: Row( + children: [ + const Icon(Icons.storage_rounded), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.servers) + ], + ), + ), + if (serversProvider.selectedServer != null && serversProvider.serverStatus.loadStatus == 1) PopupMenuItem( + onTap: () => openUrl("${server!.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}"), + child: Row( + children: [ + const Icon(Icons.web_rounded), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.webAdminPanel) + ], + ), + ) + ] + ) + ], ); } - - @override - Size get preferredSize => const Size.fromHeight(70); } \ No newline at end of file diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 9cd9411..7e4ddb7 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -83,7 +83,6 @@ class _HomeState extends State { case 1: return ListView( - controller: scrollController, children: [ ServerStatus(serverStatus: serversProvider.serverStatus.data!), Padding( @@ -261,31 +260,48 @@ class _HomeState extends State { } return Scaffold( - appBar: const HomeAppBar(), - body: RefreshIndicator( - color: Theme.of(context).colorScheme.primary, - onRefresh: () async { - final result = await getServerStatus(serversProvider.selectedServer!); - if (result['result'] == 'success') { - serversProvider.setServerStatusData(result['data']); - } - else { - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.serverStatusNotRefreshed, - color: Colors.red - ); - } - }, - child: status() + body: Stack( + children: [ + NestedScrollView( + controller: scrollController, + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: HomeAppBar(innerBoxScrolled: innerBoxIsScrolled,) + ) + ], + body: RefreshIndicator( + color: Theme.of(context).colorScheme.primary, + onRefresh: () async { + final result = await getServerStatus(serversProvider.selectedServer!); + if (result['result'] == 'success') { + serversProvider.setServerStatusData(result['data']); + } + else { + appConfigProvider.addLog(result['log']); + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.serverStatusNotRefreshed, + color: Colors.red + ); + } + }, + child: status() + ), + ), + AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: isVisible == true ? + appConfigProvider.showingSnackbar + ? 70 + : 20 + : -70, + right: 20, + child: const HomeFab() + ), + ], ), - floatingActionButton: appConfigProvider.showingSnackbar - ? null - : isVisible - ? const HomeFab() - : null - ); } } \ No newline at end of file From baed03e0c3345c8ce0d1672bc44973d3ed309e71 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 18 May 2023 02:16:18 +0200 Subject: [PATCH 120/676] Removed unused imports --- lib/screens/clients/added_client_tile.dart | 1 - lib/screens/clients/clients_list.dart | 2 -- lib/screens/top_items/top_items.dart | 1 - lib/screens/top_items/top_items_modal.dart | 2 -- lib/services/http_requests.dart | 1 - 5 files changed, 7 deletions(-) diff --git a/lib/screens/clients/added_client_tile.dart b/lib/screens/clients/added_client_tile.dart index 5827c85..ff6d566 100644 --- a/lib/screens/clients/added_client_tile.dart +++ b/lib/screens/clients/added_client_tile.dart @@ -8,7 +8,6 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class AddedClientTile extends StatelessWidget { diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index 9d2f11b..de284c5 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index d8608a9..643e8be 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -14,7 +14,6 @@ import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; -import 'package:adguard_home_manager/functions/block_unblock_domain.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; diff --git a/lib/screens/top_items/top_items_modal.dart b/lib/screens/top_items/top_items_modal.dart index d07c5f8..3c98679 100644 --- a/lib/screens/top_items/top_items_modal.dart +++ b/lib/screens/top_items/top_items_modal.dart @@ -12,9 +12,7 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; -import 'package:adguard_home_manager/functions/block_unblock_domain.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 4526f3e..5507147 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -14,7 +14,6 @@ import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; -import 'package:adguard_home_manager/models/safe_search.dart'; import 'package:adguard_home_manager/models/server_info.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/clients.dart'; From 8dffb83fd085ba6d259cbd82c6762d345af79b20 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 18 May 2023 11:13:03 +0200 Subject: [PATCH 121/676] Updated home appbar --- lib/screens/home/appbar.dart | 1 + lib/screens/home/home.dart | 425 ++++++++++++++-------------- lib/screens/home/server_status.dart | 7 +- 3 files changed, 223 insertions(+), 210 deletions(-) diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index ea519f9..58284d5 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -55,6 +55,7 @@ class HomeAppBar extends StatelessWidget { : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) ), title: Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ if (serversProvider.selectedServer != null) ...[ diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 7e4ddb7..ec1bc3b 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -2,7 +2,6 @@ import 'dart:io'; -import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; @@ -17,6 +16,7 @@ import 'package:adguard_home_manager/screens/home/chart.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class Home extends StatefulWidget { @@ -58,205 +58,199 @@ class _HomeState extends State { final width = MediaQuery.of(context).size.width; - Widget status() { - switch (serversProvider.serverStatus.loadStatus) { - case 0: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingStatus, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], + Widget loading() { + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + } + + Widget loadError() { + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, ), - ); - - case 1: - return ListView( - children: [ - ServerStatus(serverStatus: serversProvider.serverStatus.data!), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), - ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.errorLoadServerStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - const SizedBox(height: 20), + ) + ], + ), + ); + } - Wrap( - children: [ - FractionallySizedBox( - widthFactor: width > 700 ? 0.5 : 1, - child: HomeChart( - data: serversProvider.serverStatus.data!.stats.dnsQueries, - label: AppLocalizations.of(context)!.dnsQueries, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), - secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", - color: Colors.blue, - ), - ), - FractionallySizedBox( - widthFactor: width > 700 ? 0.5 : 1, - child: HomeChart( - data: serversProvider.serverStatus.data!.stats.blockedFiltering, - label: AppLocalizations.of(context)!.blockedFilters, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", - color: Colors.red, - ), - ), - FractionallySizedBox( - widthFactor: width > 700 ? 0.5 : 1, - child: HomeChart( - data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing, - label: AppLocalizations.of(context)!.malwarePhisingBlocked, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", - color: Colors.green, - ), - ), - FractionallySizedBox( - widthFactor: width > 700 ? 0.5 : 1, - child: HomeChart( - data: serversProvider.serverStatus.data!.stats.replacedParental, - label: AppLocalizations.of(context)!.blockedAdultWebsites, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", - color: Colors.orange, - ), - ), - - ], + List listItems() { + return [ + ServerStatus(serverStatus: serversProvider.serverStatus.data!), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + ), + const SizedBox(height: 20), + + Wrap( + children: [ + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: serversProvider.serverStatus.data!.stats.dnsQueries, + label: AppLocalizations.of(context)!.dnsQueries, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + color: Colors.blue, ), - - if (width <= 700) ...[ - TopItems( - label: AppLocalizations.of(context)!.topQueriedDomains, - data: serversProvider.serverStatus.data!.stats.topQueriedDomains, - type: 'topQueriedDomains', + ), + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: serversProvider.serverStatus.data!.stats.blockedFiltering, + label: AppLocalizations.of(context)!.blockedFilters, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + color: Colors.red, + ), + ), + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing, + label: AppLocalizations.of(context)!.malwarePhisingBlocked, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + color: Colors.green, + ), + ), + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: serversProvider.serverStatus.data!.stats.replacedParental, + label: AppLocalizations.of(context)!.blockedAdultWebsites, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + color: Colors.orange, + ), + ), + + ], + ), + + if (width <= 700) ...[ + TopItems( + label: AppLocalizations.of(context)!.topQueriedDomains, + data: serversProvider.serverStatus.data!.stats.topQueriedDomains, + type: 'topQueriedDomains', + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + ), + + const SizedBox(height: 20), + + TopItems( + label: AppLocalizations.of(context)!.topBlockedDomains, + data: serversProvider.serverStatus.data!.stats.topBlockedDomains, + type: 'topBlockedDomains', + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + ), + const SizedBox(height: 20), + + TopItems( + label: AppLocalizations.of(context)!.topClients, + data: serversProvider.serverStatus.data!.stats.topClients, + type: 'topClients', + clients: true, + ), + ], + if (width > 700) Column( + children: [ + const SizedBox(height: 16), + Wrap( + alignment: WrapAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: TopItems( + label: AppLocalizations.of(context)!.topQueriedDomains, + data: serversProvider.serverStatus.data!.stats.topQueriedDomains, + type: 'topQueriedDomains', + ), + ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + padding: const EdgeInsets.only(bottom: 16), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: TopItems( + label: AppLocalizations.of(context)!.topBlockedDomains, + data: serversProvider.serverStatus.data!.stats.topBlockedDomains, + type: 'topBlockedDomains', + ), ), ), - - const SizedBox(height: 20), - - TopItems( - label: AppLocalizations.of(context)!.topBlockedDomains, - data: serversProvider.serverStatus.data!.stats.topBlockedDomains, - type: 'topBlockedDomains', - ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + padding: const EdgeInsets.only(bottom: 16), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: TopItems( + label: AppLocalizations.of(context)!.topClients, + data: serversProvider.serverStatus.data!.stats.topClients, + type: 'topClients', + ), ), ), - const SizedBox(height: 20), - - TopItems( - label: AppLocalizations.of(context)!.topClients, - data: serversProvider.serverStatus.data!.stats.topClients, - type: 'topClients', - clients: true, - ), - ], - if (width > 700) Column( - children: [ - const SizedBox(height: 16), - Wrap( - alignment: WrapAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: TopItems( - label: AppLocalizations.of(context)!.topQueriedDomains, - data: serversProvider.serverStatus.data!.stats.topQueriedDomains, - type: 'topQueriedDomains', - ), - ), - ), - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: TopItems( - label: AppLocalizations.of(context)!.topBlockedDomains, - data: serversProvider.serverStatus.data!.stats.topBlockedDomains, - type: 'topBlockedDomains', - ), - ), - ), - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: TopItems( - label: AppLocalizations.of(context)!.topClients, - data: serversProvider.serverStatus.data!.stats.topClients, - type: 'topClients', - ), - ), - ), - ], - ), - ], - ) - ], - ); - - case 2: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.errorLoadServerStatus, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) ], ), - ); - - default: - return const SizedBox(); - } + ], + ) + ]; } return Scaffold( @@ -270,24 +264,45 @@ class _HomeState extends State { sliver: HomeAppBar(innerBoxScrolled: innerBoxIsScrolled,) ) ], - body: RefreshIndicator( - color: Theme.of(context).colorScheme.primary, - onRefresh: () async { - final result = await getServerStatus(serversProvider.selectedServer!); - if (result['result'] == 'success') { - serversProvider.setServerStatusData(result['data']); - } - else { - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.serverStatusNotRefreshed, - color: Colors.red - ); - } - }, - child: status() - ), + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => RefreshIndicator( + color: Theme.of(context).colorScheme.primary, + onRefresh: () async { + final result = await getServerStatus(serversProvider.selectedServer!); + if (result['result'] == 'success') { + serversProvider.setServerStatusData(result['data']); + } + else { + appConfigProvider.addLog(result['log']); + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.serverStatusNotRefreshed, + color: Colors.red + ); + } + }, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (serversProvider.serverStatus.loadStatus == 0) SliverFillRemaining( + child: loading(), + ), + if (serversProvider.serverStatus.loadStatus == 1) SliverList.list( + children: listItems() + ), + if (serversProvider.serverStatus.loadStatus == 2) SliverFillRemaining( + child: loadError(), + ), + ], + ) + ), + ) + ) ), AnimatedPositioned( duration: const Duration(milliseconds: 100), diff --git a/lib/screens/home/server_status.dart b/lib/screens/home/server_status.dart index 1df9767..3026c90 100644 --- a/lib/screens/home/server_status.dart +++ b/lib/screens/home/server_status.dart @@ -18,9 +18,7 @@ class ServerStatus extends StatelessWidget { final width = MediaQuery.of(context).size.width; return Container( - padding: width > 700 - ? const EdgeInsets.only(left: 20, right: 20, bottom: 20) - : const EdgeInsets.all(20), + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 10), child: Column( children: [ Text( @@ -31,9 +29,8 @@ class ServerStatus extends StatelessWidget { color: Theme.of(context).colorScheme.onSurface ), ), - const SizedBox(height: 20), SizedBox( - height: width > 700 ? 70 : 140, + height: width > 700 ? 90 : 170, child: GridView( physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( From ecd9b4fc89bd2e0c17a532f1f2a303ade8ff0450 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 18 May 2023 13:54:50 +0200 Subject: [PATCH 122/676] Updated more appbars --- lib/screens/logs/log_details_screen.dart | 41 ++- lib/screens/settings/advanced_setings.dart | 115 +++++--- lib/screens/settings/general_settings.dart | 127 +++++---- lib/screens/settings/settings.dart | 316 +++++++++++---------- 4 files changed, 333 insertions(+), 266 deletions(-) diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 8662b8d..a6b8f45 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -294,24 +294,35 @@ class LogDetailsScreen extends StatelessWidget { } else { return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.logDetails), - actions: [ - if (serversProvider.filteringStatus != null) IconButton( - onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), - icon: Icon( - getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? Icons.check_circle_rounded - : Icons.block + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + title: Text(AppLocalizations.of(context)!.logDetails), + actions: [ + if (serversProvider.filteringStatus != null) IconButton( + onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), + icon: Icon( + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? Icons.check_circle_rounded + : Icons.block + ), + tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? AppLocalizations.of(context)!.unblockDomain + : AppLocalizations.of(context)!.blockDomain, + ), + const SizedBox(width: 10) + ], ), - tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? AppLocalizations.of(context)!.unblockDomain - : AppLocalizations.of(context)!.blockDomain, - ), - const SizedBox(width: 10) + ) ], + body: content(), ), - body: content() ); } } diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 0012259..ca57de4 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -42,53 +42,76 @@ class AdvancedSettings extends StatelessWidget { } return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.advancedSettings), - centerTitle: false, - ), - body: ListView( - children: [ - CustomListTile( - icon: Icons.lock, - title: AppLocalizations.of(context)!.dontCheckCertificate, - subtitle: AppLocalizations.of(context)!.dontCheckCertificateDescription, - trailing: Switch( - value: appConfigProvider.overrideSslCheck, - onChanged: updateSslCheck, - ), - onTap: () => updateSslCheck(!appConfigProvider.overrideSslCheck), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 20, - right: 10 + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + title: Text(AppLocalizations.of(context)!.generalSettings), ) - ), - CustomListTile( - icon: Icons.list_rounded, - title: AppLocalizations.of(context)!.logs, - subtitle: AppLocalizations.of(context)!.checkAppLogs, - onTap: () => { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push(const AppLogs()) - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const AppLogs() - ) + ) + ], + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + CustomListTile( + icon: Icons.lock, + title: AppLocalizations.of(context)!.dontCheckCertificate, + subtitle: AppLocalizations.of(context)!.dontCheckCertificateDescription, + trailing: Switch( + value: appConfigProvider.overrideSslCheck, + onChanged: updateSslCheck, + ), + onTap: () => updateSslCheck(!appConfigProvider.overrideSslCheck), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 20, + right: 10 + ) + ), + CustomListTile( + icon: Icons.list_rounded, + title: AppLocalizations.of(context)!.logs, + subtitle: AppLocalizations.of(context)!.checkAppLogs, + onTap: () => { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push(const AppLogs()) + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const AppLogs() + ) + ) + } + }, + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 20, + right: 10 + ) + ), + ], ) - } - }, - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 20, - right: 10 - ) - ), - ], - ), - ); + ], + ), + ) + ) + ) + ); } } \ No newline at end of file diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index 18957d7..071ec84 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -126,60 +126,83 @@ class _GeneralSettingsState extends State { } return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.generalSettings), - centerTitle: false, - ), - body: ListView( - children: [ - CustomListTile( - icon: Icons.exposure_zero_rounded, - title: AppLocalizations.of(context)!.hideZeroValues, - subtitle: AppLocalizations.of(context)!.hideZeroValuesDescription, - trailing: Switch( - value: appConfigProvider.hideZeroValues, - onChanged: updateHideZeroValues, - ), - onTap: () => updateHideZeroValues(!appConfigProvider.hideZeroValues), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + title: Text(AppLocalizations.of(context)!.generalSettings), ) - ), - CustomListTile( - icon: Icons.more, - title: AppLocalizations.of(context)!.nameTimeLogs, - subtitle: AppLocalizations.of(context)!.nameTimeLogsDescription, - trailing: Switch( - value: appConfigProvider.showNameTimeLogs, - onChanged: updateShowNameTimeLogs, - ), - onTap: () => updateShowNameTimeLogs(!appConfigProvider.showNameTimeLogs), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - if ( - !(Platform.isAndroid || Platform.isIOS) || - (Platform.isAndroid && ( - appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE) || - appConfigProvider.installationSource == Source.UNKNOWN - ) - ) CustomListTile( - icon: Icons.system_update_rounded, - title: AppLocalizations.of(context)!.appUpdates, - subtitle: appConfigProvider.appUpdatesAvailable != null - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.usingLatestVersion, - trailing: generateAppUpdateStatus() ) - ], - ), + ], + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + CustomListTile( + icon: Icons.exposure_zero_rounded, + title: AppLocalizations.of(context)!.hideZeroValues, + subtitle: AppLocalizations.of(context)!.hideZeroValuesDescription, + trailing: Switch( + value: appConfigProvider.hideZeroValues, + onChanged: updateHideZeroValues, + ), + onTap: () => updateHideZeroValues(!appConfigProvider.hideZeroValues), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), + CustomListTile( + icon: Icons.more, + title: AppLocalizations.of(context)!.nameTimeLogs, + subtitle: AppLocalizations.of(context)!.nameTimeLogsDescription, + trailing: Switch( + value: appConfigProvider.showNameTimeLogs, + onChanged: updateShowNameTimeLogs, + ), + onTap: () => updateShowNameTimeLogs(!appConfigProvider.showNameTimeLogs), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), + if ( + !(Platform.isAndroid || Platform.isIOS) || + (Platform.isAndroid && ( + appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE) || + appConfigProvider.installationSource == Source.UNKNOWN + ) + ) CustomListTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.appUpdates, + subtitle: appConfigProvider.appUpdatesAvailable != null + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.usingLatestVersion, + trailing: generateAppUpdateStatus() + ) + ], + ) + ], + ), + ) + ) + ) ); } } \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 4ae2cb5..8565e2f 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -114,160 +114,170 @@ class SettingsWidget extends StatelessWidget { } return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.settings), - centerTitle: false, - ), - body: ListView( - children: [ - if (serversProvider.selectedServer != null && serversProvider.serverStatus.data != null) ...[ - SectionLabel(label: AppLocalizations.of(context)!.serverSettings), - if (serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true) settingsTile( - icon: Icons.search_rounded, - title: AppLocalizations.of(context)!.safeSearch, - subtitle: AppLocalizations.of(context)!.safeSearchSettings, - thisItem: 0, - screenToNavigate: const SafeSearchSettingsScreen(), - ), - settingsTile( - icon: Icons.lock_rounded, - title: AppLocalizations.of(context)!.accessSettings, - subtitle: AppLocalizations.of(context)!.accessSettingsDescription, - thisItem: 1, - screenToNavigate: const AccessSettings(), - ), - settingsTile( - icon: Icons.install_desktop_rounded, - title: AppLocalizations.of(context)!.dhcpSettings, - subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, - thisItem: 2, - screenToNavigate: const Dhcp(), - ), - settingsTile( - icon: Icons.dns_rounded, - title: AppLocalizations.of(context)!.dnsSettings, - subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, - thisItem: 3, - screenToNavigate: const DnsSettings(), - ), - settingsTile( - icon: Icons.security_rounded, - title: AppLocalizations.of(context)!.encryptionSettings, - subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, - thisItem: 4, - screenToNavigate: const EncryptionSettings(), - ), - settingsTile( - icon: Icons.route_rounded, - title: AppLocalizations.of(context)!.dnsRewrites, - subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, - thisItem: 5, - screenToNavigate: const DnsRewrites(), - ), - if (serversProvider.updateAvailable.data != null) settingsTile( - icon: Icons.system_update_rounded, - title: AppLocalizations.of(context)!.updates, - subtitle: AppLocalizations.of(context)!.updatesDescription, - trailing: serversProvider.updateAvailable.data != null && - serversProvider.updateAvailable.data!.updateAvailable != null && - serversProvider.updateAvailable.data!.updateAvailable == true - ? Container( - width: 10, - height: 10, - margin: const EdgeInsets.only(right: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.red - ), - ) - : null, - thisItem: 6, - screenToNavigate: const UpdateScreen(), - ), - settingsTile( - icon: Icons.info_rounded, - title: AppLocalizations.of(context)!.serverInformation, - subtitle: AppLocalizations.of(context)!.serverInformationDescription, - thisItem: 7, - screenToNavigate: const ServerInformation(), - ), - ], - SectionLabel(label: AppLocalizations.of(context)!.appSettings), - settingsTile( - icon: Icons.palette_rounded, - title: AppLocalizations.of(context)!.customization, - subtitle: AppLocalizations.of(context)!.customizationDescription, - thisItem: 8, - screenToNavigate: const Customization(), - ), - settingsTile( - icon: Icons.storage_rounded, - title: AppLocalizations.of(context)!.servers, - subtitle: serversProvider.selectedServer != null - ? serversProvider.serverStatus.data != null - ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" - : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" - : AppLocalizations.of(context)!.noServerSelected, - thisItem: 9, - screenToNavigate: const Servers(), - ), - settingsTile( - icon: Icons.settings, - title: AppLocalizations.of(context)!.generalSettings, - subtitle: AppLocalizations.of(context)!.generalSettingsDescription, - thisItem: 10, - screenToNavigate: const GeneralSettings(), - ), - settingsTile( - icon: Icons.build_outlined, - title: AppLocalizations.of(context)!.advancedSettings, - subtitle: AppLocalizations.of(context)!.advancedSetupDescription, - thisItem: 11, - screenToNavigate: const AdvancedSettings(), - ), - SectionLabel(label: AppLocalizations.of(context)!.aboutApp), - CustomListTile( - title: AppLocalizations.of(context)!.appVersion, - subtitle: appConfigProvider.getAppInfo!.version, - ), - CustomListTile( - title: AppLocalizations.of(context)!.createdBy, - subtitle: Strings.createdBy, - ), - Padding( - padding: const EdgeInsets.all(15), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - if (Platform.isAndroid) IconButton( - onPressed: () => openUrl(Urls.playStore), - icon: SvgPicture.asset( - 'assets/resources/google-play.svg', - color: Theme.of(context).colorScheme.onSurfaceVariant, - width: 30, - height: 30, - ), - tooltip: AppLocalizations.of(context)!.visitGooglePlay, - ), - IconButton( - onPressed: () => openUrl(Urls.gitHub), - icon: SvgPicture.asset( - 'assets/resources/github.svg', - color: Theme.of(context).colorScheme.onSurfaceVariant, - width: 30, - height: 30, - ), - tooltip: AppLocalizations.of(context)!.gitHub, - ), - ], - ), + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + title: Text(AppLocalizations.of(context)!.settings), + ) ) - ], - ), + ], + body: ListView( + children: [ + if (serversProvider.selectedServer != null && serversProvider.serverStatus.data != null) ...[ + SectionLabel(label: AppLocalizations.of(context)!.serverSettings), + if (serverVersionIsAhead( + currentVersion: serversProvider.serverStatus.data!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true) settingsTile( + icon: Icons.search_rounded, + title: AppLocalizations.of(context)!.safeSearch, + subtitle: AppLocalizations.of(context)!.safeSearchSettings, + thisItem: 0, + screenToNavigate: const SafeSearchSettingsScreen(), + ), + settingsTile( + icon: Icons.lock_rounded, + title: AppLocalizations.of(context)!.accessSettings, + subtitle: AppLocalizations.of(context)!.accessSettingsDescription, + thisItem: 1, + screenToNavigate: const AccessSettings(), + ), + settingsTile( + icon: Icons.install_desktop_rounded, + title: AppLocalizations.of(context)!.dhcpSettings, + subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, + thisItem: 2, + screenToNavigate: const Dhcp(), + ), + settingsTile( + icon: Icons.dns_rounded, + title: AppLocalizations.of(context)!.dnsSettings, + subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, + thisItem: 3, + screenToNavigate: const DnsSettings(), + ), + settingsTile( + icon: Icons.security_rounded, + title: AppLocalizations.of(context)!.encryptionSettings, + subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, + thisItem: 4, + screenToNavigate: const EncryptionSettings(), + ), + settingsTile( + icon: Icons.route_rounded, + title: AppLocalizations.of(context)!.dnsRewrites, + subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, + thisItem: 5, + screenToNavigate: const DnsRewrites(), + ), + if (serversProvider.updateAvailable.data != null) settingsTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.updates, + subtitle: AppLocalizations.of(context)!.updatesDescription, + trailing: serversProvider.updateAvailable.data != null && + serversProvider.updateAvailable.data!.updateAvailable != null && + serversProvider.updateAvailable.data!.updateAvailable == true + ? Container( + width: 10, + height: 10, + margin: const EdgeInsets.only(right: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.red + ), + ) + : null, + thisItem: 6, + screenToNavigate: const UpdateScreen(), + ), + settingsTile( + icon: Icons.info_rounded, + title: AppLocalizations.of(context)!.serverInformation, + subtitle: AppLocalizations.of(context)!.serverInformationDescription, + thisItem: 7, + screenToNavigate: const ServerInformation(), + ), + ], + SectionLabel(label: AppLocalizations.of(context)!.appSettings), + settingsTile( + icon: Icons.palette_rounded, + title: AppLocalizations.of(context)!.customization, + subtitle: AppLocalizations.of(context)!.customizationDescription, + thisItem: 8, + screenToNavigate: const Customization(), + ), + settingsTile( + icon: Icons.storage_rounded, + title: AppLocalizations.of(context)!.servers, + subtitle: serversProvider.selectedServer != null + ? serversProvider.serverStatus.data != null + ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" + : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" + : AppLocalizations.of(context)!.noServerSelected, + thisItem: 9, + screenToNavigate: const Servers(), + ), + settingsTile( + icon: Icons.settings, + title: AppLocalizations.of(context)!.generalSettings, + subtitle: AppLocalizations.of(context)!.generalSettingsDescription, + thisItem: 10, + screenToNavigate: const GeneralSettings(), + ), + settingsTile( + icon: Icons.build_outlined, + title: AppLocalizations.of(context)!.advancedSettings, + subtitle: AppLocalizations.of(context)!.advancedSetupDescription, + thisItem: 11, + screenToNavigate: const AdvancedSettings(), + ), + SectionLabel(label: AppLocalizations.of(context)!.aboutApp), + CustomListTile( + title: AppLocalizations.of(context)!.appVersion, + subtitle: appConfigProvider.getAppInfo!.version, + ), + CustomListTile( + title: AppLocalizations.of(context)!.createdBy, + subtitle: Strings.createdBy, + ), + Padding( + padding: const EdgeInsets.all(15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if (Platform.isAndroid) IconButton( + onPressed: () => openUrl(Urls.playStore), + icon: SvgPicture.asset( + 'assets/resources/google-play.svg', + color: Theme.of(context).colorScheme.onSurfaceVariant, + width: 30, + height: 30, + ), + tooltip: AppLocalizations.of(context)!.visitGooglePlay, + ), + IconButton( + onPressed: () => openUrl(Urls.gitHub), + icon: SvgPicture.asset( + 'assets/resources/github.svg', + color: Theme.of(context).colorScheme.onSurfaceVariant, + width: 30, + height: 30, + ), + tooltip: AppLocalizations.of(context)!.gitHub, + ), + ], + ), + ) + ], + ), + ) ); } } \ No newline at end of file From 8d7beae32864890884ba6f54f73cbe13b1408c38 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 20 May 2023 01:16:33 +0200 Subject: [PATCH 123/676] Fixed some issues --- lib/screens/clients/logs_list_client.dart | 2 +- lib/screens/home/management_modal.dart | 10 +++---- .../settings/encryption/encryption.dart | 30 +++++-------------- pubspec.yaml | 2 +- 4 files changed, 14 insertions(+), 30 deletions(-) diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/logs_list_client.dart index dd731c4..6fe4782 100644 --- a/lib/screens/clients/logs_list_client.dart +++ b/lib/screens/clients/logs_list_client.dart @@ -73,7 +73,7 @@ class _LogsListClientState extends State { final result = await cancelableRequest?.value; if (result != null) { - if (loadingMore != null && loadingMore == true) { + if (loadingMore != null && loadingMore == true && mounted) { setState(() => isLoadingMore = false); } diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 46f94e5..9781206 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -8,6 +8,7 @@ import 'package:provider/provider.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -137,11 +138,10 @@ class _ManagementModalState extends State with SingleTickerProv if (result != false) { appConfigProvider.addLog(result); } - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.invalidUsernamePassword), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.invalidUsernamePassword, + color: Colors.red ); } } diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 6af29ab..b99efd7 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -187,25 +187,7 @@ class _EncryptionSettingsWidgetState extends State { tlsPortController.text != '' && tlsPortError == null && dnsOverQuicPortController.text != '' && - dnsOverQuicPortError == null && - (( - certificateOption == 0 && - certificatePathController.text != '' && - certificatePathError == null - ) || ( - certificateOption == 1 && - certificateContentController.text != '' && - certificateContentError == null - )) && - (( - privateKeyOption == 0 && - privateKeyPathController.text != '' && - privateKeyPathError == null - ) || ( - privateKeyOption == 1 && - pastePrivateKeyController.text != '' && - pastePrivateKeyError == null - )) + dnsOverQuicPortError == null ) { setState(() => localValidationValid = true); return true; @@ -246,9 +228,9 @@ class _EncryptionSettingsWidgetState extends State { "enabled": enabled, "server_name": domainNameController.text, "force_https": redirectHttps, - "port_https": int.parse(httpsPortController.text), - "port_dns_over_tls": int.parse(tlsPortController.text), - "port_dns_over_quic": int.parse(dnsOverQuicPortController.text), + "port_https": int.tryParse(httpsPortController.text), + "port_dns_over_tls": int.tryParse(tlsPortController.text), + "port_dns_over_quic": int.tryParse(dnsOverQuicPortController.text), "certificate_chain": encodeBase64(certificateContentController.text), "private_key": encodeBase64(pastePrivateKeyController.text), "private_key_saved": usePreviouslySavedKey, @@ -672,7 +654,9 @@ class _EncryptionSettingsWidgetState extends State { tooltip: generateStatusString(context, localValidationValid, certKeyValidApi) ), IconButton( - onPressed: saveData, + onPressed: localValidationValid ? + () => saveData() + : null, icon: const Icon(Icons.save), tooltip: AppLocalizations.of(context)!.save, ), diff --git a/pubspec.yaml b/pubspec.yaml index 9982de9..5296fbf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -67,7 +67,7 @@ dependencies: git: url: https://github.com/JGeek00/flutter_split_view ref: master-alt - url_launcher: ^6.1.10 + url_launcher: ^6.1.11 contextmenu: ^3.0.0 async: ^2.10.0 sentry_flutter: ^7.5.2 From d02a8594127bc42e6dce3d455b5d2d9347654dbf Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 20 May 2023 20:31:48 +0200 Subject: [PATCH 124/676] Bug fixed --- lib/models/logs.dart | 2 +- lib/screens/logs/log_tile.dart | 4 +-- lib/widgets/domain_options.dart | 51 ++++++++++++++++++--------------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/lib/models/logs.dart b/lib/models/logs.dart index c6122e5..9c21bca 100644 --- a/lib/models/logs.dart +++ b/lib/models/logs.dart @@ -172,7 +172,7 @@ class Whois { class Question { final String questionClass; - final String name; + final String? name; final String type; Question({ diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index fbdee24..bacf358 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -102,7 +102,7 @@ class LogTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - log.question.name, + log.question.name ?? "N/A", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, @@ -276,7 +276,7 @@ class LogTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - log.question.name, + log.question.name ?? "N/A", style: TextStyle( fontSize: 16, height: 1.5, diff --git a/lib/widgets/domain_options.dart b/lib/widgets/domain_options.dart index e250763..1612390 100644 --- a/lib/widgets/domain_options.dart +++ b/lib/widgets/domain_options.dart @@ -19,7 +19,7 @@ import 'package:adguard_home_manager/models/menu_option.dart'; class DomainOptions extends StatelessWidget { final bool isBlocked; final bool? isClient; - final String item; + final String? item; final Widget child; final void Function() onTap; final BorderRadius? borderRadius; @@ -110,17 +110,17 @@ class DomainOptions extends StatelessWidget { if (isClient != true && isBlocked == true) MenuOption( title: AppLocalizations.of(context)!.unblock, icon: Icons.check, - action: () => blockUnblock(item, 'unblock') + action: () => blockUnblock(item!, 'unblock') ), if (isClient != true && isBlocked == false) MenuOption( title: AppLocalizations.of(context)!.block, icon: Icons.block, - action: () => blockUnblock(item, 'block') + action: () => blockUnblock(item!, 'block') ), MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy, - action: () => copyDomainClipboard(item) + action: () => copyDomainClipboard(item!) ), ]; } @@ -134,25 +134,30 @@ class DomainOptions extends StatelessWidget { ); } - return Material( - color: Colors.transparent, - borderRadius: borderRadius, - child: ContextMenuArea( - builder: (context) => generateOptions().map((opt) => CustomListTile( - title: opt.title, - icon: opt.icon, - onTap: () { - opt.action(); - Navigator.pop(context); - }, - )).toList(), - child: InkWell( - onTap: onTap, - onLongPress: () => openOptionsModal(), - borderRadius: borderRadius, - child: child, + if (item != null) { + return Material( + color: Colors.transparent, + borderRadius: borderRadius, + child: ContextMenuArea( + builder: (context) => generateOptions().map((opt) => CustomListTile( + title: opt.title, + icon: opt.icon, + onTap: () { + opt.action(); + Navigator.pop(context); + }, + )).toList(), + child: InkWell( + onTap: onTap, + onLongPress: openOptionsModal, + borderRadius: borderRadius, + child: child, + ), ), - ), - ); + ); + } + else { + return child; + } } } \ No newline at end of file From 8ca59d26c7f3a801515a89e93a3328a8e18c4726 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 20 May 2023 21:12:52 +0200 Subject: [PATCH 125/676] Show name logs when available --- lib/l10n/app_en.arb | 9 +- lib/l10n/app_es.arb | 9 +- lib/providers/app_config_provider.dart | 36 ++++- lib/screens/logs/log_tile.dart | 172 +++++++++------------ lib/screens/logs/logs.dart | 5 +- lib/screens/settings/general_settings.dart | 116 ++++++++------ lib/services/db/database.dart | 26 +++- 7 files changed, 208 insertions(+), 165 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 7ad8a7b..685157d 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -558,8 +558,8 @@ "validPrivateKey": "Valid private key", "expirationDate": "Expiration date", "keysNotMatch": "Invalid certificate or key: tls: private key does not match public key", - "nameTimeLogs": "Name and time on logs", - "nameTimeLogsDescription": "Show client name and processing time on logs list", + "timeLogs": "Time on logs", + "timeLogsDescription": "Show processing time on logs list", "hostNames": "Host names", "keyType": "Key type", "updateAvailable": "Update available", @@ -622,5 +622,8 @@ "unsupprtedVersionMessage": "The support for your server version {version} is not guaranteed. This application may have some issues working with that server version.\n\nAdGuard Home Manager is designed to work with the stable releases of the AdGuard Home server. It may work with alpha and beta releases, but the compatibility is not guaranteed and the app may have some issues working with that versions.", "iUnderstand": "I understand", "appUpdates": "Application updates", - "usingLatestVersion": "You are using the latest version" + "usingLatestVersion": "You are using the latest version", + "ipLogs": "IP on logs", + "ipLogsDescription": "Show always IP address on logs instead of client name", + "application": "Application" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index e8c8477..41c93f0 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -558,8 +558,8 @@ "validPrivateKey": "Clave privada válida", "expirationDate": "Fecha de expiración", "keysNotMatch": "Certificado o clave inválido: tls: la clave privada no corresponde con la clave pública", - "nameTimeLogs": "Nombre y tiempo en logs", - "nameTimeLogsDescription": "Mostrar el nombre del cliente y el tiempo de procesamiento en la lista de logs", + "timeLogs": "Tiempo en logs", + "timeLogsDescription": "Mostrar el tiempo de procesamiento en la lista de logs", "hostNames": "Nombres de host", "keyType": "Tipo de clave", "updateAvailable": "Actualización disponible", @@ -622,5 +622,8 @@ "unsupprtedVersionMessage": "El soporte para la versión del servidor {version} no está garantizada. Esta aplicación puede tener problemas al trabajar con esa versión del servidor.\n\nAdGuard Home Manager está diseñado para trabajar con las versiones estables del servidor AdGuard Home. Puede funcionar con versiones alpha y beta, pero la compatibilidad no está asegurada y la aplicación puede tener problemas para trabajar con esas versiones.", "iUnderstand": "Lo entiendo", "appUpdates": "Actualizaciones de la app", - "usingLatestVersion": "Estás usando la última versión" + "usingLatestVersion": "Estás usando la última versión", + "ipLogs": "IP en registros", + "ipLogsDescription": "Mostrar siempre dirección IP en vez del nombre del cliente", + "application": "Aplicación" } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 7c1ae85..f0d8b80 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -37,7 +37,9 @@ class AppConfigProvider with ChangeNotifier { int _hideZeroValues = 0; - int _showNameTimeLogs = 0; + int _showTimeLogs = 0; + + int _showIpLogs = 0; String? _doNotRememberVersion; @@ -119,8 +121,12 @@ class AppConfigProvider with ChangeNotifier { return _useThemeColorForStatus; } - bool get showNameTimeLogs { - return _showNameTimeLogs == 1 ? true : false; + bool get showTimeLogs { + return _showTimeLogs == 1 ? true : false; + } + + bool get showIpLogs { + return _showIpLogs == 1 ? true : false; } String? get doNotRememberVersion { @@ -229,14 +235,30 @@ class AppConfigProvider with ChangeNotifier { } } - Future setShowNameTimeLogs(bool status) async { + Future setshowTimeLogs(bool status) async { final updated = await updateConfigQuery( db: _dbInstance!, - column: 'showNameTimeLogs', + column: 'showTimeLogs', value: status == true ? 1 : 0 ); if (updated == true) { - _showNameTimeLogs = status == true ? 1 : 0; + _showTimeLogs = status == true ? 1 : 0; + notifyListeners(); + return true; + } + else { + return false; + } + } + + Future setShowIpLogs(bool status) async { + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'showIpLogs', + value: status == true ? 1 : 0 + ); + if (updated == true) { + _showIpLogs = status == true ? 1 : 0; notifyListeners(); return true; } @@ -325,7 +347,7 @@ class AppConfigProvider with ChangeNotifier { _useDynamicColor = convertFromIntToBool(dbData['useDynamicColor'])!; _staticColor = dbData['staticColor']; _useThemeColorForStatus = dbData['useThemeColorForStatus'] != null ? convertFromIntToBool(dbData['useThemeColorForStatus'])! : false; - _showNameTimeLogs = dbData['showNameTimeLogs']; + _showTimeLogs = dbData['showTimeLogs']; _doNotRememberVersion = dbData['doNotRememberVersion']; _dbInstance = dbInstance; diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index bacf358..bd2b1a9 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -71,6 +71,18 @@ class LogTile extends StatelessWidget { ); } + String logClient() { + if (appConfigProvider.showIpLogs == true) { + return log.client; + } + else if (log.clientInfo != null && log.clientInfo!.name != "") { + return log.clientInfo!.name; + } + else { + return log.client; + } + } + if (width > 1100 && !(useAlwaysNormalTile == true)) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), @@ -110,7 +122,7 @@ class LogTile extends StatelessWidget { ), ), const SizedBox(height: 5), - if (log.client.length <= 15 && appConfigProvider.showNameTimeLogs == false) Row( + if (log.client.length <= 15 && appConfigProvider.showTimeLogs == false) Row( children: [ ...[ Icon( @@ -118,10 +130,10 @@ class LogTile extends StatelessWidget { size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 5), + const SizedBox(width: 8), Flexible( child: Text( - log.client, + logClient(), overflow: TextOverflow.ellipsis, style: TextStyle( color: Theme.of(context).listTileTheme.textColor, @@ -132,14 +144,14 @@ class LogTile extends StatelessWidget { ), ) ], - const SizedBox(width: 15), + const SizedBox(width: 16), ...[ Icon( Icons.schedule_rounded, size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 5), + const SizedBox(width: 8), Flexible( child: Text( convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), @@ -153,7 +165,7 @@ class LogTile extends StatelessWidget { ], ], ), - if (log.client.length > 15 || appConfigProvider.showNameTimeLogs == true) Column( + if (log.client.length > 15 || appConfigProvider.showTimeLogs == true) Column( children: [ Row( children: [ @@ -162,10 +174,10 @@ class LogTile extends StatelessWidget { size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 15), + const SizedBox(width: 8), Flexible( child: Text( - log.client, + logClient(), overflow: TextOverflow.ellipsis, style: TextStyle( color: Theme.of(context).listTileTheme.textColor, @@ -175,29 +187,6 @@ class LogTile extends StatelessWidget { ) ], ), - if (appConfigProvider.showNameTimeLogs == true && log.clientInfo != null && log.clientInfo!.name != '') ...[ - const SizedBox(height: 10), - Row( - children: [ - Icon( - Icons.badge_rounded, - size: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(width: 15), - Flexible( - child: Text( - log.clientInfo!.name, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor, - fontSize: 13 - ), - ), - ) - ], - ), - ], const SizedBox(height: 10), Row( children: [ @@ -206,7 +195,7 @@ class LogTile extends StatelessWidget { size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 15), + const SizedBox(width: 8), SizedBox( child: Text( convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), @@ -219,7 +208,7 @@ class LogTile extends StatelessWidget { ) ], ), - if (appConfigProvider.showNameTimeLogs == true && log.elapsedMs != '') ...[ + if (appConfigProvider.showTimeLogs == true && log.elapsedMs != '') ...[ const SizedBox(height: 10), Row( children: [ @@ -228,7 +217,7 @@ class LogTile extends StatelessWidget { size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 15), + const SizedBox(width: 8), SizedBox( child: Text( "${double.parse(log.elapsedMs).toStringAsFixed(2)} ms", @@ -285,7 +274,7 @@ class LogTile extends StatelessWidget { ), ), const SizedBox(height: 5), - if (log.client.length <= 15 && appConfigProvider.showNameTimeLogs == false) Row( + if (log.client.length <= 15 && appConfigProvider.showTimeLogs == false) Row( children: [ ...[ Icon( @@ -293,10 +282,10 @@ class LogTile extends StatelessWidget { size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 5), + const SizedBox(width: 8), Flexible( child: Text( - log.client, + logClient(), overflow: TextOverflow.ellipsis, style: TextStyle( color: Theme.of(context).listTileTheme.textColor, @@ -307,14 +296,14 @@ class LogTile extends StatelessWidget { ), ) ], - const SizedBox(width: 15), + const SizedBox(width: 16), ...[ Icon( Icons.schedule_rounded, size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 5), + const SizedBox(width: 8), Flexible( child: Text( convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), @@ -328,7 +317,7 @@ class LogTile extends StatelessWidget { ], ], ), - if (log.client.length > 15 || appConfigProvider.showNameTimeLogs == true) Column( + if (log.client.length > 15 || appConfigProvider.showTimeLogs == true) Column( children: [ Row( children: [ @@ -337,10 +326,10 @@ class LogTile extends StatelessWidget { size: 16, color: Theme.of(context).listTileTheme.textColor, ), - const SizedBox(width: 15), + const SizedBox(width: 8), Flexible( child: Text( - log.client, + logClient(), overflow: TextOverflow.ellipsis, style: TextStyle( color: Theme.of(context).listTileTheme.textColor, @@ -350,73 +339,54 @@ class LogTile extends StatelessWidget { ) ], ), - if (appConfigProvider.showNameTimeLogs == true && log.clientInfo != null && log.clientInfo!.name != '') ...[ - const SizedBox(height: 10), - Row( - children: [ - Icon( - Icons.badge_rounded, - size: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(width: 15), - Flexible( - child: Text( - log.clientInfo!.name, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor, - fontSize: 13 - ), - ), - ) - ], - ), - ], const SizedBox(height: 10), Row( children: [ - Icon( - Icons.schedule_rounded, - size: 16, - color: Theme.of(context).listTileTheme.textColor, - ), - const SizedBox(width: 15), - SizedBox( - child: Text( - convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), - overflow: TextOverflow.ellipsis, - style: TextStyle( + Row( + children: [ + Icon( + Icons.schedule_rounded, + size: 16, color: Theme.of(context).listTileTheme.textColor, - fontSize: 13 ), + const SizedBox(width: 8), + SizedBox( + child: Text( + convertTimestampLocalTimezone(log.time, 'HH:mm:ss'), + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ) + ], + ), + if (appConfigProvider.showTimeLogs == true && log.elapsedMs != '') ...[ + const SizedBox(width: 16), + Row( + children: [ + Icon( + Icons.timer, + size: 16, + color: Theme.of(context).listTileTheme.textColor, + ), + const SizedBox(width: 8), + SizedBox( + child: Text( + "${double.parse(log.elapsedMs).toStringAsFixed(2)} ms", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor, + fontSize: 13 + ), + ), + ) + ], ), - ) + ], ], ), - if (appConfigProvider.showNameTimeLogs == true && log.elapsedMs != '') ...[ - const SizedBox(height: 10), - Row( - children: [ - Icon( - Icons.timer, - size: 16, - color: Theme.of(context).listTileTheme.textColor, - ), - const SizedBox(width: 15), - SizedBox( - child: Text( - "${double.parse(log.elapsedMs).toStringAsFixed(2)} ms", - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor, - fontSize: 13 - ), - ), - ) - ], - ), - ], ], ), ], diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 74a7869..c88cd0e 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -330,7 +330,7 @@ class _LogsWidgetState extends State { ), ); } - else { + else if (logsProvider.logsData!.data[index].question.name != null) { return LogTile( log: logsProvider.logsData!.data[index], index: index, @@ -349,6 +349,9 @@ class _LogsWidgetState extends State { } ); } + else { + return null; + } } ) : Center( diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index 071ec84..5b5f27e 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -2,6 +2,8 @@ import 'dart:io'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:store_checker/store_checker.dart'; @@ -31,42 +33,23 @@ class _GeneralSettingsState extends State { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - Future updateHideZeroValues(bool newStatus) async { - final result = await appConfigProvider.setHideZeroValues(newStatus); + Future updateSettings({ + required bool newStatus, + required Future Function(bool) function + }) async { + final result = await function(newStatus); if (result == true) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.settingsUpdatedSuccessfully), - backgroundColor: Colors.green, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.settingsUpdatedSuccessfully, + color: Colors.green ); } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.cannotUpdateSettings), - backgroundColor: Colors.red, - ) - ); - } - } - - Future updateShowNameTimeLogs(bool newStatus) async { - final result = await appConfigProvider.setShowNameTimeLogs(newStatus); - if (result == true) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.settingsUpdatedSuccessfully), - backgroundColor: Colors.green, - ) - ); - } - else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.cannotUpdateSettings), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.cannotUpdateSettings, + color: Colors.red ); } } @@ -150,15 +133,45 @@ class _GeneralSettingsState extends State { ), SliverList.list( children: [ + SectionLabel(label: AppLocalizations.of(context)!.home), CustomListTile( icon: Icons.exposure_zero_rounded, title: AppLocalizations.of(context)!.hideZeroValues, subtitle: AppLocalizations.of(context)!.hideZeroValuesDescription, trailing: Switch( value: appConfigProvider.hideZeroValues, - onChanged: updateHideZeroValues, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setHideZeroValues + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.hideZeroValues, + function: appConfigProvider.setHideZeroValues + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), + SectionLabel(label: AppLocalizations.of(context)!.logs), + CustomListTile( + icon: Icons.timer_rounded, + title: AppLocalizations.of(context)!.timeLogs, + subtitle: AppLocalizations.of(context)!.timeLogsDescription, + trailing: Switch( + value: appConfigProvider.showTimeLogs, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setshowTimeLogs + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.showTimeLogs, + function: appConfigProvider.setshowTimeLogs ), - onTap: () => updateHideZeroValues(!appConfigProvider.hideZeroValues), padding: const EdgeInsets.only( top: 10, bottom: 10, @@ -168,13 +181,19 @@ class _GeneralSettingsState extends State { ), CustomListTile( icon: Icons.more, - title: AppLocalizations.of(context)!.nameTimeLogs, - subtitle: AppLocalizations.of(context)!.nameTimeLogsDescription, + title: AppLocalizations.of(context)!.ipLogs, + subtitle: AppLocalizations.of(context)!.ipLogsDescription, trailing: Switch( - value: appConfigProvider.showNameTimeLogs, - onChanged: updateShowNameTimeLogs, + value: appConfigProvider.showIpLogs, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setShowIpLogs + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.showIpLogs, + function: appConfigProvider.setShowIpLogs ), - onTap: () => updateShowNameTimeLogs(!appConfigProvider.showNameTimeLogs), padding: const EdgeInsets.only( top: 10, bottom: 10, @@ -188,14 +207,17 @@ class _GeneralSettingsState extends State { appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE) || appConfigProvider.installationSource == Source.UNKNOWN ) - ) CustomListTile( - icon: Icons.system_update_rounded, - title: AppLocalizations.of(context)!.appUpdates, - subtitle: appConfigProvider.appUpdatesAvailable != null - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.usingLatestVersion, - trailing: generateAppUpdateStatus() - ) + ) ...[ + SectionLabel(label: AppLocalizations.of(context)!.application), + CustomListTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.appUpdates, + subtitle: appConfigProvider.appUpdatesAvailable != null + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.usingLatestVersion, + trailing: generateAppUpdateStatus() + ) + ] ], ) ], diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index af9d8fb..2dc4d70 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -71,13 +71,24 @@ Future> loadDb(bool acceptsDynamicTheme) async { }); } + Future upgradeDbToV8(Database db) async { + await db.execute("ALTER TABLE appConfig RENAME COLUMN showNameTimeLogs TO showTimeLogs"); + await db.execute("ALTER TABLE appConfig ADD COLUMN showIpLogs NUMERIC"); + + await db.transaction((txn) async{ + await txn.rawQuery( + 'SELECT * FROM appConfig', + ); + }); + } + Database db = await openDatabase( 'adguard_home_manager.db', - version: 7, + version: 8, onCreate: (Database db, int version) async { await db.execute("CREATE TABLE servers (id TEXT PRIMARY KEY, name TEXT, connectionMethod TEXT, domain TEXT, path TEXT, port INTEGER, user TEXT, password TEXT, defaultServer INTEGER, authToken TEXT, runningOnHa INTEGER)"); - await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showNameTimeLogs NUMERIC, doNotRememberVersion TEXT)"); - await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showNameTimeLogs) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0)"); + await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showTimeLogs NUMERIC, showIpLogs, doNotRememberVersion TEXT)"); + await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0)"); }, onUpgrade: (Database db, int oldVersion, int newVersion) async { if (oldVersion == 1) { @@ -87,6 +98,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV5(db); await upgradeDbToV6(db); await upgradeDbToV7(db); + await upgradeDbToV8(db); } if (oldVersion == 2) { await upgradeDbToV3(db); @@ -94,24 +106,32 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV5(db); await upgradeDbToV6(db); await upgradeDbToV7(db); + await upgradeDbToV8(db); } if (oldVersion == 3) { await upgradeDbToV4(db); await upgradeDbToV5(db); await upgradeDbToV6(db); await upgradeDbToV7(db); + await upgradeDbToV8(db); } if (oldVersion == 4) { await upgradeDbToV5(db); await upgradeDbToV6(db); await upgradeDbToV7(db); + await upgradeDbToV8(db); } if (oldVersion == 5) { await upgradeDbToV6(db); await upgradeDbToV7(db); + await upgradeDbToV8(db); } if (oldVersion == 6) { await upgradeDbToV7(db); + await upgradeDbToV8(db); + } + if (oldVersion == 7) { + await upgradeDbToV8(db); } }, onOpen: (Database db) async { From cf5af1061fab43a70f4b5fd619f16935341038d9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 20 May 2023 22:57:38 +0200 Subject: [PATCH 126/676] Added new combined chart on home --- lib/l10n/app_en.arb | 7 +- lib/l10n/app_es.arb | 5 +- lib/providers/app_config_provider.dart | 23 ++ lib/screens/home/chart.dart | 6 +- lib/screens/home/combined_chart.dart | 285 +++++++++++++++++++++ lib/screens/home/home.dart | 23 +- lib/screens/home/server_status.dart | 21 +- lib/screens/settings/general_settings.dart | 22 ++ lib/services/db/database.dart | 5 +- lib/widgets/combined_line_chart.dart | 134 ++++++++++ 10 files changed, 506 insertions(+), 25 deletions(-) create mode 100644 lib/screens/home/combined_chart.dart create mode 100644 lib/widgets/combined_line_chart.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 685157d..a96efab 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -280,7 +280,7 @@ "accessSettingsDescription": "Configure access rules for the server", "loadingClients": "Loading clients...", "clientsNotLoaded": "Clients couldn't be loaded.", - "noAllowedClients": "No hay clientes permitidos", + "noAllowedClients": "No allowed clients", "allowedClientsDescription": "If this list has entries, AdGuard Home will accept requests only from these clients.", "blockedClientsDescription": "If this list has entries, AdGuard Home will drop requests from these clients. This field is ignored if there are entries in Allowed clients.", "disallowedDomainsDescription": "AdGuard Home drops DNS queries matching these domains, and these queries don't even appear in the query log.", @@ -625,5 +625,8 @@ "usingLatestVersion": "You are using the latest version", "ipLogs": "IP on logs", "ipLogsDescription": "Show always IP address on logs instead of client name", - "application": "Application" + "application": "Application", + "combinedChart": "Combined chart", + "combinedChartDescription": "Combine all charts into one", + "statistics": "Statistics" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 41c93f0..4739f4b 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -625,5 +625,8 @@ "usingLatestVersion": "Estás usando la última versión", "ipLogs": "IP en registros", "ipLogsDescription": "Mostrar siempre dirección IP en vez del nombre del cliente", - "application": "Aplicación" + "application": "Aplicación", + "combinedChart": "Gráfico combinado", + "combinedChartDescription": "Combina todos los gráficos en uno solo", + "statistics": "Estadísticas" } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index f0d8b80..0dc5f1c 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -41,6 +41,8 @@ class AppConfigProvider with ChangeNotifier { int _showIpLogs = 0; + int _combinedChartHome = 0; + String? _doNotRememberVersion; GitHubRelease? _appUpdatesAvailable; @@ -129,6 +131,10 @@ class AppConfigProvider with ChangeNotifier { return _showIpLogs == 1 ? true : false; } + bool get combinedChartHome { + return _combinedChartHome == 1 ? true : false; + } + String? get doNotRememberVersion { return _doNotRememberVersion; } @@ -315,6 +321,22 @@ class AppConfigProvider with ChangeNotifier { } } + Future setCombinedChartHome(bool value) async { + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'combinedChart', + value: value == true ? 1 : 0 + ); + if (updated == true) { + _combinedChartHome = value == true ? 1 : 0; + notifyListeners(); + return true; + } + else { + return false; + } + } + Future setStaticColor(int value) async { final updated = await updateConfigQuery( db: _dbInstance!, @@ -349,6 +371,7 @@ class AppConfigProvider with ChangeNotifier { _useThemeColorForStatus = dbData['useThemeColorForStatus'] != null ? convertFromIntToBool(dbData['useThemeColorForStatus'])! : false; _showTimeLogs = dbData['showTimeLogs']; _doNotRememberVersion = dbData['doNotRememberVersion']; + _combinedChartHome = dbData['combinedChart']; _dbInstance = dbInstance; notifyListeners(); diff --git a/lib/screens/home/chart.dart b/lib/screens/home/chart.dart index 2ea4535..cf2550a 100644 --- a/lib/screens/home/chart.dart +++ b/lib/screens/home/chart.dart @@ -37,7 +37,7 @@ class HomeChart extends StatelessWidget { return Column( children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( children: [ Padding( @@ -115,13 +115,13 @@ class HomeChart extends StatelessWidget { ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Divider( thickness: 1, color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), ), ), - const SizedBox(height: 20), + const SizedBox(height: 16), ], ); } diff --git a/lib/screens/home/combined_chart.dart b/lib/screens/home/combined_chart.dart new file mode 100644 index 0000000..f7080ab --- /dev/null +++ b/lib/screens/home/combined_chart.dart @@ -0,0 +1,285 @@ +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/widgets/combined_line_chart.dart'; + +import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; + +class CombinedChartData { + final CombinedChartItem totalQueries; + final CombinedChartItem? blockedFilters; + final CombinedChartItem? replacedSafeBrowsing; + final CombinedChartItem? replacedParental; + + const CombinedChartData({ + required this.totalQueries, + this.blockedFilters, + this.replacedSafeBrowsing, + this.replacedParental + }); +} + +class CombinedChartItem { + final String label; + final Color color; + final List data; + + const CombinedChartItem({ + required this.label, + required this.color, + required this.data + }); +} + +class CombinedHomeChart extends StatelessWidget { + const CombinedHomeChart({Key? key}) : super(key: key); + + List? removeZero(List list) { + final removed = list.where((i) => i > 0); + if (removed.isNotEmpty) { + return list; + } + else { + return null; + } + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; + + if (serversProvider.serverStatus.data != null) { + final data = CombinedChartData( + totalQueries: CombinedChartItem( + label: AppLocalizations.of(context)!.dnsQueries, + color: Colors.blue, + data: serversProvider.serverStatus.data!.stats.dnsQueries + ), + blockedFilters: appConfigProvider.hideZeroValues == true + ? removeZero(serversProvider.serverStatus.data!.stats.blockedFiltering) != null + ? CombinedChartItem( + label: AppLocalizations.of(context)!.blockedFilters, + color: Colors.red, + data: serversProvider.serverStatus.data!.stats.blockedFiltering + ) + : null + : CombinedChartItem( + label: AppLocalizations.of(context)!.blockedFilters, + color: Colors.red, + data: serversProvider.serverStatus.data!.stats.blockedFiltering + ) , + replacedSafeBrowsing: appConfigProvider.hideZeroValues == true + ? removeZero(serversProvider.serverStatus.data!.stats.replacedSafebrowsing) != null + ? CombinedChartItem( + label: AppLocalizations.of(context)!.malwarePhisingBlocked, + color: Colors.green, + data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing + ) + : null + : CombinedChartItem( + label: AppLocalizations.of(context)!.malwarePhisingBlocked, + color: Colors.green, + data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing + ) , + replacedParental: appConfigProvider.hideZeroValues == true + ? removeZero(serversProvider.serverStatus.data!.stats.replacedParental) != null + ? CombinedChartItem( + label: AppLocalizations.of(context)!.blockedAdultWebsites, + color: Colors.orange, + data: serversProvider.serverStatus.data!.stats.replacedParental + ) + : null + : CombinedChartItem( + label: AppLocalizations.of(context)!.blockedAdultWebsites, + color: Colors.orange, + data: serversProvider.serverStatus.data!.stats.replacedParental + ) , + ); + + Widget legend({ + required String label, + required Color color, + required String primaryValue, + String? secondaryValue + }) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + child: Text( + label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: color + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + primaryValue, + style: TextStyle( + color: color, + fontSize: 16, + fontWeight: FontWeight.w500 + ), + ), + if (secondaryValue != null) Text( + secondaryValue, + style: TextStyle( + fontSize: 10, + color: color + ), + ) + ], + ) + ], + ); + } + + if (width > 900) { + return Column( + children: [ + Text( + AppLocalizations.of(context)!.statistics, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + flex: 3, + child: SizedBox( + height: 300, + width: double.maxFinite, + child: CustomCombinedLineChart( + inputData: data, + ), + ), + ), + const SizedBox(width: 16), + Expanded( + flex: 2, + child: SizedBox( + height: 300, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + legend( + label: data.totalQueries.label, + color: data.totalQueries.color, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + ), + const SizedBox(height: 16), + if (data.blockedFilters != null) legend( + label: data.blockedFilters!.label, + color: data.blockedFilters!.color, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + ), + const SizedBox(height: 16), + if (data.replacedSafeBrowsing != null) legend( + label: data.replacedSafeBrowsing!.label, + color: data.replacedSafeBrowsing!.color, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + ), + const SizedBox(height: 16), + if (data.replacedParental != null) legend( + label: data.replacedParental!.label, + color: data.replacedParental!.color, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + ), + ], + ), + ) + ), + ], + ) + ], + ); + } + else { + return Column( + children: [ + Column( + children: [ + Text( + AppLocalizations.of(context)!.statistics, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + SizedBox( + height: 300, + width: double.maxFinite, + child: CustomCombinedLineChart( + inputData: data, + ), + ), + const SizedBox(height: 16), + legend( + label: data.totalQueries.label, + color: data.totalQueries.color, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + ), + const SizedBox(height: 16), + if (data.blockedFilters != null) legend( + label: data.blockedFilters!.label, + color: data.blockedFilters!.color, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + ), + const SizedBox(height: 16), + if (data.replacedSafeBrowsing != null) legend( + label: data.replacedSafeBrowsing!.label, + color: data.replacedSafeBrowsing!.color, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + ), + const SizedBox(height: 16), + if (data.replacedParental != null) legend( + label: data.replacedParental!.label, + color: data.replacedParental!.color, + primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + ), + const SizedBox(height: 16), + ], + ), + Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + const SizedBox(height: 16) + ], + ); + } + } + else { + return const SizedBox(); + } + } +} \ No newline at end of file diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index ec1bc3b..f6bd07d 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -8,6 +8,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/home/server_status.dart'; +import 'package:adguard_home_manager/screens/home/combined_chart.dart'; import 'package:adguard_home_manager/screens/home/appbar.dart'; import 'package:adguard_home_manager/screens/home/fab.dart'; import 'package:adguard_home_manager/screens/home/top_items.dart'; @@ -110,15 +111,15 @@ class _HomeState extends State { return [ ServerStatus(serverStatus: serversProvider.serverStatus.data!), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Divider( thickness: 1, color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), ), ), - const SizedBox(height: 20), + const SizedBox(height: 16), - Wrap( + if (appConfigProvider.combinedChartHome == false) Wrap( children: [ FractionallySizedBox( widthFactor: width > 700 ? 0.5 : 1, @@ -159,10 +160,14 @@ class _HomeState extends State { secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.orange, ), - ), - + ), ], ), + + if (appConfigProvider.combinedChartHome == true) const Padding( + padding: EdgeInsets.symmetric(horizontal: 16), + child: CombinedHomeChart(), + ), if (width <= 700) ...[ TopItems( @@ -171,14 +176,14 @@ class _HomeState extends State { type: 'topQueriedDomains', ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Divider( thickness: 1, color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), ), ), - const SizedBox(height: 20), + const SizedBox(height: 16), TopItems( label: AppLocalizations.of(context)!.topBlockedDomains, @@ -186,13 +191,13 @@ class _HomeState extends State { type: 'topBlockedDomains', ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Divider( thickness: 1, color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), ), ), - const SizedBox(height: 20), + const SizedBox(height: 16), TopItems( label: AppLocalizations.of(context)!.topClients, diff --git a/lib/screens/home/server_status.dart b/lib/screens/home/server_status.dart index 3026c90..3cc7656 100644 --- a/lib/screens/home/server_status.dart +++ b/lib/screens/home/server_status.dart @@ -18,19 +18,24 @@ class ServerStatus extends StatelessWidget { final width = MediaQuery.of(context).size.width; return Container( - padding: const EdgeInsets.only(left: 20, right: 20, bottom: 10), + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16), child: Column( children: [ - Text( - AppLocalizations.of(context)!.serverStatus, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface + Padding( + padding: width > 700 + ? const EdgeInsets.all(16) + : const EdgeInsets.all(0), + child: Text( + AppLocalizations.of(context)!.serverStatus, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), ), ), SizedBox( - height: width > 700 ? 90 : 170, + height: width > 700 ? 70 : 170, child: GridView( physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index 5b5f27e..f82638f 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -156,6 +156,28 @@ class _GeneralSettingsState extends State { right: 10 ) ), + CustomListTile( + icon: Icons.show_chart_rounded, + title: AppLocalizations.of(context)!.combinedChart, + subtitle: AppLocalizations.of(context)!.combinedChartDescription, + trailing: Switch( + value: appConfigProvider.combinedChartHome, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setCombinedChartHome + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.combinedChartHome, + function: appConfigProvider.setCombinedChartHome + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), SectionLabel(label: AppLocalizations.of(context)!.logs), CustomListTile( icon: Icons.timer_rounded, diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index 2dc4d70..eddcbc2 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -74,6 +74,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { Future upgradeDbToV8(Database db) async { await db.execute("ALTER TABLE appConfig RENAME COLUMN showNameTimeLogs TO showTimeLogs"); await db.execute("ALTER TABLE appConfig ADD COLUMN showIpLogs NUMERIC"); + await db.execute("ALTER TABLE appConfig ADD COLUMN combinedChart NUMERIC"); await db.transaction((txn) async{ await txn.rawQuery( @@ -87,8 +88,8 @@ Future> loadDb(bool acceptsDynamicTheme) async { version: 8, onCreate: (Database db, int version) async { await db.execute("CREATE TABLE servers (id TEXT PRIMARY KEY, name TEXT, connectionMethod TEXT, domain TEXT, path TEXT, port INTEGER, user TEXT, password TEXT, defaultServer INTEGER, authToken TEXT, runningOnHa INTEGER)"); - await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showTimeLogs NUMERIC, showIpLogs, doNotRememberVersion TEXT)"); - await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0)"); + await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showTimeLogs NUMERIC, showIpLogs NUMERIC, combinedChart NUMERIC, doNotRememberVersion TEXT)"); + await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs, combinedChart) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0, 0)"); }, onUpgrade: (Database db, int oldVersion, int newVersion) async { if (oldVersion == 1) { diff --git a/lib/widgets/combined_line_chart.dart b/lib/widgets/combined_line_chart.dart new file mode 100644 index 0000000..0ce6a58 --- /dev/null +++ b/lib/widgets/combined_line_chart.dart @@ -0,0 +1,134 @@ +import 'package:adguard_home_manager/screens/home/combined_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:provider/provider.dart'; + +import 'package:adguard_home_manager/providers/app_config_provider.dart'; + + +class CustomCombinedLineChart extends StatelessWidget { + final CombinedChartData inputData; + + const CustomCombinedLineChart({ + Key? key, + required this.inputData, + }) : super(key: key); + + LineChartData mainData(Map data, ThemeMode selectedTheme) { + return LineChartData( + gridData: FlGridData( + show: false, + drawVerticalLine: false, + ), + titlesData: FlTitlesData( + show: false, + ), + borderData: FlBorderData( + show: false, + ), + lineBarsData: List.from( + data["lines"].map((item) => LineChartBarData( + spots: item['data'], + color: item['color'], + isCurved: true, + barWidth: 2, + isStrokeCapRound: true, + preventCurveOverShooting: true, + dotData: FlDotData( + show: false, + ), + belowBarData: BarAreaData( + show: true, + color: item['color'].withOpacity(0.2) + ), + )) + ), + lineTouchData: LineTouchData( + enabled: true, + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: selectedTheme == ThemeMode.light + ? const Color.fromRGBO(220, 220, 220, 0.9) + : const Color.fromRGBO(35, 35, 35, 0.9), + getTooltipItems: (items) => items.asMap().entries.map((item) => LineTooltipItem( + "${data['lines'][item.key]['label']}: ${item.value.y.toInt().toString()}", + TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: data['lines'][item.key]['color'] + ) + )).toList() + ), + ) + ); + } + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + + Map formatData(CombinedChartData unformattedData) { + int topPoint = 0; + + List dataLine(List data) { + final List formattedData = []; + + int xPosition = 0; + for (int i = 0; i < data.length; i++) { + if (data[i] > topPoint) { + topPoint = data[i]; + } + formattedData.add( + FlSpot( + xPosition.toDouble(), + data[i].toDouble() + ) + ); + xPosition++; + } + + return formattedData; + } + + List> toDraw = []; + + toDraw.add({ + "data": dataLine(unformattedData.totalQueries.data), + "color": unformattedData.totalQueries.color, + "label": unformattedData.totalQueries.label + }); + if (unformattedData.blockedFilters != null) { + toDraw.add({ + "data": dataLine(unformattedData.blockedFilters!.data), + "color": unformattedData.blockedFilters!.color, + "label": unformattedData.blockedFilters!.label + }); + } + if (unformattedData.replacedSafeBrowsing != null) { + toDraw.add({ + "data": dataLine(unformattedData.replacedSafeBrowsing!.data), + "color": unformattedData.replacedSafeBrowsing!.color, + "label": unformattedData.replacedSafeBrowsing!.label + }); + } + if (unformattedData.replacedParental != null) { + toDraw.add({ + "data": dataLine(unformattedData.replacedParental!.data), + "color": unformattedData.replacedParental!.color, + "label": unformattedData.replacedParental!.label + }); + } + + return { + 'lines': toDraw, + 'topPoint': topPoint + }; + } + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 15), + child: LineChart( + mainData(formatData(inputData), appConfigProvider.selectedTheme) + ), + ); + } +} \ No newline at end of file From df46d4b53f5bc219b96b3c06e1aef7f6619aac4e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 00:43:24 +0200 Subject: [PATCH 127/676] Small fixes --- lib/providers/app_config_provider.dart | 1 + lib/services/db/database.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 0dc5f1c..e2d23c1 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -371,6 +371,7 @@ class AppConfigProvider with ChangeNotifier { _useThemeColorForStatus = dbData['useThemeColorForStatus'] != null ? convertFromIntToBool(dbData['useThemeColorForStatus'])! : false; _showTimeLogs = dbData['showTimeLogs']; _doNotRememberVersion = dbData['doNotRememberVersion']; + _showIpLogs = dbData['showIpLogs']; _combinedChartHome = dbData['combinedChart']; _dbInstance = dbInstance; diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index eddcbc2..180c566 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -75,6 +75,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await db.execute("ALTER TABLE appConfig RENAME COLUMN showNameTimeLogs TO showTimeLogs"); await db.execute("ALTER TABLE appConfig ADD COLUMN showIpLogs NUMERIC"); await db.execute("ALTER TABLE appConfig ADD COLUMN combinedChart NUMERIC"); + await db.execute("UPDATE appConfig SET showIpLogs = 0, combinedChart = 0"); await db.transaction((txn) async{ await txn.rawQuery( From 098eb4586f85db5ff21fe654ecb48f8d2d3b47ff Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 01:03:44 +0200 Subject: [PATCH 128/676] Updated android and macos version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 1406889..a1405ff 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.2.0; + MARKETING_VERSION = 2.3.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.2.0; + MARKETING_VERSION = 2.3.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.2.0; + MARKETING_VERSION = 2.3.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; diff --git a/pubspec.yaml b/pubspec.yaml index 5296fbf..bb1453c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.2.0+58 +version: 2.3.0+59 environment: sdk: '>=2.18.1 <3.0.0' From b28fea3e7915026b0ee928579b08926d6c913607 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 01:19:28 +0200 Subject: [PATCH 129/676] Updated Linux version --- debian/debian.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index 6c23be8..f1e3410 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.2.0 + Version: 2.3.0 Architecture: amd64 Essential: no Priority: optional From 4a202727728036dfd565f3d52799984f1656114b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 01:30:16 +0200 Subject: [PATCH 130/676] Updated Windows version --- windows/innosetup_installer_builder.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 79b9261..a983de2 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AdGuard Home Manager" -#define MyAppVersion "2.2.0" +#define MyAppVersion "2.3.0" #define MyAppPublisher "JGeek00" #define MyAppURL "https://github.com/JGeek00/adguard-home-manager" #define MyAppExeName "adguard_home_manager.exe" From 9d59a5caac8a70a56444c9f3da02195e55a4fa8f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 02:03:33 +0200 Subject: [PATCH 131/676] Fixed some issues home ui --- lib/screens/home/combined_chart.dart | 9 +- lib/screens/home/home.dart | 126 ++++++++++++++------------- lib/screens/home/server_status.dart | 21 ++--- 3 files changed, 80 insertions(+), 76 deletions(-) diff --git a/lib/screens/home/combined_chart.dart b/lib/screens/home/combined_chart.dart index f7080ab..9bd9d36 100644 --- a/lib/screens/home/combined_chart.dart +++ b/lib/screens/home/combined_chart.dart @@ -149,7 +149,7 @@ class CombinedHomeChart extends StatelessWidget { ); } - if (width > 900) { + if (width > 700) { return Column( children: [ Text( @@ -213,7 +213,12 @@ class CombinedHomeChart extends StatelessWidget { ) ), ], - ) + ), + Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + const SizedBox(height: 16) ], ); } diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index f6bd07d..9626130 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -208,7 +208,6 @@ class _HomeState extends State { ], if (width > 700) Column( children: [ - const SizedBox(height: 16), Wrap( alignment: WrapAlignment.center, children: [ @@ -259,68 +258,71 @@ class _HomeState extends State { } return Scaffold( - body: Stack( - children: [ - NestedScrollView( - controller: scrollController, - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: HomeAppBar(innerBoxScrolled: innerBoxIsScrolled,) + body: SafeArea( + top: false, + child: Stack( + children: [ + NestedScrollView( + controller: scrollController, + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: HomeAppBar(innerBoxScrolled: innerBoxIsScrolled,) + ) + ], + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => RefreshIndicator( + color: Theme.of(context).colorScheme.primary, + onRefresh: () async { + final result = await getServerStatus(serversProvider.selectedServer!); + if (result['result'] == 'success') { + serversProvider.setServerStatusData(result['data']); + } + else { + appConfigProvider.addLog(result['log']); + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.serverStatusNotRefreshed, + color: Colors.red + ); + } + }, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (serversProvider.serverStatus.loadStatus == 0) SliverFillRemaining( + child: loading(), + ), + if (serversProvider.serverStatus.loadStatus == 1) SliverList.list( + children: listItems() + ), + if (serversProvider.serverStatus.loadStatus == 2) SliverFillRemaining( + child: loadError(), + ), + ], + ) + ), + ) ) - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => RefreshIndicator( - color: Theme.of(context).colorScheme.primary, - onRefresh: () async { - final result = await getServerStatus(serversProvider.selectedServer!); - if (result['result'] == 'success') { - serversProvider.setServerStatusData(result['data']); - } - else { - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.serverStatusNotRefreshed, - color: Colors.red - ); - } - }, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (serversProvider.serverStatus.loadStatus == 0) SliverFillRemaining( - child: loading(), - ), - if (serversProvider.serverStatus.loadStatus == 1) SliverList.list( - children: listItems() - ), - if (serversProvider.serverStatus.loadStatus == 2) SliverFillRemaining( - child: loadError(), - ), - ], - ) - ), - ) - ) - ), - AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: isVisible == true ? - appConfigProvider.showingSnackbar - ? 70 - : 20 - : -70, - right: 20, - child: const HomeFab() - ), - ], + ), + AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: isVisible == true ? + appConfigProvider.showingSnackbar + ? 70 + : 20 + : -70, + right: 20, + child: const HomeFab() + ), + ], + ), ), ); } diff --git a/lib/screens/home/server_status.dart b/lib/screens/home/server_status.dart index 3cc7656..2a52889 100644 --- a/lib/screens/home/server_status.dart +++ b/lib/screens/home/server_status.dart @@ -21,22 +21,19 @@ class ServerStatus extends StatelessWidget { padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16), child: Column( children: [ - Padding( - padding: width > 700 - ? const EdgeInsets.all(16) - : const EdgeInsets.all(0), - child: Text( - AppLocalizations.of(context)!.serverStatus, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), + Text( + AppLocalizations.of(context)!.serverStatus, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface ), ), + const SizedBox(height: 16), SizedBox( - height: width > 700 ? 70 : 170, + height: width > 700 ? 66 : 146, child: GridView( + padding: const EdgeInsets.all(0), physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: width > 700 ? 4 : 2, From b079357b232557145ec6d1e6f77256747f3722d6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 02:14:52 +0200 Subject: [PATCH 132/676] Updated Android and macOS version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index a1405ff..f4a2695 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 59; + CURRENT_PROJECT_VERSION = 60; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 59; + CURRENT_PROJECT_VERSION = 60; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 59; + CURRENT_PROJECT_VERSION = 60; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; diff --git a/pubspec.yaml b/pubspec.yaml index bb1453c..07903d9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.3.0+59 +version: 2.3.1+60 environment: sdk: '>=2.18.1 <3.0.0' From 59c39b9247d6dd61f6533733261d5ba0c5ecde24 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 02:20:54 +0200 Subject: [PATCH 133/676] Updated Linux version --- debian/debian.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index f1e3410..c04109c 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.3.0 + Version: 2.3.1 Architecture: amd64 Essential: no Priority: optional From b3e1931b1bb5892a8d72a262ff50b6f56234e39d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 02:24:55 +0200 Subject: [PATCH 134/676] Updated Windows version --- windows/innosetup_installer_builder.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index a983de2..4912e9c 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AdGuard Home Manager" -#define MyAppVersion "2.3.0" +#define MyAppVersion "2.3.1" #define MyAppPublisher "JGeek00" #define MyAppURL "https://github.com/JGeek00/adguard-home-manager" #define MyAppExeName "adguard_home_manager.exe" From df4564e97561968bc81fcf6219483c2e97610952 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 14:48:27 +0200 Subject: [PATCH 135/676] Database fixes --- lib/providers/app_config_provider.dart | 12 ++++----- lib/services/db/database.dart | 34 ++++++++++++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index e2d23c1..0f8096d 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -363,16 +363,16 @@ class AppConfigProvider with ChangeNotifier { } void saveFromDb(Database dbInstance, Map dbData) { - _selectedTheme = dbData['theme']; - _overrideSslCheck = dbData['overrideSslCheck']; + _selectedTheme = dbData['theme'] ?? 0; + _overrideSslCheck = dbData['overrideSslCheck'] ?? 0; _hideZeroValues = dbData['hideZeroValues']; _useDynamicColor = convertFromIntToBool(dbData['useDynamicColor'])!; - _staticColor = dbData['staticColor']; + _staticColor = dbData['staticColor'] ?? 0; _useThemeColorForStatus = dbData['useThemeColorForStatus'] != null ? convertFromIntToBool(dbData['useThemeColorForStatus'])! : false; - _showTimeLogs = dbData['showTimeLogs']; + _showTimeLogs = dbData['showTimeLogs'] ?? 0; _doNotRememberVersion = dbData['doNotRememberVersion']; - _showIpLogs = dbData['showIpLogs']; - _combinedChartHome = dbData['combinedChart']; + _showIpLogs = dbData['showIpLogs'] ?? 0; + _combinedChartHome = dbData['combinedChart'] ?? 0; _dbInstance = dbInstance; notifyListeners(); diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index 180c566..9a9ac18 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -4,6 +4,12 @@ Future> loadDb(bool acceptsDynamicTheme) async { List>? servers; List>? appConfig; + Future rebuildAppConfig(Database db) async { + await db.execute("DROP TABLE appConfig"); + await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showTimeLogs NUMERIC, showIpLogs NUMERIC, combinedChart NUMERIC, doNotRememberVersion TEXT)"); + await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs, combinedChart) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0, 0)"); + } + Future upgradeDbToV2(Database db) async { await db.execute("ALTER TABLE appConfig ADD COLUMN overrideSslCheck NUMERIC"); await db.execute("UPDATE appConfig SET overrideSslCheck = 0"); @@ -72,16 +78,28 @@ Future> loadDb(bool acceptsDynamicTheme) async { } Future upgradeDbToV8(Database db) async { - await db.execute("ALTER TABLE appConfig RENAME COLUMN showNameTimeLogs TO showTimeLogs"); - await db.execute("ALTER TABLE appConfig ADD COLUMN showIpLogs NUMERIC"); - await db.execute("ALTER TABLE appConfig ADD COLUMN combinedChart NUMERIC"); - await db.execute("UPDATE appConfig SET showIpLogs = 0, combinedChart = 0"); - - await db.transaction((txn) async{ - await txn.rawQuery( + try { + final data = await db.rawQuery( 'SELECT * FROM appConfig', ); - }); + await rebuildAppConfig(db); + await db.update( + 'appConfig', + { + 'theme': data[0]['theme'], + 'overrideSslCheck': data[0]['overrideSslCheck'], + 'hideZeroValues': data[0]['hideZeroValues'], + 'useDynamicColor': data[0]['useDynamicColor'], + 'staticColor': data[0]['staticColor'], + 'useThemeColorForStatus': data[0]['useThemeColorForStatus'], + 'showTimeLogs': data[0]['showNameTimeLogs'], + 'showIpLogs': data[0]['showIpLogs'], + 'combinedChart': data[0]['combinedChart'], + } + ); + } catch (e) { + await rebuildAppConfig(db); + } } Database db = await openDatabase( From 9aa79806a92cf7a0d84a1dfd2faeb850bc9f9682 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 14:52:35 +0200 Subject: [PATCH 136/676] Fixed scrolling issue on some screens --- lib/screens/logs/log_details_screen.dart | 42 ++-- lib/screens/settings/general_settings.dart | 248 ++++++++++----------- 2 files changed, 128 insertions(+), 162 deletions(-) diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index a6b8f45..1dafc64 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -294,35 +294,25 @@ class LogDetailsScreen extends StatelessWidget { } else { return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(AppLocalizations.of(context)!.logDetails), - actions: [ - if (serversProvider.filteringStatus != null) IconButton( - onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), - icon: Icon( - getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? Icons.check_circle_rounded - : Icons.block - ), - tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? AppLocalizations.of(context)!.unblockDomain - : AppLocalizations.of(context)!.blockDomain, - ), - const SizedBox(width: 10) - ], + appBar: AppBar( + centerTitle: false, + title: Text(AppLocalizations.of(context)!.logDetails), + actions: [ + if (serversProvider.filteringStatus != null) IconButton( + onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), + icon: Icon( + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? Icons.check_circle_rounded + : Icons.block ), - ) + tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? AppLocalizations.of(context)!.unblockDomain + : AppLocalizations.of(context)!.blockDomain, + ), + const SizedBox(width: 10) ], - body: content(), ), + body: content(), ); } } diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index f82638f..178eb40 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -109,143 +109,119 @@ class _GeneralSettingsState extends State { } return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(AppLocalizations.of(context)!.generalSettings), - ) - ) - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverList.list( - children: [ - SectionLabel(label: AppLocalizations.of(context)!.home), - CustomListTile( - icon: Icons.exposure_zero_rounded, - title: AppLocalizations.of(context)!.hideZeroValues, - subtitle: AppLocalizations.of(context)!.hideZeroValuesDescription, - trailing: Switch( - value: appConfigProvider.hideZeroValues, - onChanged: (value) => updateSettings( - newStatus: value, - function: appConfigProvider.setHideZeroValues - ), - ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.hideZeroValues, - function: appConfigProvider.setHideZeroValues - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - CustomListTile( - icon: Icons.show_chart_rounded, - title: AppLocalizations.of(context)!.combinedChart, - subtitle: AppLocalizations.of(context)!.combinedChartDescription, - trailing: Switch( - value: appConfigProvider.combinedChartHome, - onChanged: (value) => updateSettings( - newStatus: value, - function: appConfigProvider.setCombinedChartHome - ), - ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.combinedChartHome, - function: appConfigProvider.setCombinedChartHome - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - SectionLabel(label: AppLocalizations.of(context)!.logs), - CustomListTile( - icon: Icons.timer_rounded, - title: AppLocalizations.of(context)!.timeLogs, - subtitle: AppLocalizations.of(context)!.timeLogsDescription, - trailing: Switch( - value: appConfigProvider.showTimeLogs, - onChanged: (value) => updateSettings( - newStatus: value, - function: appConfigProvider.setshowTimeLogs - ), - ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.showTimeLogs, - function: appConfigProvider.setshowTimeLogs - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - CustomListTile( - icon: Icons.more, - title: AppLocalizations.of(context)!.ipLogs, - subtitle: AppLocalizations.of(context)!.ipLogsDescription, - trailing: Switch( - value: appConfigProvider.showIpLogs, - onChanged: (value) => updateSettings( - newStatus: value, - function: appConfigProvider.setShowIpLogs - ), - ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.showIpLogs, - function: appConfigProvider.setShowIpLogs - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - if ( - !(Platform.isAndroid || Platform.isIOS) || - (Platform.isAndroid && ( - appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE) || - appConfigProvider.installationSource == Source.UNKNOWN - ) - ) ...[ - SectionLabel(label: AppLocalizations.of(context)!.application), - CustomListTile( - icon: Icons.system_update_rounded, - title: AppLocalizations.of(context)!.appUpdates, - subtitle: appConfigProvider.appUpdatesAvailable != null - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.usingLatestVersion, - trailing: generateAppUpdateStatus() - ) - ] - ], - ) - ], + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.generalSettings), + ), + body: ListView( + children: [ + SectionLabel(label: AppLocalizations.of(context)!.home), + CustomListTile( + icon: Icons.exposure_zero_rounded, + title: AppLocalizations.of(context)!.hideZeroValues, + subtitle: AppLocalizations.of(context)!.hideZeroValuesDescription, + trailing: Switch( + value: appConfigProvider.hideZeroValues, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setHideZeroValues + ), ), - ) - ) + onTap: () => updateSettings( + newStatus: !appConfigProvider.hideZeroValues, + function: appConfigProvider.setHideZeroValues + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), + CustomListTile( + icon: Icons.show_chart_rounded, + title: AppLocalizations.of(context)!.combinedChart, + subtitle: AppLocalizations.of(context)!.combinedChartDescription, + trailing: Switch( + value: appConfigProvider.combinedChartHome, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setCombinedChartHome + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.combinedChartHome, + function: appConfigProvider.setCombinedChartHome + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), + SectionLabel(label: AppLocalizations.of(context)!.logs), + CustomListTile( + icon: Icons.timer_rounded, + title: AppLocalizations.of(context)!.timeLogs, + subtitle: AppLocalizations.of(context)!.timeLogsDescription, + trailing: Switch( + value: appConfigProvider.showTimeLogs, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setshowTimeLogs + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.showTimeLogs, + function: appConfigProvider.setshowTimeLogs + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), + CustomListTile( + icon: Icons.more, + title: AppLocalizations.of(context)!.ipLogs, + subtitle: AppLocalizations.of(context)!.ipLogsDescription, + trailing: Switch( + value: appConfigProvider.showIpLogs, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setShowIpLogs + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.showIpLogs, + function: appConfigProvider.setShowIpLogs + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), + if ( + !(Platform.isAndroid || Platform.isIOS) || + (Platform.isAndroid && ( + appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE) || + appConfigProvider.installationSource == Source.UNKNOWN + ) + ) ...[ + SectionLabel(label: AppLocalizations.of(context)!.application), + CustomListTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.appUpdates, + subtitle: appConfigProvider.appUpdatesAvailable != null + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.usingLatestVersion, + trailing: generateAppUpdateStatus() + ) + ] + ], ) ); } From 8234c092b691ee20d01aca52d64c9a2c3b483bda Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 15:20:59 +0200 Subject: [PATCH 137/676] Updated Android and macOS version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index f4a2695..5bf52bf 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 60; + CURRENT_PROJECT_VERSION = 61; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 60; + CURRENT_PROJECT_VERSION = 61; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 60; + CURRENT_PROJECT_VERSION = 61; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; diff --git a/pubspec.yaml b/pubspec.yaml index 07903d9..0197c6c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.3.1+60 +version: 2.3.2+61 environment: sdk: '>=2.18.1 <3.0.0' From 3434b489667d87af3eb8e568b498199c4ff5af8f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 15:26:26 +0200 Subject: [PATCH 138/676] Updated Linux version --- debian/debian.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index c04109c..7adcb2a 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.3.1 + Version: 2.3.2 Architecture: amd64 Essential: no Priority: optional From 47a42db5155c75536dea8adb30813b4541ce5efc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 15:30:36 +0200 Subject: [PATCH 139/676] Updated Windows version --- windows/innosetup_installer_builder.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 4912e9c..c818a3e 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AdGuard Home Manager" -#define MyAppVersion "2.3.1" +#define MyAppVersion "2.3.2" #define MyAppPublisher "JGeek00" #define MyAppURL "https://github.com/JGeek00/adguard-home-manager" #define MyAppExeName "adguard_home_manager.exe" From 0d87a2f2529922599ccb39a526f0d2945b51da6b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 18:42:33 +0200 Subject: [PATCH 140/676] Small bug fixes --- lib/services/db/queries.dart | 2 +- lib/services/http_requests.dart | 2 +- lib/widgets/add_server_modal.dart | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/services/db/queries.dart b/lib/services/db/queries.dart index d5b018d..d81d187 100644 --- a/lib/services/db/queries.dart +++ b/lib/services/db/queries.dart @@ -43,7 +43,7 @@ Future editServerQuery(Database db, Server server) async { 'port': server.port, 'user': server.user, 'password': server.password, - 'defaultServer': server.defaultServer, + 'defaultServer': convertFromBoolToInt(server.defaultServer), 'authToken': server.authToken, 'runningOnHa': convertFromBoolToInt(server.runningOnHa) }, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 5507147..35b542f 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -274,7 +274,7 @@ Future getServerVersion(Server server) async { if (result['statusCode'] == 200 && result['body'] != null) { return { 'result': 'success', - 'data': result['body']['version'] + 'data': jsonDecode(result['body'])['version'] }; } else { diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 4eba693..70ca410 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -377,7 +377,7 @@ class _AddServerModalState extends State { final serverSaved = await serversProvider.editServer(serverObj); if (serverSaved == null) { - final version = await getServerVersion(serverObj);; + final version = await getServerVersion(serverObj); if ( version['result'] == 'success' && (version['data'].contains('a') || version['data'].contains('b')) // alpha or beta From d23e26c8d796440f8e2423ef87a1b8aabaa08d8b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 18:59:04 +0200 Subject: [PATCH 141/676] Updated libraries --- lib/main.dart | 6 +- .../settings/customization/customization.dart | 4 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 +- macos/Podfile.lock | 10 ++-- pubspec.lock | 58 ++++++------------- pubspec.yaml | 4 +- 6 files changed, 30 insertions(+), 54 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 135685f..e768f7d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -55,7 +55,7 @@ void main() async { appConfigProvider.setIosInfo(iosInfo); } - final dbData = await loadDb(appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt! >= 31); + final dbData = await loadDb(appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31); if (dbData['appConfig']['overrideSslCheck'] == 1) { HttpOverrides.global = MyHttpOverrides(); @@ -162,12 +162,12 @@ class _MainState extends State
{ return DynamicColorBuilder( builder: (lightDynamic, darkDynamic) => MaterialApp( title: 'AdGuard Home Manager', - theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt! >= 31 + theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 ? appConfigProvider.useDynamicColor == true ? lightTheme(lightDynamic) : lightThemeOldVersions(colors[appConfigProvider.staticColor]) : lightThemeOldVersions(colors[appConfigProvider.staticColor]), - darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt! >= 31 + darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 ? appConfigProvider.useDynamicColor == true ? darkTheme(darkDynamic) : darkThemeOldVersions(colors[appConfigProvider.staticColor]) diff --git a/lib/screens/settings/customization/customization.dart b/lib/screens/settings/customization/customization.dart index e955323..98a7121 100644 --- a/lib/screens/settings/customization/customization.dart +++ b/lib/screens/settings/customization/customization.dart @@ -111,7 +111,7 @@ class _CustomizationWidgetState extends State { label: AppLocalizations.of(context)!.color, padding: const EdgeInsets.only(top: 45, left: 16, right: 16, bottom: 5), ), - if (appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt! >= 31) CustomSwitchListTile( + if (appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31) CustomSwitchListTile( value: dynamicColor, onChanged: (value) { setState(() => dynamicColor = value); @@ -119,7 +119,7 @@ class _CustomizationWidgetState extends State { }, title: AppLocalizations.of(context)!.useDynamicTheme, ), - if (!(appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt! >= 31)) const SizedBox(height: 20), + if (!(appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31)) const SizedBox(height: 20), if (dynamicColor == false) ...[ SizedBox( width: MediaQuery.of(context).size.width, diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 24bbeae..82a9884 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,7 +5,7 @@ import FlutterMacOS import Foundation -import device_info_plus_macos +import device_info_plus import dynamic_color import package_info_plus import sentry_flutter diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 0075110..bf5412f 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - device_info_plus_macos (0.0.1): + - device_info_plus (0.0.1): - FlutterMacOS - dynamic_color (0.0.2): - FlutterMacOS @@ -40,7 +40,7 @@ PODS: - FlutterMacOS DEPENDENCIES: - - device_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus_macos/macos`) + - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) @@ -58,8 +58,8 @@ SPEC REPOS: - sqlite3 EXTERNAL SOURCES: - device_info_plus_macos: - :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus_macos/macos + device_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos dynamic_color: :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos FlutterMacOS: @@ -78,7 +78,7 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/window_size/macos SPEC CHECKSUMS: - device_info_plus_macos: 1ad388a1ef433505c4038e7dd9605aadd1e2e9c7 + device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a diff --git a/pubspec.lock b/pubspec.lock index 3bb15f5..b1df451 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -133,50 +133,18 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: b809c4ed5f7fcdb325ccc70b80ad934677dc4e2aa414bf46859a42bfdfafcbb6 + sha256: "499c61743e13909c13374a8c209075385858c614b9c0f2487b5f9995eeaf7369" url: "https://pub.dev" source: hosted - version: "4.1.3" - device_info_plus_linux: - dependency: transitive - description: - name: device_info_plus_linux - sha256: "77a8b3c4af06bc46507f89304d9f49dfc64b4ae004b994532ed23b34adeae4b3" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - device_info_plus_macos: - dependency: transitive - description: - name: device_info_plus_macos - sha256: "37961762fbd46d3620c7b69ca606671014db55fc1b7a11e696fd90ed2e8fe03d" - url: "https://pub.dev" - source: hosted - version: "3.0.0" + version: "9.0.1" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - sha256: "83fdba24fcf6846d3b10f10dfdc8b6c6d7ada5f8ed21d62ea2909c2dfa043773" + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 url: "https://pub.dev" source: hosted - version: "3.0.0" - device_info_plus_web: - dependency: transitive - description: - name: device_info_plus_web - sha256: "5890f6094df108181c7a29720bc23d0fd6159f17d82787fac093d1fefcaf6325" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - device_info_plus_windows: - dependency: transitive - description: - name: device_info_plus_windows - sha256: "23a2874af0e23ee6e3a2a0ebcecec3a9da13241f2cb93a93a44c8764df123dd7" - url: "https://pub.dev" - source: hosted - version: "4.1.0" + version: "7.0.0" dynamic_color: dependency: "direct main" description: @@ -450,10 +418,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "10259b111176fba5c505b102e3a5b022b51dd97e30522e906d6922c745584745" + sha256: "28386bbe89ab5a7919a47cea99cdd1128e5a6e0bbd7eaafe20440ead84a15de3" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "4.0.1" package_info_plus_platform_interface: dependency: transitive description: @@ -751,10 +719,18 @@ packages: dependency: transitive description: name: win32 - sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4 + sha256: "6ca3aaab1790eeb1f5cad232e33d9c53ba66e884dd3e7686c4e730bffc45f1a3" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "5.0.2" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: e4506d60b7244251bc59df15656a3093501c37fb5af02105a944d73eb95be4c9 + url: "https://pub.dev" + source: hosted + version: "1.1.1" window_size: dependency: "direct main" description: @@ -781,5 +757,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0-417 <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.4.0-17.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index 0197c6c..5f2b61d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,11 +41,11 @@ dependencies: intl: any provider: ^6.0.3 sqflite: ^2.2.5 - package_info_plus: ^3.1.2 + package_info_plus: ^4.0.1 flutter_displaymode: ^0.6.0 dynamic_color: ^1.6.5 animations: ^2.0.5 - device_info_plus: ^4.1.2 + device_info_plus: ^9.0.1 uuid: ^3.0.6 expandable: ^5.0.1 fl_chart: ^0.62.0 From 645ec6eb0b341a56fdab5371b37a1c1617c24b8b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 21 May 2023 23:21:03 +0200 Subject: [PATCH 142/676] Fixed updater --- lib/base.dart | 3 +- lib/screens/settings/advanced_setings.dart | 146 +++++++++------------ lib/screens/settings/general_settings.dart | 5 +- 3 files changed, 70 insertions(+), 84 deletions(-) diff --git a/lib/base.dart b/lib/base.dart index 932d635..5c6289b 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -49,7 +49,8 @@ class _BaseState extends State with WidgetsBindingObserver { widget.appConfigProvider.setAppUpdatesAvailable(result['body']); if (Platform.isAndroid) { if ( - widget.appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || + widget.appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || + widget.appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || widget.appConfigProvider.installationSource == Source.UNKNOWN ) { return result['body']; diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index ca57de4..2ed0ee4 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -10,6 +10,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/screens/settings/app_logs/app_logs.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class AdvancedSettings extends StatelessWidget { @@ -20,97 +21,80 @@ class AdvancedSettings extends StatelessWidget { final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; - - Future updateSslCheck(bool newStatus) async { - final result = await appConfigProvider.setOverrideSslCheck(newStatus); + + Future updateSettings({ + required bool newStatus, + required Future Function(bool) function + }) async { + final result = await function(newStatus); if (result == true) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.restartAppTakeEffect), - backgroundColor: Colors.green, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.settingsUpdatedSuccessfully, + color: Colors.green ); } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.cannotUpdateSettings), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.cannotUpdateSettings, + color: Colors.red ); } } return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(AppLocalizations.of(context)!.generalSettings), - ) - ) - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverList.list( - children: [ - CustomListTile( - icon: Icons.lock, - title: AppLocalizations.of(context)!.dontCheckCertificate, - subtitle: AppLocalizations.of(context)!.dontCheckCertificateDescription, - trailing: Switch( - value: appConfigProvider.overrideSslCheck, - onChanged: updateSslCheck, - ), - onTap: () => updateSslCheck(!appConfigProvider.overrideSslCheck), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 20, - right: 10 - ) - ), - CustomListTile( - icon: Icons.list_rounded, - title: AppLocalizations.of(context)!.logs, - subtitle: AppLocalizations.of(context)!.checkAppLogs, - onTap: () => { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push(const AppLogs()) - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const AppLogs() - ) - ) - } - }, - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 20, - right: 10 - ) - ), - ], - ) - ], + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.advancedSettings), + ), + body: ListView( + children: [ + CustomListTile( + icon: Icons.lock, + title: AppLocalizations.of(context)!.dontCheckCertificate, + subtitle: AppLocalizations.of(context)!.dontCheckCertificateDescription, + trailing: Switch( + value: appConfigProvider.overrideSslCheck, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setOverrideSslCheck + ), ), - ) - ) + onTap: () => updateSettings( + newStatus: !appConfigProvider.overrideSslCheck, + function: appConfigProvider.setOverrideSslCheck + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 20, + right: 10 + ) + ), + CustomListTile( + icon: Icons.list_rounded, + title: AppLocalizations.of(context)!.logs, + subtitle: AppLocalizations.of(context)!.checkAppLogs, + onTap: () => { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push(const AppLogs()) + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const AppLogs() + ) + ) + } + }, + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 20, + right: 10 + ) + ), + ], ) ); } diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index 178eb40..d237d3c 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -207,9 +207,10 @@ class _GeneralSettingsState extends State { if ( !(Platform.isAndroid || Platform.isIOS) || (Platform.isAndroid && ( - appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE) || + appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || + appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || appConfigProvider.installationSource == Source.UNKNOWN - ) + )) ) ...[ SectionLabel(label: AppLocalizations.of(context)!.application), CustomListTile( From 0271c704a70a9b1946da200d9c37e7ec9583e71d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 12:04:20 +0200 Subject: [PATCH 143/676] Small bugfix --- lib/functions/compare_versions.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index df299b3..b28bf65 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -4,6 +4,7 @@ bool compareVersions({ required String currentVersion, required String newVersion }) { + if (currentVersion == "") return false; try { if (currentVersion.contains('a')) { // alpha return true; @@ -72,6 +73,7 @@ bool serverVersionIsAhead({ required String referenceVersion, String? referenceVersionBeta }) { + if (currentVersion == "") return false; try { final current = currentVersion.replaceAll('v', ''); final reference = referenceVersion.replaceAll('v', ''); From 4a2d78e8cfb1c59c146be30e5a59b0a7bb5b7321 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 13:51:22 +0200 Subject: [PATCH 144/676] Extracted server status stuff to a separate provider --- lib/functions/block_unblock_domain.dart | 6 +- lib/main.dart | 110 ++++++--- lib/models/server_status.dart | 13 +- lib/providers/clients_provider.dart | 13 + lib/providers/filters_provider.dart | 13 + lib/providers/logs_provider.dart | 11 +- lib/providers/servers_provider.dart | 227 ++++-------------- lib/providers/status_provider.dart | 194 +++++++++++++++ lib/screens/clients/added_list.dart | 10 +- lib/screens/clients/client_screen.dart | 6 +- lib/screens/clients/fab.dart | 8 +- lib/screens/clients/search_clients.dart | 10 +- lib/screens/filters/filters.dart | 8 +- lib/screens/home/appbar.dart | 13 +- lib/screens/home/combined_chart.dart | 58 ++--- lib/screens/home/fab.dart | 7 +- lib/screens/home/home.dart | 51 ++-- lib/screens/home/management_modal.dart | 62 ++--- lib/screens/home/server_status.dart | 6 +- lib/screens/home/top_items.dart | 14 +- lib/screens/logs/logs.dart | 8 +- .../settings/safe_search_settings.dart | 49 ++-- lib/screens/settings/settings.dart | 10 +- lib/screens/top_items/top_items.dart | 8 +- lib/screens/top_items/top_items_modal.dart | 6 +- lib/services/http_requests.dart | 2 +- lib/widgets/add_server_modal.dart | 13 +- lib/widgets/domain_options.dart | 6 +- .../servers_list/servers_list_item.dart | 23 +- .../servers_list/servers_tile_item.dart | 25 +- 30 files changed, 585 insertions(+), 405 deletions(-) create mode 100644 lib/providers/clients_provider.dart create mode 100644 lib/providers/filters_provider.dart create mode 100644 lib/providers/status_provider.dart diff --git a/lib/functions/block_unblock_domain.dart b/lib/functions/block_unblock_domain.dart index cc2c8ed..5b92659 100644 --- a/lib/functions/block_unblock_domain.dart +++ b/lib/functions/block_unblock_domain.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -12,6 +13,7 @@ import 'package:adguard_home_manager/services/http_requests.dart'; Future> blockUnblock(BuildContext context, String domain, String newStatus) async { final serversProvider = Provider.of(context, listen: false); + final statusProvider = Provider.of(context, listen: false); final appConfigProvider = Provider.of(context, listen: false); final ProcessModal processModal = ProcessModal(context: context); @@ -20,7 +22,7 @@ Future> blockUnblock(BuildContext context, String domain, S final rules = await getFilteringRules(server: serversProvider.selectedServer!); if (rules['result'] == 'success') { - FilteringStatus oldStatus = serversProvider.serverStatus.data!.filteringStatus; + FilteringStatus oldStatus = statusProvider.serverStatus!.filteringStatus; List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); if (newStatus == 'block') { newRules.add("||$domain^"); @@ -28,7 +30,7 @@ Future> blockUnblock(BuildContext context, String domain, S else if (newStatus == 'unblock') { newRules.add("@@||$domain^"); } - FilteringStatus newObj = serversProvider.serverStatus.data!.filteringStatus; + FilteringStatus newObj = statusProvider.serverStatus!.filteringStatus; newObj.userRules = newRules; serversProvider.setFilteringStatus(newObj); diff --git a/lib/main.dart b/lib/main.dart index e768f7d..388aff6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,14 +17,18 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/base.dart'; -import 'package:adguard_home_manager/classes/http_override.dart'; -import 'package:adguard_home_manager/services/db/database.dart'; -import 'package:adguard_home_manager/constants/colors.dart'; -import 'package:adguard_home_manager/config/globals.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/config/theme.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; +import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/colors.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/config/globals.dart'; +import 'package:adguard_home_manager/config/theme.dart'; +import 'package:adguard_home_manager/classes/http_override.dart'; +import 'package:adguard_home_manager/services/db/database.dart'; void main() async { @@ -43,6 +47,9 @@ void main() async { AppConfigProvider appConfigProvider = AppConfigProvider(); ServersProvider serversProvider = ServersProvider(); + StatusProvider statusProvider = StatusProvider(); + ClientsProvider clientsProvider = ClientsProvider(); + FiltersProvider filtersProvider = FiltersProvider(); LogsProvider logsProvider = LogsProvider(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); @@ -68,11 +75,68 @@ void main() async { serversProvider.setDbInstance(dbData['dbInstance']); appConfigProvider.saveFromDb(dbData['dbInstance'], dbData['appConfig']); - serversProvider.saveFromDb(dbData['servers']); + final result = await serversProvider.saveFromDb(dbData['servers']); + if (result != null) { + if (result['success'] == true) { + statusProvider.setServerStatusData( + data: result['serverData'], + ); + statusProvider.setServerStatusLoad(LoadStatus.loaded); + } + else { + statusProvider.setServerStatusLoad(LoadStatus.error); + } + } PackageInfo appInfo = await PackageInfo.fromPlatform(); appConfigProvider.setAppInfo(appInfo); + void startApp() => runApp( + MultiProvider( + providers: [ + ChangeNotifierProvider( + create: ((context) => serversProvider) + ), + ChangeNotifierProvider( + create: ((context) => statusProvider) + ), + ChangeNotifierProvider( + create: ((context) => clientsProvider) + ), + ChangeNotifierProvider( + create: ((context) => logsProvider) + ), + ChangeNotifierProvider( + create: ((context) => filtersProvider) + ), + ChangeNotifierProvider( + create: ((context) => appConfigProvider) + ), + ChangeNotifierProxyProvider( + create: (context) => serversProvider, + update: (context, status, servers) => servers!..update(status), + ), + ChangeNotifierProxyProvider( + create: (context) => statusProvider, + update: (context, servers, status) => status!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => clientsProvider, + update: (context, servers, clients) => clients!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => logsProvider, + update: (context, servers, logs) => logs!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => filtersProvider, + update: (context, servers, filters) => filters!..update(servers), + ), + ], + child: const Main(), + ) + ); + if ( ( kReleaseMode && @@ -87,41 +151,11 @@ void main() async { options.dsn = dotenv.env['SENTRY_DSN']; options.sendDefaultPii = false; }, - appRunner: () => runApp( - MultiProvider( - providers: [ - ChangeNotifierProvider( - create: ((context) => serversProvider) - ), - ChangeNotifierProvider( - create: ((context) => appConfigProvider) - ), - ChangeNotifierProvider( - create: ((context) => logsProvider) - ), - ], - child: const Main(), - ) - ) + appRunner: () => startApp() ); } else { - runApp( - MultiProvider( - providers: [ - ChangeNotifierProvider( - create: ((context) => serversProvider) - ), - ChangeNotifierProvider( - create: ((context) => appConfigProvider) - ), - ChangeNotifierProvider( - create: ((context) => logsProvider) - ), - ], - child: const Main(), - ) - ); + startApp(); } } diff --git a/lib/models/server_status.dart b/lib/models/server_status.dart index 3d68399..b43dbd1 100644 --- a/lib/models/server_status.dart +++ b/lib/models/server_status.dart @@ -4,15 +4,6 @@ import 'package:adguard_home_manager/models/dns_statistics.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; class ServerStatus { - int loadStatus; - ServerStatusData? data; - - ServerStatus({ - required this.loadStatus, - this.data - }); -} -class ServerStatusData { final DnsStatistics stats; final List clients; final FilteringStatus filteringStatus; @@ -31,7 +22,7 @@ class ServerStatusData { bool? safeSearchYandex; bool? safeSearchYoutube; - ServerStatusData({ + ServerStatus({ required this.stats, required this.clients, required this.filteringStatus, @@ -51,7 +42,7 @@ class ServerStatusData { required this.safeSearchYoutube }); - factory ServerStatusData.fromJson(Map json) => ServerStatusData( + factory ServerStatus.fromJson(Map json) => ServerStatus( stats: DnsStatistics.fromJson(json['stats']), clients: json["clients"] != null ? List.from(json["clients"].map((x) => Client.fromJson(x))) : [], generalEnabled: json['status']['protection_enabled'], diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart new file mode 100644 index 0000000..3d7e0ae --- /dev/null +++ b/lib/providers/clients_provider.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class ClientsProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? serversProvider) { + if (serversProvider != null) { + _serversProvider = serversProvider; + } + } +} \ No newline at end of file diff --git a/lib/providers/filters_provider.dart b/lib/providers/filters_provider.dart new file mode 100644 index 0000000..bb82913 --- /dev/null +++ b/lib/providers/filters_provider.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class FiltersProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? serversProvider) { + if (serversProvider != null) { + _serversProvider = serversProvider; + } + } +} \ No newline at end of file diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index db2619c..fdae694 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -1,10 +1,19 @@ -import 'package:adguard_home_manager/models/clients.dart'; import 'package:flutter/material.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/logs.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; class LogsProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? serversProvider) { + if (serversProvider != null) { + _serversProvider = serversProvider; + } + } + int _loadStatus = 0; LogsData? _logsData; List? _clients; diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 6d8500c..decbb0a 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -9,26 +9,29 @@ import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/services/db/queries.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; class ServersProvider with ChangeNotifier { + StatusProvider? _statusProvider; + + update(StatusProvider? statusProvider) { + if (statusProvider != null) { + _statusProvider = statusProvider; + } + } + Database? _dbInstance; List _serversList = []; Server? _selectedServer; - final ServerStatus _serverStatus = ServerStatus( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error - data: null - ); // serverStatus != null means server is connected - List _protectionsManagementProcess = []; // protections that are currenty being enabled or disabled + String? _serverVersion; final Clients _clients = Clients( loadStatus: LoadStatus.loading, @@ -78,14 +81,6 @@ class ServersProvider with ChangeNotifier { return _selectedServer; } - ServerStatus get serverStatus { - return _serverStatus; - } - - List get protectionsManagementProcess { - return _protectionsManagementProcess; - } - Clients get clients { return _clients; } @@ -144,16 +139,6 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setServerStatusData(ServerStatusData data) { - _serverStatus.data = data; - notifyListeners(); - } - - void setServerStatusLoad(int status) { - _serverStatus.loadStatus = status; - notifyListeners(); - } - void setClientsLoadStatus(LoadStatus status, bool notify) { _clients.loadStatus = status; if (notify == true) { @@ -226,7 +211,7 @@ class ServersProvider with ChangeNotifier { } void setFilteringProtectionStatus(bool status) { - _serverStatus.data!.filteringEnabled = status; + _statusProvider!.setFilteringStatus(status); _filtering.data!.enabled = status; notifyListeners(); } @@ -382,149 +367,6 @@ class ServersProvider with ChangeNotifier { } } - Future updateBlocking({ - required Server server, - required String block, - required bool newStatus, - int? time - }) async { - switch (block) { - case 'general': - _protectionsManagementProcess.add('general'); - notifyListeners(); - - final result = await updateGeneralProtection( - server: server, - enable: newStatus, - time: time - ); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.generalEnabled = newStatus; - if (time != null) { - _serverStatus.data!.timeGeneralDisabled = time; - _serverStatus.data!.disabledUntil = generateTimeDeadline(time); - } - else { - _serverStatus.data!.timeGeneralDisabled = 0; - _serverStatus.data!.disabledUntil = null; - } - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - case 'general_legacy': - _protectionsManagementProcess.add('general'); - notifyListeners(); - - final result = await updateGeneralProtectionLegacy(server, newStatus); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.generalEnabled = newStatus; - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - - case 'filtering': - _protectionsManagementProcess.add('filtering'); - notifyListeners(); - - final result = await updateFiltering( - server: server, - enable: newStatus, - ); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'filtering').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.filteringEnabled = newStatus; - notifyListeners(); - return null; - } - else { - - notifyListeners(); - return result['log']; - } - - case 'safeSearch': - _protectionsManagementProcess.add('safeSearch'); - notifyListeners(); - - final result = serverVersionIsAhead( - currentVersion: serverStatus.data!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? await updateSafeSearchSettings(server: server, body: { 'enabled': newStatus }) - : await updateSafeSearchLegacy(server, newStatus); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeSearch').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.safeSearchEnabled = newStatus; - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - case 'safeBrowsing': - _protectionsManagementProcess.add('safeBrowsing'); - notifyListeners(); - - final result = await updateSafeBrowsing(server, newStatus); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeBrowsing').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.safeBrowsingEnabled = newStatus; - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - case 'parentalControl': - _protectionsManagementProcess.add('parentalControl'); - notifyListeners(); - - final result = await updateParentalControl(server, newStatus); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'parentalControl').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.parentalControlEnabled = newStatus; - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - default: - return false; - } - } - void checkServerUpdatesAvailable(Server server) async { setUpdateAvailableLoadStatus(LoadStatus.loading, true); final result = await checkServerUpdates(server: server); @@ -556,8 +398,26 @@ class ServersProvider with ChangeNotifier { } } - void saveFromDb(List>? data) async { + Future> initializateServer(Server server) async { + _selectedServer = server; + final serverStatus = await getServerStatus(server); + if (serverStatus['result'] == 'success') { + checkServerUpdatesAvailable(server); // Do not await + return { + "success": true, + "serverData": serverStatus['data'] + }; + } + else { + return { + "success": false + }; + } + } + + Future?> saveFromDb(List>? data) async { if (data != null) { + Server? defaultServer; for (var server in data) { final Server serverObj = Server( id: server['id'], @@ -574,20 +434,23 @@ class ServersProvider with ChangeNotifier { ); _serversList.add(serverObj); if (convertFromIntToBool(server['defaultServer']) == true) { - _selectedServer = serverObj; - _serverStatus.loadStatus = 0; - final serverStatus = await getServerStatus(serverObj); - if (serverStatus['result'] == 'success') { - _serverStatus.data = serverStatus['data']; - _serverStatus.loadStatus = 1; - checkServerUpdatesAvailable(serverObj); // Do not await - } - else { - _serverStatus.loadStatus = 2; - } + defaultServer = serverObj; } } + + notifyListeners(); + + if (defaultServer != null) { + final result = await initializateServer(defaultServer); + return result; + } + else { + return null; + } + } + else { + notifyListeners(); + return null; } - notifyListeners(); } } \ No newline at end of file diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart new file mode 100644 index 0000000..26bdfe2 --- /dev/null +++ b/lib/providers/status_provider.dart @@ -0,0 +1,194 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/functions/time_server_disabled.dart'; +import 'package:adguard_home_manager/models/server.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; + +class StatusProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? serversProvider) { + if (serversProvider != null) { + _serversProvider = serversProvider; + } + } + + LoadStatus _loadStatus = LoadStatus.loading; + ServerStatus? _serverStatus; // serverStatus != null means server is connected + List _protectionsManagementProcess = []; // protections that are currenty being enabled or disabled + + LoadStatus get loadStatus { + return _loadStatus; + } + + ServerStatus? get serverStatus { + return _serverStatus; + } + + List get protectionsManagementProcess { + return _protectionsManagementProcess; + } + + void setServerStatusData({ + required ServerStatus data, + }) { + _serverStatus = data; + notifyListeners(); + } + + void setServerStatusLoad(LoadStatus status) { + _loadStatus = status; + notifyListeners(); + } + + Future updateBlocking({ + required Server server, + required String block, + required bool newStatus, + int? time + }) async { + switch (block) { + case 'general': + _protectionsManagementProcess.add('general'); + notifyListeners(); + + final result = await updateGeneralProtection( + server: server, + enable: newStatus, + time: time + ); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); + + if (result['result'] == 'success') { + _serverStatus!.generalEnabled = newStatus; + if (time != null) { + _serverStatus!.timeGeneralDisabled = time; + _serverStatus!.disabledUntil = generateTimeDeadline(time); + } + else { + _serverStatus!.timeGeneralDisabled = 0; + _serverStatus!.disabledUntil = null; + } + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + case 'general_legacy': + _protectionsManagementProcess.add('general'); + notifyListeners(); + + final result = await updateGeneralProtectionLegacy(server, newStatus); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); + + if (result['result'] == 'success') { + _serverStatus!.generalEnabled = newStatus; + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + + case 'filtering': + _protectionsManagementProcess.add('filtering'); + notifyListeners(); + + final result = await updateFiltering( + server: server, + enable: newStatus, + ); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'filtering').toList(); + + if (result['result'] == 'success') { + _serverStatus!.filteringEnabled = newStatus; + notifyListeners(); + return null; + } + else { + + notifyListeners(); + return result['log']; + } + + case 'safeSearch': + _protectionsManagementProcess.add('safeSearch'); + notifyListeners(); + + final result = serverVersionIsAhead( + currentVersion: serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? await updateSafeSearchSettings(server: server, body: { 'enabled': newStatus }) + : await updateSafeSearchLegacy(server, newStatus); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeSearch').toList(); + + if (result['result'] == 'success') { + _serverStatus!.safeSearchEnabled = newStatus; + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + case 'safeBrowsing': + _protectionsManagementProcess.add('safeBrowsing'); + notifyListeners(); + + final result = await updateSafeBrowsing(server, newStatus); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeBrowsing').toList(); + + if (result['result'] == 'success') { + _serverStatus!.safeBrowsingEnabled = newStatus; + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + case 'parentalControl': + _protectionsManagementProcess.add('parentalControl'); + notifyListeners(); + + final result = await updateParentalControl(server, newStatus); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'parentalControl').toList(); + + if (result['result'] == 'success') { + _serverStatus!.parentalControlEnabled = newStatus; + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + default: + return false; + } + } + + void setFilteringStatus(bool status) { + _serverStatus!.filteringEnabled = status; + } +} \ No newline at end of file diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 43f3a44..cc535db 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -18,6 +18,7 @@ import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/maps_fns.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -77,6 +78,7 @@ class _AddedListState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -88,7 +90,7 @@ class _AddedListState extends State { final result = await postUpdateClient(server: serversProvider.selectedServer!, data: { 'name': client.name, 'data': serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == false @@ -168,7 +170,7 @@ class _AddedListState extends State { context: context, builder: (BuildContext context) => ClientScreen( onConfirm: confirmEditClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, onDelete: deleteClient, client: client, dialog: true, @@ -180,7 +182,7 @@ class _AddedListState extends State { fullscreenDialog: true, builder: (BuildContext context) => ClientScreen( onConfirm: confirmEditClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, onDelete: deleteClient, client: client, dialog: false, @@ -240,7 +242,7 @@ class _AddedListState extends State { onLongPress: openOptionsModal, onEdit: openClientModal, splitView: widget.splitView, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, ), noData: SizedBox( width: double.maxFinite, diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart index 2e282f5..52bf1c1 100644 --- a/lib/screens/clients/client_screen.dart +++ b/lib/screens/clients/client_screen.dart @@ -11,6 +11,7 @@ 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'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; @@ -131,6 +132,7 @@ class _ClientScreenState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); void createClient() { final Client client = Client( @@ -506,7 +508,7 @@ class _ClientScreenState extends State { ), if ( serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true @@ -531,7 +533,7 @@ class _ClientScreenState extends State { ), if ( serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == false diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 3c05c7e..a92a1d0 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -14,6 +14,7 @@ import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/functions/maps_fns.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -24,6 +25,7 @@ class ClientsFab extends StatelessWidget { Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final statusProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -34,7 +36,7 @@ class ClientsFab extends StatelessWidget { final result = await postAddClient( server: serversProvider.selectedServer!, data: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == false @@ -73,7 +75,7 @@ class ClientsFab extends StatelessWidget { context: context, builder: (BuildContext context) => ClientScreen( onConfirm: confirmAddClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, dialog: true, ) ); @@ -83,7 +85,7 @@ class ClientsFab extends StatelessWidget { fullscreenDialog: true, builder: (BuildContext context) => ClientScreen( onConfirm: confirmAddClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, dialog: false, ) )); diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index c9e72d8..7f2c3df 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -11,6 +11,7 @@ import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/client_screen.dart'; import 'package:adguard_home_manager/screens/clients/options_modal.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/services/http_requests.dart'; @@ -19,7 +20,7 @@ import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/widgets/section_label.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class SearchClients extends StatelessWidget { @@ -99,6 +100,7 @@ class _SearchClientsWidgetState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -189,7 +191,7 @@ class _SearchClientsWidgetState extends State { context: context, builder: (BuildContext context) => ClientScreen( onConfirm: confirmEditClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, onDelete: deleteClient, client: client, dialog: true, @@ -201,7 +203,7 @@ class _SearchClientsWidgetState extends State { fullscreenDialog: true, builder: (BuildContext context) => ClientScreen( onConfirm: confirmEditClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, onDelete: deleteClient, client: client, dialog: false, @@ -356,7 +358,7 @@ class _SearchClientsWidgetState extends State { Icons.search_rounded, size: 19, color: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index ce7e858..4107f1e 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -15,6 +15,7 @@ import 'package:adguard_home_manager/screens/filters/blocked_services_screen.dar import 'package:adguard_home_manager/screens/filters/update_interval_lists_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; @@ -83,6 +84,7 @@ class _FiltersWidgetState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -158,20 +160,20 @@ class _FiltersWidgetState extends State { void enableDisableFiltering() async { ProcessModal processModal = ProcessModal(context: context); processModal.open( - serversProvider.serverStatus.data!.filteringEnabled == true + statusProvider.serverStatus!.filteringEnabled == true ? AppLocalizations.of(context)!.disableFiltering : AppLocalizations.of(context)!.enableFiltering ); final result = await updateFiltering( server: serversProvider.selectedServer!, - enable: !serversProvider.serverStatus.data!.filteringEnabled + enable: !statusProvider.serverStatus!.filteringEnabled ); processModal.close(); if (result['result'] == 'success') { - serversProvider.setFilteringProtectionStatus(!serversProvider.serverStatus.data!.filteringEnabled); + serversProvider.setFilteringProtectionStatus(!statusProvider.serverStatus!.filteringEnabled); showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 58284d5..1ae88e1 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -4,6 +4,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/servers/servers.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -20,6 +22,7 @@ class HomeAppBar extends StatelessWidget { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final Server? server = serversProvider.selectedServer; @@ -38,14 +41,14 @@ class HomeAppBar extends StatelessWidget { centerTitle: false, forceElevated: innerBoxScrolled, leading: Icon( - serversProvider.selectedServer != null && serversProvider.serverStatus.data != null - ? serversProvider.serverStatus.data!.generalEnabled == true + serversProvider.selectedServer != null && statusProvider.serverStatus != null + ? statusProvider.serverStatus!.generalEnabled == true ? Icons.gpp_good_rounded : Icons.gpp_bad_rounded : Icons.shield, size: 30, - color: serversProvider.selectedServer != null && serversProvider.serverStatus.data != null - ? serversProvider.serverStatus.data!.generalEnabled == true + color: serversProvider.selectedServer != null && statusProvider.serverStatus != null + ? statusProvider.serverStatus!.generalEnabled == true ? appConfigProvider.useThemeColorForStatus ? Theme.of(context).colorScheme.primary : Colors.green @@ -95,7 +98,7 @@ class HomeAppBar extends StatelessWidget { ], ), ), - if (serversProvider.selectedServer != null && serversProvider.serverStatus.loadStatus == 1) PopupMenuItem( + if (serversProvider.selectedServer != null && statusProvider.loadStatus == LoadStatus.loaded) PopupMenuItem( onTap: () => openUrl("${server!.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}"), child: Row( children: [ diff --git a/lib/screens/home/combined_chart.dart b/lib/screens/home/combined_chart.dart index 9bd9d36..3de92f9 100644 --- a/lib/screens/home/combined_chart.dart +++ b/lib/screens/home/combined_chart.dart @@ -7,7 +7,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/combined_line_chart.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class CombinedChartData { @@ -51,56 +51,56 @@ class CombinedHomeChart extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; - if (serversProvider.serverStatus.data != null) { + if (statusProvider.serverStatus != null) { final data = CombinedChartData( totalQueries: CombinedChartItem( label: AppLocalizations.of(context)!.dnsQueries, color: Colors.blue, - data: serversProvider.serverStatus.data!.stats.dnsQueries + data: statusProvider.serverStatus!.stats.dnsQueries ), blockedFilters: appConfigProvider.hideZeroValues == true - ? removeZero(serversProvider.serverStatus.data!.stats.blockedFiltering) != null + ? removeZero(statusProvider.serverStatus!.stats.blockedFiltering) != null ? CombinedChartItem( label: AppLocalizations.of(context)!.blockedFilters, color: Colors.red, - data: serversProvider.serverStatus.data!.stats.blockedFiltering + data: statusProvider.serverStatus!.stats.blockedFiltering ) : null : CombinedChartItem( label: AppLocalizations.of(context)!.blockedFilters, color: Colors.red, - data: serversProvider.serverStatus.data!.stats.blockedFiltering + data: statusProvider.serverStatus!.stats.blockedFiltering ) , replacedSafeBrowsing: appConfigProvider.hideZeroValues == true - ? removeZero(serversProvider.serverStatus.data!.stats.replacedSafebrowsing) != null + ? removeZero(statusProvider.serverStatus!.stats.replacedSafebrowsing) != null ? CombinedChartItem( label: AppLocalizations.of(context)!.malwarePhisingBlocked, color: Colors.green, - data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing + data: statusProvider.serverStatus!.stats.replacedSafebrowsing ) : null : CombinedChartItem( label: AppLocalizations.of(context)!.malwarePhisingBlocked, color: Colors.green, - data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing + data: statusProvider.serverStatus!.stats.replacedSafebrowsing ) , replacedParental: appConfigProvider.hideZeroValues == true - ? removeZero(serversProvider.serverStatus.data!.stats.replacedParental) != null + ? removeZero(statusProvider.serverStatus!.stats.replacedParental) != null ? CombinedChartItem( label: AppLocalizations.of(context)!.blockedAdultWebsites, color: Colors.orange, - data: serversProvider.serverStatus.data!.stats.replacedParental + data: statusProvider.serverStatus!.stats.replacedParental ) : null : CombinedChartItem( label: AppLocalizations.of(context)!.blockedAdultWebsites, color: Colors.orange, - data: serversProvider.serverStatus.data!.stats.replacedParental + data: statusProvider.serverStatus!.stats.replacedParental ) , ); @@ -184,29 +184,29 @@ class CombinedHomeChart extends StatelessWidget { legend( label: data.totalQueries.label, color: data.totalQueries.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), - secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", ), const SizedBox(height: 16), if (data.blockedFilters != null) legend( label: data.blockedFilters!.label, color: data.blockedFilters!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), if (data.replacedSafeBrowsing != null) legend( label: data.replacedSafeBrowsing!.label, color: data.replacedSafeBrowsing!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), if (data.replacedParental != null) legend( label: data.replacedParental!.label, color: data.replacedParental!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), ], ), @@ -247,29 +247,29 @@ class CombinedHomeChart extends StatelessWidget { legend( label: data.totalQueries.label, color: data.totalQueries.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), - secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", ), const SizedBox(height: 16), if (data.blockedFilters != null) legend( label: data.blockedFilters!.label, color: data.blockedFilters!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), if (data.replacedSafeBrowsing != null) legend( label: data.replacedSafeBrowsing!.label, color: data.replacedSafeBrowsing!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), if (data.replacedParental != null) legend( label: data.replacedParental!.label, color: data.replacedParental!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), ], diff --git a/lib/screens/home/fab.dart b/lib/screens/home/fab.dart index 1369535..0e7db97 100644 --- a/lib/screens/home/fab.dart +++ b/lib/screens/home/fab.dart @@ -3,14 +3,15 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/screens/home/management_modal.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; class HomeFab extends StatelessWidget { const HomeFab({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -35,7 +36,7 @@ class HomeFab extends StatelessWidget { } } - return serversProvider.serverStatus.loadStatus == 1 + return statusProvider.loadStatus == LoadStatus.loaded ? FloatingActionButton( onPressed: openManagementBottomSheet, child: const Icon(Icons.shield_rounded), diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 9626130..31912e9 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -15,6 +15,8 @@ import 'package:adguard_home_manager/screens/home/top_items.dart'; import 'package:adguard_home_manager/screens/home/chart.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -55,6 +57,7 @@ class _HomeState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -109,7 +112,7 @@ class _HomeState extends State { List listItems() { return [ - ServerStatus(serverStatus: serversProvider.serverStatus.data!), + ServerStatusWidget(serverStatus: statusProvider.serverStatus!), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Divider( @@ -124,40 +127,40 @@ class _HomeState extends State { FractionallySizedBox( widthFactor: width > 700 ? 0.5 : 1, child: HomeChart( - data: serversProvider.serverStatus.data!.stats.dnsQueries, + data: statusProvider.serverStatus!.stats.dnsQueries, label: AppLocalizations.of(context)!.dnsQueries, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), - secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", color: Colors.blue, ), ), FractionallySizedBox( widthFactor: width > 700 ? 0.5 : 1, child: HomeChart( - data: serversProvider.serverStatus.data!.stats.blockedFiltering, + data: statusProvider.serverStatus!.stats.blockedFiltering, label: AppLocalizations.of(context)!.blockedFilters, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.red, ), ), FractionallySizedBox( widthFactor: width > 700 ? 0.5 : 1, child: HomeChart( - data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing, + data: statusProvider.serverStatus!.stats.replacedSafebrowsing, label: AppLocalizations.of(context)!.malwarePhisingBlocked, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.green, ), ), FractionallySizedBox( widthFactor: width > 700 ? 0.5 : 1, child: HomeChart( - data: serversProvider.serverStatus.data!.stats.replacedParental, + data: statusProvider.serverStatus!.stats.replacedParental, label: AppLocalizations.of(context)!.blockedAdultWebsites, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.orange, ), ), @@ -172,7 +175,7 @@ class _HomeState extends State { if (width <= 700) ...[ TopItems( label: AppLocalizations.of(context)!.topQueriedDomains, - data: serversProvider.serverStatus.data!.stats.topQueriedDomains, + data: statusProvider.serverStatus!.stats.topQueriedDomains, type: 'topQueriedDomains', ), Padding( @@ -187,7 +190,7 @@ class _HomeState extends State { TopItems( label: AppLocalizations.of(context)!.topBlockedDomains, - data: serversProvider.serverStatus.data!.stats.topBlockedDomains, + data: statusProvider.serverStatus!.stats.topBlockedDomains, type: 'topBlockedDomains', ), Padding( @@ -201,7 +204,7 @@ class _HomeState extends State { TopItems( label: AppLocalizations.of(context)!.topClients, - data: serversProvider.serverStatus.data!.stats.topClients, + data: statusProvider.serverStatus!.stats.topClients, type: 'topClients', clients: true, ), @@ -219,7 +222,7 @@ class _HomeState extends State { ), child: TopItems( label: AppLocalizations.of(context)!.topQueriedDomains, - data: serversProvider.serverStatus.data!.stats.topQueriedDomains, + data: statusProvider.serverStatus!.stats.topQueriedDomains, type: 'topQueriedDomains', ), ), @@ -232,7 +235,7 @@ class _HomeState extends State { ), child: TopItems( label: AppLocalizations.of(context)!.topBlockedDomains, - data: serversProvider.serverStatus.data!.stats.topBlockedDomains, + data: statusProvider.serverStatus!.stats.topBlockedDomains, type: 'topBlockedDomains', ), ), @@ -245,7 +248,7 @@ class _HomeState extends State { ), child: TopItems( label: AppLocalizations.of(context)!.topClients, - data: serversProvider.serverStatus.data!.stats.topClients, + data: statusProvider.serverStatus!.stats.topClients, type: 'topClients', ), ), @@ -279,7 +282,9 @@ class _HomeState extends State { onRefresh: () async { final result = await getServerStatus(serversProvider.selectedServer!); if (result['result'] == 'success') { - serversProvider.setServerStatusData(result['data']); + statusProvider.setServerStatusData( + data: result['data'] + ); } else { appConfigProvider.addLog(result['log']); @@ -295,13 +300,13 @@ class _HomeState extends State { SliverOverlapInjector( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), - if (serversProvider.serverStatus.loadStatus == 0) SliverFillRemaining( + if (statusProvider.loadStatus == LoadStatus.loading) SliverFillRemaining( child: loading(), ), - if (serversProvider.serverStatus.loadStatus == 1) SliverList.list( + if (statusProvider.loadStatus == LoadStatus.loaded) SliverList.list( children: listItems() ), - if (serversProvider.serverStatus.loadStatus == 2) SliverFillRemaining( + if (statusProvider.loadStatus == LoadStatus.error) SliverFillRemaining( child: loadError(), ), ], diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 9781206..5329d3c 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -10,6 +10,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -74,6 +75,7 @@ class _ManagementModalState extends State with SingleTickerProv @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void startTimer(DateTime deadline) { @@ -92,7 +94,9 @@ class _ManagementModalState extends State with SingleTickerProv }); final result = await getServerStatus(serversProvider.selectedServer!); if (result['result'] == 'success') { - serversProvider.setServerStatusData(result['data']); + statusProvider.setServerStatusData( + data: result['data'] + ); } } else { setState(() { @@ -104,16 +108,16 @@ class _ManagementModalState extends State with SingleTickerProv } if ( - serversProvider.serverStatus.data != null && - serversProvider.serverStatus.data!.disabledUntil != null && - serversProvider.serverStatus.data!.disabledUntil != currentDeadline + statusProvider.serverStatus != null && + statusProvider.serverStatus!.disabledUntil != null && + statusProvider.serverStatus!.disabledUntil != currentDeadline ) { - startTimer(serversProvider.serverStatus.data!.disabledUntil!); + startTimer(statusProvider.serverStatus!.disabledUntil!); } if ( - serversProvider.serverStatus.data != null && - serversProvider.serverStatus.data!.generalEnabled == true + statusProvider.serverStatus != null && + statusProvider.serverStatus!.generalEnabled == true ) { setState(() { start = 0; @@ -128,7 +132,7 @@ class _ManagementModalState extends State with SingleTickerProv required String filter, int? time }) async { - final result = await serversProvider.updateBlocking( + final result = await statusProvider.updateBlocking( server: serversProvider.selectedServer!, block: filter, newStatus: value, @@ -164,7 +168,7 @@ class _ManagementModalState extends State with SingleTickerProv child: Icon( Icons.keyboard_arrow_down_rounded, size: 26, - color: serversProvider.serverStatus.data!.generalEnabled == true + color: statusProvider.serverStatus!.generalEnabled == true ? Theme.of(context).colorScheme.onSurfaceVariant : Colors.grey, ), @@ -180,7 +184,7 @@ class _ManagementModalState extends State with SingleTickerProv fontSize: 18, ), ), - if (serversProvider.serverStatus.data!.timeGeneralDisabled > 0) ...[ + if (statusProvider.serverStatus!.timeGeneralDisabled > 0) ...[ const SizedBox(height: 2), if (currentDeadline != null) Text( "${AppLocalizations.of(context)!.remainingTime}: ${generateRemainingTimeString(currentDeadline!.difference(DateTime.now()))}" @@ -191,8 +195,8 @@ class _ManagementModalState extends State with SingleTickerProv ], ), Switch( - value: serversProvider.serverStatus.data!.generalEnabled, - onChanged: serversProvider.protectionsManagementProcess.contains('general') == false + value: statusProvider.serverStatus!.generalEnabled, + onChanged: statusProvider.protectionsManagementProcess.contains('general') == false ? (value) { if (value == false && expandableController.expanded == true && legacyMode == false) { expandableController.toggle(); @@ -216,35 +220,35 @@ class _ManagementModalState extends State with SingleTickerProv children: [ ActionChip( label: Text(AppLocalizations.of(context)!.seconds(30)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(29000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.minute(1)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(59000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.minutes(10)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(599000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.hour(1)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(3599000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.hours(24)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(86399000) : null, ), @@ -256,7 +260,7 @@ class _ManagementModalState extends State with SingleTickerProv return Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true @@ -266,7 +270,7 @@ class _ManagementModalState extends State with SingleTickerProv color: Colors.transparent, borderRadius: BorderRadius.circular(28), child: InkWell( - onTap: serversProvider.serverStatus.data!.generalEnabled == true && !serversProvider.protectionsManagementProcess.contains('general') + onTap: statusProvider.serverStatus!.generalEnabled == true && !statusProvider.protectionsManagementProcess.contains('general') ? () => expandableController.toggle() : null, borderRadius: BorderRadius.circular(28), @@ -301,9 +305,9 @@ class _ManagementModalState extends State with SingleTickerProv color: Colors.transparent, borderRadius: BorderRadius.circular(28), child: InkWell( - onTap: serversProvider.protectionsManagementProcess.contains('general') == false + onTap: statusProvider.protectionsManagementProcess.contains('general') == false ? () => updateBlocking( - value: !serversProvider.serverStatus.data!.generalEnabled, + value: !statusProvider.serverStatus!.generalEnabled, filter: 'general_legacy' ) : null, borderRadius: BorderRadius.circular(28), @@ -408,30 +412,30 @@ class _ManagementModalState extends State with SingleTickerProv smallSwitch( AppLocalizations.of(context)!.ruleFiltering, Icons.filter_list_rounded, - serversProvider.serverStatus.data!.filteringEnabled, + statusProvider.serverStatus!.filteringEnabled, (value) => updateBlocking(value: value, filter: 'filtering'), - serversProvider.protectionsManagementProcess.contains('filtering') + statusProvider.protectionsManagementProcess.contains('filtering') ), smallSwitch( AppLocalizations.of(context)!.safeBrowsing, Icons.vpn_lock_rounded, - serversProvider.serverStatus.data!.safeBrowsingEnabled, + statusProvider.serverStatus!.safeBrowsingEnabled, (value) => updateBlocking(value: value, filter: 'safeBrowsing'), - serversProvider.protectionsManagementProcess.contains('safeBrowsing') + statusProvider.protectionsManagementProcess.contains('safeBrowsing') ), smallSwitch( AppLocalizations.of(context)!.parentalFiltering, Icons.block, - serversProvider.serverStatus.data!.parentalControlEnabled, + statusProvider.serverStatus!.parentalControlEnabled, (value) => updateBlocking(value: value, filter: 'parentalControl'), - serversProvider.protectionsManagementProcess.contains('parentalControl') + statusProvider.protectionsManagementProcess.contains('parentalControl') ), smallSwitch( AppLocalizations.of(context)!.safeSearch, Icons.search_rounded, - serversProvider.serverStatus.data!.safeSearchEnabled, + statusProvider.serverStatus!.safeSearchEnabled, (value) => updateBlocking(value: value, filter: 'safeSearch'), - serversProvider.protectionsManagementProcess.contains('safeSearch') + statusProvider.protectionsManagementProcess.contains('safeSearch') ), ]; } diff --git a/lib/screens/home/server_status.dart b/lib/screens/home/server_status.dart index 2a52889..c130564 100644 --- a/lib/screens/home/server_status.dart +++ b/lib/screens/home/server_status.dart @@ -5,10 +5,10 @@ import 'package:adguard_home_manager/screens/home/status_box.dart'; import 'package:adguard_home_manager/models/server_status.dart'; -class ServerStatus extends StatelessWidget { - final ServerStatusData serverStatus; +class ServerStatusWidget extends StatelessWidget { + final ServerStatus serverStatus; - const ServerStatus({ + const ServerStatusWidget({ Key? key, required this.serverStatus, }) : super(key: key); diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index e956409..04f8851 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -13,6 +13,7 @@ import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -37,6 +38,7 @@ class TopItems extends StatelessWidget { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); @@ -61,7 +63,7 @@ class TopItems extends StatelessWidget { final rules = await getFilteringRules(server: serversProvider.selectedServer!); if (rules['result'] == 'success') { - FilteringStatus oldStatus = serversProvider.serverStatus.data!.filteringStatus; + FilteringStatus oldStatus = statusProvider.serverStatus!.filteringStatus; List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); if (newStatus == 'block') { @@ -70,7 +72,7 @@ class TopItems extends StatelessWidget { else if (newStatus == 'unblock') { newRules.add("@@||$domain^"); } - FilteringStatus newObj = serversProvider.serverStatus.data!.filteringStatus; + FilteringStatus newObj = statusProvider.serverStatus!.filteringStatus; newObj.userRules = newRules; serversProvider.setFilteringStatus(newObj); @@ -154,7 +156,7 @@ class TopItems extends StatelessWidget { String? name; if (clients != null && clients == true) { try { - name = serversProvider.serverStatus.data!.clients.firstWhere((c) => c.ids.contains(item.keys.toList()[0])).name; + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(item.keys.toList()[0])).name; } catch (e) { // ---- // } @@ -241,13 +243,13 @@ class TopItems extends StatelessWidget { List> generateData() { switch (type) { case 'topQueriedDomains': - return serversProvider.serverStatus.data!.stats.topQueriedDomains; + return statusProvider.serverStatus!.stats.topQueriedDomains; case 'topBlockedDomains': - return serversProvider.serverStatus.data!.stats.topBlockedDomains; + return statusProvider.serverStatus!.stats.topBlockedDomains; case 'topClients': - return serversProvider.serverStatus.data!.stats.topClients; + return statusProvider.serverStatus!.stats.topClients; default: return []; diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index c88cd0e..7a6afd6 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -15,6 +15,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -190,6 +191,7 @@ class _LogsWidgetState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); @@ -200,7 +202,7 @@ class _LogsWidgetState extends State { processModal.open(AppLocalizations.of(context)!.updatingSettings); final result = serverVersionIsAhead( - currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true @@ -442,7 +444,7 @@ class _LogsWidgetState extends State { onConfirm: updateConfig, onClear: clearQueries, dialog: true, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, ), barrierDismissible: false ) @@ -454,7 +456,7 @@ class _LogsWidgetState extends State { onConfirm: updateConfig, onClear: clearQueries, dialog: false, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, ), backgroundColor: Colors.transparent, isScrollControlled: true diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 7dbbbfc..986e7b7 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -7,6 +7,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -19,10 +21,12 @@ class SafeSearchSettingsScreen extends StatelessWidget { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProviuder = Provider.of(context); final appConfigProvider = Provider.of(context); return SafeSearchSettingsScreenWidget( serversProvider: serversProvider, + statusProvider: statusProviuder, appConfigProvider: appConfigProvider, ); } @@ -30,11 +34,13 @@ class SafeSearchSettingsScreen extends StatelessWidget { class SafeSearchSettingsScreenWidget extends StatefulWidget { final ServersProvider serversProvider; + final StatusProvider statusProvider; final AppConfigProvider appConfigProvider; const SafeSearchSettingsScreenWidget({ Key? key, required this.serversProvider, + required this.statusProvider, required this.appConfigProvider }) : super(key: key); @@ -56,8 +62,10 @@ class _SafeSearchSettingsScreenWidgetState extends State(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveConfig() async { @@ -118,7 +127,7 @@ class _SafeSearchSettingsScreenWidgetState extends State saveConfig() : null, icon: const Icon(Icons.save_rounded), diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 8565e2f..4586b28 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -27,6 +27,7 @@ import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/urls.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -67,8 +68,9 @@ class SettingsWidget extends StatelessWidget { @override Widget build(BuildContext context) { - final appConfigProvider = Provider.of(context); final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -129,10 +131,10 @@ class SettingsWidget extends StatelessWidget { ], body: ListView( children: [ - if (serversProvider.selectedServer != null && serversProvider.serverStatus.data != null) ...[ + if (serversProvider.selectedServer != null && statusProvider.serverStatus != null) ...[ SectionLabel(label: AppLocalizations.of(context)!.serverSettings), if (serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true) settingsTile( @@ -217,7 +219,7 @@ class SettingsWidget extends StatelessWidget { icon: Icons.storage_rounded, title: AppLocalizations.of(context)!.servers, subtitle: serversProvider.selectedServer != null - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" : AppLocalizations.of(context)!.noServerSelected, diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 643e8be..db3584a 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -12,6 +12,7 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -58,6 +59,7 @@ class _TopItemsScreenState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); @@ -132,7 +134,9 @@ class _TopItemsScreenState extends State { onRefresh: () async { final result = await getServerStatus(serversProvider.selectedServer!); if (result['result'] == 'success') { - serversProvider.setServerStatusData(result['data']); + statusProvider.setServerStatusData( + data: result['data'] + ); } else { appConfigProvider.addLog(result['log']); @@ -150,7 +154,7 @@ class _TopItemsScreenState extends State { String? name; if (widget.isClient != null && widget.isClient == true) { try { - name = serversProvider.serverStatus.data!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; } catch (e) { // ---- // } diff --git a/lib/screens/top_items/top_items_modal.dart b/lib/screens/top_items/top_items_modal.dart index 3c98679..845459a 100644 --- a/lib/screens/top_items/top_items_modal.dart +++ b/lib/screens/top_items/top_items_modal.dart @@ -13,8 +13,8 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class TopItemsModal extends StatefulWidget { final String type; @@ -55,7 +55,7 @@ class _TopItemsModalState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); @@ -122,7 +122,7 @@ class _TopItemsModalState extends State { String? name; if (widget.isClient != null && widget.isClient == true) { try { - name = serversProvider.serverStatus.data!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; } catch (e) { // ---- // } diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 35b542f..25a15ea 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -335,7 +335,7 @@ Future getServerStatus(Server server) async { }; return { 'result': 'success', - 'data': ServerStatusData.fromJson(mappedData) + 'data': ServerStatus.fromJson(mappedData) }; } else { diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 70ca410..d299cf4 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -7,6 +7,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/base64.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/app_log.dart'; @@ -217,6 +219,7 @@ class _AddServerModalState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context, listen: false); + final statusProvider = Provider.of(context, listen: false); final appConfigProvider = Provider.of(context, listen: false); final mediaQuery = MediaQuery.of(context); @@ -257,13 +260,15 @@ class _AddServerModalState extends State { } final serverCreated = await serversProvider.createServer(serverObj); if (serverCreated == null) { - serversProvider.setServerStatusLoad(0); + statusProvider.setServerStatusLoad(LoadStatus.loading); final serverStatus = await getServerStatus(serverObj); if (serverStatus['result'] == 'success') { - serversProvider.setServerStatusData(serverStatus['data']); - serversProvider.setServerStatusLoad(1); + statusProvider.setServerStatusData( + data: serverStatus['data'] + ); + statusProvider.setServerStatusLoad(LoadStatus.loaded); if (serverStatus['data'].serverVersion.contains('a') || serverStatus['data'].serverVersion.contains('b')) { Navigator.pop(context); widget.onUnsupportedVersion(serverStatus['data'].serverVersion); @@ -274,7 +279,7 @@ class _AddServerModalState extends State { } else { appConfigProvider.addLog(serverStatus['log']); - serversProvider.setServerStatusLoad(2); + statusProvider.setServerStatusLoad(LoadStatus.error); Navigator.pop(context); } } diff --git a/lib/widgets/domain_options.dart b/lib/widgets/domain_options.dart index 1612390..5637e9d 100644 --- a/lib/widgets/domain_options.dart +++ b/lib/widgets/domain_options.dart @@ -11,6 +11,7 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -37,6 +38,7 @@ class DomainOptions extends StatelessWidget { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void blockUnblock(String domain, String newStatus) async { @@ -46,7 +48,7 @@ class DomainOptions extends StatelessWidget { final rules = await getFilteringRules(server: serversProvider.selectedServer!); if (rules['result'] == 'success') { - FilteringStatus oldStatus = serversProvider.serverStatus.data!.filteringStatus; + FilteringStatus oldStatus = statusProvider.serverStatus!.filteringStatus; List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); if (newStatus == 'block') { @@ -55,7 +57,7 @@ class DomainOptions extends StatelessWidget { else if (newStatus == 'unblock') { newRules.add("@@||$domain^"); } - FilteringStatus newObj = serversProvider.serverStatus.data!.filteringStatus; + FilteringStatus newObj = statusProvider.serverStatus!.filteringStatus; newObj.userRules = newRules; serversProvider.setFilteringStatus(newObj); diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 614c2ca..1a9c482 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -11,6 +11,8 @@ import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -69,6 +71,7 @@ class _ServersListItemState extends State with SingleTickerProv @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -134,16 +137,18 @@ class _ServersListItemState extends State with SingleTickerProv if (result['result'] == 'success') { serversProvider.setSelectedServer(server); - serversProvider.setServerStatusLoad(0); + statusProvider.setServerStatusLoad(LoadStatus.loading); final serverStatus = await getServerStatus(server); if (serverStatus['result'] == 'success') { - serversProvider.setServerStatusData(serverStatus['data']); + statusProvider.setServerStatusData( + data: serverStatus['data'] + ); serversProvider.checkServerUpdatesAvailable(server); - serversProvider.setServerStatusLoad(1); + statusProvider.setServerStatusLoad(LoadStatus.loaded); } else { appConfigProvider.addLog(serverStatus['log']); - serversProvider.setServerStatusLoad(2); + statusProvider.setServerStatusLoad(LoadStatus.error); } process.close(); @@ -192,7 +197,7 @@ class _ServersListItemState extends State with SingleTickerProv Icon( Icons.storage_rounded, color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? Colors.green : Colors.orange : null, @@ -225,7 +230,7 @@ class _ServersListItemState extends State with SingleTickerProv return Icon( Icons.storage_rounded, color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? Colors.green : Colors.orange : null, @@ -344,7 +349,7 @@ class _ServersListItemState extends State with SingleTickerProv margin: const EdgeInsets.only(right: 12), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), decoration: BoxDecoration( - color: serversProvider.serverStatus.data != null + color: statusProvider.serverStatus != null ? Colors.green : Colors.orange, borderRadius: BorderRadius.circular(30) @@ -352,14 +357,14 @@ class _ServersListItemState extends State with SingleTickerProv child: Row( children: [ Icon( - serversProvider.serverStatus.data != null + statusProvider.serverStatus != null ? Icons.check : Icons.warning, color: Colors.white, ), const SizedBox(width: 10), Text( - serversProvider.serverStatus.data != null + statusProvider.serverStatus != null ? AppLocalizations.of(context)!.connected : AppLocalizations.of(context)!.selectedDisconnected, style: const TextStyle( diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index 8145b5e..32c3772 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -10,6 +10,8 @@ import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -36,6 +38,7 @@ class _ServersTileItemState extends State with SingleTickerProv @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -101,16 +104,18 @@ class _ServersTileItemState extends State with SingleTickerProv if (result['result'] == 'success') { serversProvider.setSelectedServer(server); - serversProvider.setServerStatusLoad(0); + statusProvider.setServerStatusLoad(LoadStatus.loading); final serverStatus = await getServerStatus(server); if (serverStatus['result'] == 'success') { - serversProvider.setServerStatusData(serverStatus['data']); + statusProvider.setServerStatusData( + data: serverStatus['data'] + ); serversProvider.checkServerUpdatesAvailable(server); - serversProvider.setServerStatusLoad(1); + statusProvider.setServerStatusLoad(LoadStatus.loaded); } else { appConfigProvider.addLog(serverStatus['log']); - serversProvider.setServerStatusLoad(2); + statusProvider.setServerStatusLoad(LoadStatus.error); } process.close(); @@ -159,7 +164,7 @@ class _ServersTileItemState extends State with SingleTickerProv Icon( Icons.storage_rounded, color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? Colors.green : Colors.orange : null, @@ -192,7 +197,7 @@ class _ServersTileItemState extends State with SingleTickerProv return Icon( Icons.storage_rounded, color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? Colors.green : Colors.orange : null, @@ -305,13 +310,13 @@ class _ServersTileItemState extends State with SingleTickerProv ), SizedBox( child: serversProvider.selectedServer != null && - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null && + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null && serversProvider.selectedServer?.id == server.id ? Container( margin: const EdgeInsets.only(right: 12), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), decoration: BoxDecoration( - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null ? Colors.green : Colors.orange, borderRadius: BorderRadius.circular(30) @@ -319,14 +324,14 @@ class _ServersTileItemState extends State with SingleTickerProv child: Row( children: [ Icon( - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null ? Icons.check : Icons.warning, color: Colors.white, ), const SizedBox(width: 10), Text( - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null ? AppLocalizations.of(context)!.connected : AppLocalizations.of(context)!.selectedDisconnected, style: const TextStyle( From 8a3d42b66cbeb75ffb627470fb033c5c15eb3801 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 14:16:53 +0200 Subject: [PATCH 145/676] Extracted clients to a separate provider --- lib/models/clients.dart | 29 ++----- lib/providers/clients_provider.dart | 83 +++++++++++++++++++ lib/providers/servers_provider.dart | 79 ------------------ lib/screens/clients/added_list.dart | 10 ++- lib/screens/clients/client_screen.dart | 4 +- lib/screens/clients/clients.dart | 83 +++++++------------ lib/screens/clients/clients_desktop_view.dart | 24 +++--- lib/screens/clients/fab.dart | 6 +- lib/screens/clients/search_clients.dart | 40 +++------ .../access_settings/access_settings.dart | 64 ++++++-------- .../access_settings/clients_list.dart | 18 ++-- lib/services/http_requests.dart | 2 +- 12 files changed, 192 insertions(+), 250 deletions(-) diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 2c9f222..4d8e7db 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -1,45 +1,28 @@ -import 'dart:convert'; - -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/safe_search.dart'; class Clients { - LoadStatus loadStatus; - ClientsData? data; - - Clients({ - required this.loadStatus, - this.data - }); -} - -ClientsData clientsFromJson(String str) => ClientsData.fromJson(json.decode(str)); - -String clientsToJson(ClientsData data) => json.encode(data.toJson()); - -class ClientsData { List clients; - final List autoClientsData; + final List autoClients; final List supportedTags; ClientsAllowedBlocked? clientsAllowedBlocked; - ClientsData({ + Clients({ required this.clients, - required this.autoClientsData, + required this.autoClients, required this.supportedTags, this.clientsAllowedBlocked }); - factory ClientsData.fromJson(Map json) => ClientsData( + factory Clients.fromJson(Map json) => Clients( clients: json["clients"] != null ? List.from(json["clients"].map((x) => Client.fromJson(x))) : [], - autoClientsData: json["auto_clients"] != null ? List.from(json["auto_clients"].map((x) => AutoClient.fromJson(x))) : [], + autoClients: json["auto_clients"] != null ? List.from(json["auto_clients"].map((x) => AutoClient.fromJson(x))) : [], supportedTags: json["supported_tags"] != null ? List.from(json["supported_tags"].map((x) => x)) : [], ); Map toJson() => { "clients": List.from(clients.map((x) => x.toJson())), - "auto_clients": List.from(autoClientsData.map((x) => x.toJson())), + "auto_clients": List.from(autoClients.map((x) => x.toJson())), "supported_tags": List.from(supportedTags.map((x) => x)), }; } diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart index 3d7e0ae..df5d584 100644 --- a/lib/providers/clients_provider.dart +++ b/lib/providers/clients_provider.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; class ClientsProvider with ChangeNotifier { ServersProvider? _serversProvider; @@ -10,4 +13,84 @@ class ClientsProvider with ChangeNotifier { _serversProvider = serversProvider; } } + + LoadStatus _loadStatus = LoadStatus.loading; + Clients? _clients; + String? _searchTermClients; + List _filteredActiveClients = []; + List _filteredAddedClients = []; + + LoadStatus get loadStatus { + return _loadStatus; + } + + Clients? get clients { + return _clients; + } + + String? get searchTermClients { + return _searchTermClients; + } + + List get filteredActiveClients { + return _filteredActiveClients; + } + + List get filteredAddedClients { + return _filteredAddedClients; + } + + void setClientsLoadStatus(LoadStatus status, bool notify) { + _loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } + + void setClientsData(Clients data) { + _clients = data; + if (_searchTermClients != null && _searchTermClients != '') { + _filteredActiveClients = _clients!.autoClients.where( + (client) => client.ip.contains(_searchTermClients!.toLowerCase()) || (client.name != null ? client.name!.contains(_searchTermClients!.toLowerCase()) : false) + ).toList(); + _filteredAddedClients = _clients!.clients.where( + (client) { + isContained(String value) => value.contains(value.toLowerCase()); + return client.ids.any(isContained); + } + ).toList(); + } + else { + _filteredActiveClients = data.autoClients; + _filteredAddedClients = data.clients; + } + notifyListeners(); + } + + void setSearchTermClients(String? value) { + _searchTermClients = value; + if (value != null && value != '') { + if (_clients != null) { + _filteredActiveClients = _clients!.autoClients.where( + (client) => client.ip.contains(value.toLowerCase()) || (client.name != null ? client.name!.contains(value.toLowerCase()) : false) + ).toList(); + _filteredAddedClients = _clients!.clients.where( + (client) { + isContained(String value) => value.contains(value.toLowerCase()); + return client.ids.any(isContained); + } + ).toList(); + } + } + else { + if (_clients != null) _filteredActiveClients = _clients!.autoClients; + if (_clients != null) _filteredAddedClients = _clients!.clients; + } + notifyListeners(); + } + + void setAllowedDisallowedClientsBlockedDomains(ClientsAllowedBlocked data) { + _clients?.clientsAllowedBlocked = data; + notifyListeners(); + } } \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index decbb0a..771bbaf 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -31,15 +31,6 @@ class ServersProvider with ChangeNotifier { List _serversList = []; Server? _selectedServer; - String? _serverVersion; - - final Clients _clients = Clients( - loadStatus: LoadStatus.loading, - data: null - ); - String? _searchTermClients; - List _filteredActiveClients = []; - List _filteredAddedClients = []; final Filtering _filtering = Filtering( loadStatus: LoadStatus.loading, @@ -81,22 +72,6 @@ class ServersProvider with ChangeNotifier { return _selectedServer; } - Clients get clients { - return _clients; - } - - String? get searchTermClients { - return _searchTermClients; - } - - List get filteredActiveClients { - return _filteredActiveClients; - } - - List get filteredAddedClients { - return _filteredAddedClients; - } - FilteringStatus? get filteringStatus { return _filteringStatus; } @@ -139,60 +114,6 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setClientsLoadStatus(LoadStatus status, bool notify) { - _clients.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } - - void setClientsData(ClientsData data) { - _clients.data = data; - if (_searchTermClients != null && _searchTermClients != '') { - _filteredActiveClients = _clients.data!.autoClientsData.where( - (client) => client.ip.contains(_searchTermClients!.toLowerCase()) || (client.name != null ? client.name!.contains(_searchTermClients!.toLowerCase()) : false) - ).toList(); - _filteredAddedClients = _clients.data!.clients.where( - (client) { - isContained(String value) => value.contains(value.toLowerCase()); - return client.ids.any(isContained); - } - ).toList(); - } - else { - _filteredActiveClients = data.autoClientsData; - _filteredAddedClients = data.clients; - } - notifyListeners(); - } - - void setSearchTermClients(String? value) { - _searchTermClients = value; - if (value != null && value != '') { - if (_clients.data != null) { - _filteredActiveClients = _clients.data!.autoClientsData.where( - (client) => client.ip.contains(value.toLowerCase()) || (client.name != null ? client.name!.contains(value.toLowerCase()) : false) - ).toList(); - _filteredAddedClients = _clients.data!.clients.where( - (client) { - isContained(String value) => value.contains(value.toLowerCase()); - return client.ids.any(isContained); - } - ).toList(); - } - } - else { - if (_clients.data != null) _filteredActiveClients = _clients.data!.autoClientsData; - if (_clients.data != null) _filteredAddedClients = _clients.data!.clients; - } - notifyListeners(); - } - - void setAllowedDisallowedClientsBlockedDomains(ClientsAllowedBlocked data) { - _clients.data?.clientsAllowedBlocked = data; - notifyListeners(); - } - void setFilteringStatus(FilteringStatus status) { _filteringStatus = status; notifyListeners(); diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index cc535db..5c876f0 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -19,6 +19,7 @@ import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/maps_fns.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -79,6 +80,7 @@ class _AddedListState extends State { Widget build(BuildContext context) { final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -101,7 +103,7 @@ class _AddedListState extends State { processModal.close(); if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; + Clients clientsData = clientsProvider.clients!; clientsData.clients = clientsData.clients.map((e) { if (e.name == client.name) { return client; @@ -110,7 +112,7 @@ class _AddedListState extends State { return e; } }).toList(); - serversProvider.setClientsData(clientsData); + clientsProvider.setClientsData(clientsData); showSnacbkar( appConfigProvider: appConfigProvider, @@ -138,9 +140,9 @@ class _AddedListState extends State { processModal.close(); if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; + Clients clientsData = clientsProvider.clients!; clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); - serversProvider.setClientsData(clientsData); + clientsProvider.setClientsData(clientsData); if (widget.splitView == true) { SplitView.of(context).popUntil(0); diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart index 52bf1c1..c1c08ef 100644 --- a/lib/screens/clients/client_screen.dart +++ b/lib/screens/clients/client_screen.dart @@ -11,6 +11,7 @@ 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'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; @@ -132,6 +133,7 @@ class _ClientScreenState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final statusProvider = Provider.of(context); void createClient() { @@ -202,7 +204,7 @@ class _ClientScreenState extends State { context: context, builder: (context) => TagsModal( selectedTags: selectedTags, - tags: serversProvider.clients.data!.supportedTags, + tags: clientsProvider.clients!.supportedTags, onConfirm: (selected) => setState(() => selectedTags = selected), ) ); diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 9e13c77..98a9391 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -11,53 +11,21 @@ import 'package:adguard_home_manager/screens/clients/logs_list_client.dart'; import 'package:adguard_home_manager/screens/clients/clients_desktop_view.dart'; import 'package:adguard_home_manager/screens/clients/added_list.dart'; -import 'package:adguard_home_manager/models/app_log.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class Clients extends StatelessWidget { +class Clients extends StatefulWidget { const Clients({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return ClientsWidget( - server: serversProvider.selectedServer!, - setLoadingStatus: serversProvider.setClientsLoadStatus, - setClientsData: serversProvider.setClientsData, - setSelectedClientsTab: appConfigProvider.setSelectedClientsTab, - addLog: appConfigProvider.addLog, - ); - } + State createState() => _ClientsState(); } -class ClientsWidget extends StatefulWidget { - final Server server; - final void Function(LoadStatus, bool) setLoadingStatus; - final void Function(ClientsData) setClientsData; - final void Function(int) setSelectedClientsTab; - final void Function(AppLog) addLog; - - const ClientsWidget({ - Key? key, - required this.server, - required this.setLoadingStatus, - required this.setClientsData, - required this.setSelectedClientsTab, - required this.addLog, - }) : super(key: key); - - @override - State createState() => _ClientsWidgetState(); -} - -class _ClientsWidgetState extends State with TickerProviderStateMixin { +class _ClientsState extends State with TickerProviderStateMixin { late TabController tabController; final ScrollController scrollController = ScrollController(); @@ -65,16 +33,20 @@ class _ClientsWidgetState extends State with TickerProviderStateM final TextEditingController searchController = TextEditingController(); Future fetchClients() async { - widget.setLoadingStatus(LoadStatus.loading, false); - final result = await getClients(widget.server); + final clientsProvider = Provider.of(context, listen: false); + final serversProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + + clientsProvider.setClientsLoadStatus(LoadStatus.loading, false); + final result = await getClients(serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { - widget.setClientsData(result['data']); - widget.setLoadingStatus(LoadStatus.loaded, true); + clientsProvider.setClientsData(result['data']); + clientsProvider.setClientsLoadStatus(LoadStatus.loaded, true); } else { - widget.addLog(result['log']); - widget.setLoadingStatus(LoadStatus.error, true); + appConfigProvider.addLog(result['log']); + clientsProvider.setClientsLoadStatus(LoadStatus.error, true); } } } @@ -88,7 +60,9 @@ class _ClientsWidgetState extends State with TickerProviderStateM length: 2, vsync: this, ); - tabController.addListener(() => widget.setSelectedClientsTab(tabController.index)); + tabController.addListener( + () => Provider.of(context, listen: false).setSelectedClientsTab(tabController.index) + ); } List generateClientsList(List clients, List ips) { @@ -98,6 +72,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -137,9 +112,9 @@ class _ClientsWidgetState extends State with TickerProviderStateM children: [ ClientsList( scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.filteredActiveClients : [], + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredActiveClients : [], fetchClients: fetchClients, onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( builder: (context) => LogsListClient( @@ -153,9 +128,9 @@ class _ClientsWidgetState extends State with TickerProviderStateM ), AddedList( scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.filteredAddedClients : [], + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredAddedClients : [], fetchClients: fetchClients, onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( builder: (context) => LogsListClient( @@ -203,7 +178,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM title: Text(AppLocalizations.of(context)!.clients), centerTitle: false, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded) ...[ + if (clientsProvider.loadStatus == LoadStatus.loaded) ...[ IconButton( onPressed: () => { Navigator.push(context, MaterialPageRoute( @@ -240,7 +215,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM setState(() { searchMode = false; searchController.text = ""; - serversProvider.setSearchTermClients(null); + clientsProvider.setSearchTermClients(null); }); }, icon: const Icon(Icons.arrow_back_rounded) @@ -249,13 +224,13 @@ class _ClientsWidgetState extends State with TickerProviderStateM Expanded( child: TextField( controller: searchController, - onChanged: (value) => serversProvider.setSearchTermClients(value), + onChanged: (value) => clientsProvider.setSearchTermClients(value), decoration: InputDecoration( suffixIcon: IconButton( onPressed: () { setState(() { searchController.text = ""; - serversProvider.setSearchTermClients(null); + clientsProvider.setSearchTermClients(null); }); }, icon: const Icon(Icons.clear_rounded) @@ -281,7 +256,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM centerTitle: false, forceElevated: innerBoxIsScrolled, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ IconButton( onPressed: () => setState(() => searchMode = true), icon: const Icon(Icons.search), diff --git a/lib/screens/clients/clients_desktop_view.dart b/lib/screens/clients/clients_desktop_view.dart index 0a4b783..04bfc35 100644 --- a/lib/screens/clients/clients_desktop_view.dart +++ b/lib/screens/clients/clients_desktop_view.dart @@ -10,6 +10,7 @@ import 'package:adguard_home_manager/screens/clients/added_list.dart'; import 'package:adguard_home_manager/screens/clients/clients_list.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -55,6 +56,7 @@ class _ClientsDesktopViewState extends State with TickerPro @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); PreferredSizeWidget tabBar() { @@ -92,9 +94,9 @@ class _ClientsDesktopViewState extends State with TickerPro children: [ ClientsList( scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.filteredActiveClients : [], + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredActiveClients : [], fetchClients: widget.fetchClients, onClientSelected: (client) => setState(() { selectedAddedClient = null; @@ -114,9 +116,9 @@ class _ClientsDesktopViewState extends State with TickerPro ), AddedList( scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.filteredAddedClients : [], + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredAddedClients : [], fetchClients: widget.fetchClients, onClientSelected: (client) => setState(() { selectedActiveClient = null; @@ -146,7 +148,7 @@ class _ClientsDesktopViewState extends State with TickerPro setState(() { searchMode = false; searchController.text = ""; - serversProvider.setSearchTermClients(null); + clientsProvider.setSearchTermClients(null); }); }, icon: const Icon(Icons.arrow_back_rounded) @@ -155,13 +157,13 @@ class _ClientsDesktopViewState extends State with TickerPro Expanded( child: TextField( controller: searchController, - onChanged: (value) => serversProvider.setSearchTermClients(value), + onChanged: (value) => clientsProvider.setSearchTermClients(value), decoration: InputDecoration( suffixIcon: IconButton( onPressed: () { setState(() { searchController.text = ""; - serversProvider.setSearchTermClients(null); + clientsProvider.setSearchTermClients(null); }); }, icon: const Icon(Icons.clear_rounded) @@ -195,7 +197,7 @@ class _ClientsDesktopViewState extends State with TickerPro title: title(), centerTitle: false, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ IconButton( onPressed: () => setState(() => searchMode = true), icon: const Icon(Icons.search), @@ -226,7 +228,7 @@ class _ClientsDesktopViewState extends State with TickerPro centerTitle: false, forceElevated: innerBoxIsScrolled, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ IconButton( onPressed: () => setState(() => searchMode = true), icon: const Icon(Icons.search), diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index a92a1d0..61b2aec 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -9,6 +9,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/client_screen.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/functions/maps_fns.dart'; @@ -26,6 +27,7 @@ class ClientsFab extends StatelessWidget { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final statusProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -47,9 +49,9 @@ class ClientsFab extends StatelessWidget { processModal.close(); if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; + Clients clientsData = clientsProvider.clients!; clientsData.clients.add(client); - serversProvider.setClientsData(clientsData); + clientsProvider.setClientsData(clientsData); showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index 7f2c3df..569d50c 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -19,36 +19,19 @@ import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class SearchClients extends StatelessWidget { +class SearchClients extends StatefulWidget { const SearchClients({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - - return SearchClientsWidget( - serversProvider: serversProvider, - ); - } + State createState() => _SearchClientsState(); } -class SearchClientsWidget extends StatefulWidget { - final ServersProvider serversProvider; - - const SearchClientsWidget({ - Key? key, - required this.serversProvider, - }) : super(key: key); - - @override - State createState() => _SearchClientsWidgetState(); -} - -class _SearchClientsWidgetState extends State { +class _SearchClientsState extends State { late ScrollController scrollController; final TextEditingController searchController = TextEditingController(); @@ -87,11 +70,13 @@ class _SearchClientsWidgetState extends State { @override void initState() { + final clientsProvider = Provider.of(context, listen: false); + scrollController = ScrollController()..addListener(scrollListener); setState(() { - clients = widget.serversProvider.clients.data!.clients; - autoClients = widget.serversProvider.clients.data!.autoClientsData; + clients = clientsProvider.clients!.clients; + autoClients = clientsProvider.clients!.autoClients; }); super.initState(); @@ -101,6 +86,7 @@ class _SearchClientsWidgetState extends State { Widget build(BuildContext context) { final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -114,9 +100,9 @@ class _SearchClientsWidgetState extends State { processModal.close(); if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; + Clients clientsData = clientsProvider.clients!; clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); - serversProvider.setClientsData(clientsData); + clientsProvider.setClientsData(clientsData); setState(() { clients = clientsData.clients; }); @@ -151,7 +137,7 @@ class _SearchClientsWidgetState extends State { processModal.close(); if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; + Clients clientsData = clientsProvider.clients!; clientsData.clients = clientsData.clients.map((e) { if (e.name == client.name) { return client; @@ -160,7 +146,7 @@ class _SearchClientsWidgetState extends State { return e; } }).toList(); - serversProvider.setClientsData(clientsData); + clientsProvider.setClientsData(clientsData); setState(() { clients = clientsData.clients; diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index 9f03328..b209bf6 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -7,54 +7,37 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/access_settings/clients_list.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class AccessSettings extends StatelessWidget { +class AccessSettings extends StatefulWidget { const AccessSettings({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return AccessSettingsWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _AccessSettingsState(); } -class AccessSettingsWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const AccessSettingsWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - }) : super(key: key); - - @override - State createState() => _AccessSettingsWidgetState(); -} - -class _AccessSettingsWidgetState extends State with TickerProviderStateMixin { +class _AccessSettingsState extends State with TickerProviderStateMixin { final ScrollController scrollController = ScrollController(); late TabController tabController; Future fetchClients() async { - widget.serversProvider.setClientsLoadStatus(LoadStatus.loading, false); - final result = await getClients(widget.serversProvider.selectedServer!); + final clientsProvider = Provider.of(context, listen: false); + final serversProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + + clientsProvider.setClientsLoadStatus(LoadStatus.loading, false); + final result = await getClients(serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { - widget.serversProvider.setClientsData(result['data']); - widget.serversProvider.setClientsLoadStatus(LoadStatus.loaded, true); + clientsProvider.setClientsData(result['data']); + clientsProvider.setClientsLoadStatus(LoadStatus.loaded, true); } else { - widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setClientsLoadStatus(LoadStatus.error, true); + appConfigProvider.addLog(result['log']); + clientsProvider.setClientsLoadStatus(LoadStatus.error, true); } } } @@ -74,6 +57,7 @@ class _AccessSettingsWidgetState extends State with Ticker @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final clientsProvider = Provider.of(context); Widget body() { return TabBarView( @@ -82,25 +66,25 @@ class _AccessSettingsWidgetState extends State with Ticker ClientsList( type: 'allowed', scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clientsAllowedBlocked!.allowedClients : [], + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.clients!.clientsAllowedBlocked!.allowedClients : [], fetchClients: fetchClients ), ClientsList( type: 'disallowed', scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clientsAllowedBlocked!.disallowedClients : [], + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.clients!.clientsAllowedBlocked!.disallowedClients : [], fetchClients: fetchClients ), ClientsList( type: 'domains', scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts : [], + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.clients!.clientsAllowedBlocked!.blockedHosts : [], fetchClients: fetchClients ), ] diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index bc3646f..8e9fb30 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -16,6 +16,7 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -69,14 +70,15 @@ class _ClientsListState extends State { Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; void confirmRemoveItem(String client, String type) async { Map> body = { - "allowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.allowedClients ?? [], - "disallowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.disallowedClients ?? [], - "blocked_hosts": serversProvider.clients.data!.clientsAllowedBlocked?.blockedHosts ?? [], + "allowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.allowedClients ?? [], + "disallowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.disallowedClients ?? [], + "blocked_hosts": clientsProvider.clients!.clientsAllowedBlocked?.blockedHosts ?? [], }; if (type == 'allowed') { @@ -97,7 +99,7 @@ class _ClientsListState extends State { processModal.close(); if (result['result'] == 'success') { - serversProvider.setAllowedDisallowedClientsBlockedDomains( + clientsProvider.setAllowedDisallowedClientsBlockedDomains( ClientsAllowedBlocked( allowedClients: body['allowed_clients'] ?? [], disallowedClients: body['disallowed_clients'] ?? [], @@ -125,9 +127,9 @@ class _ClientsListState extends State { void confirmAddItem(String item, String type) async { Map> body = { - "allowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.allowedClients ?? [], - "disallowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.disallowedClients ?? [], - "blocked_hosts": serversProvider.clients.data!.clientsAllowedBlocked?.blockedHosts ?? [], + "allowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.allowedClients ?? [], + "disallowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.disallowedClients ?? [], + "blocked_hosts": clientsProvider.clients!.clientsAllowedBlocked?.blockedHosts ?? [], }; if (type == 'allowed') { @@ -148,7 +150,7 @@ class _ClientsListState extends State { processModal.close(); if (result['result'] == 'success') { - serversProvider.setAllowedDisallowedClientsBlockedDomains( + clientsProvider.setAllowedDisallowedClientsBlockedDomains( ClientsAllowedBlocked( allowedClients: body['allowed_clients'] ?? [], disallowedClients: body['disallowed_clients'] ?? [], diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 25a15ea..cbc95b5 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -591,7 +591,7 @@ Future getClients(Server server) async { if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - final clients = ClientsData.fromJson(jsonDecode(result[0]['body'])); + final clients = Clients.fromJson(jsonDecode(result[0]['body'])); clients.clientsAllowedBlocked = ClientsAllowedBlocked.fromJson(jsonDecode(result[1]['body'])); return { 'result': 'success', From 77f6d02ff414d191919618b1be311500b960194f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 14:17:40 +0200 Subject: [PATCH 146/676] Removed unused imports --- lib/screens/clients/client_screen.dart | 2 -- lib/screens/settings/access_settings/access_settings.dart | 1 - 2 files changed, 3 deletions(-) diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart index c1c08ef..c40a6d4 100644 --- a/lib/screens/clients/client_screen.dart +++ b/lib/screens/clients/client_screen.dart @@ -13,7 +13,6 @@ import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/safe_search.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; class ClientScreen extends StatefulWidget { @@ -132,7 +131,6 @@ class _ClientScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final clientsProvider = Provider.of(context); final statusProvider = Provider.of(context); diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index b209bf6..6b3e046 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -56,7 +56,6 @@ class _AccessSettingsState extends State with TickerProviderStat @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final clientsProvider = Provider.of(context); Widget body() { From 04b78685887e57a8cf20e2d22c26a422e110d1f8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 14:29:14 +0200 Subject: [PATCH 147/676] Changed filtering status to status provider --- lib/functions/block_unblock_domain.dart | 4 +- lib/providers/servers_provider.dart | 16 +--- lib/providers/status_provider.dart | 16 +++- lib/screens/home/top_items.dart | 4 +- lib/screens/logs/log_details_screen.dart | 16 ++-- lib/screens/logs/logs.dart | 102 +++++++++-------------- lib/widgets/domain_options.dart | 4 +- 7 files changed, 72 insertions(+), 90 deletions(-) diff --git a/lib/functions/block_unblock_domain.dart b/lib/functions/block_unblock_domain.dart index 5b92659..0049564 100644 --- a/lib/functions/block_unblock_domain.dart +++ b/lib/functions/block_unblock_domain.dart @@ -32,7 +32,7 @@ Future> blockUnblock(BuildContext context, String domain, S } FilteringStatus newObj = statusProvider.serverStatus!.filteringStatus; newObj.userRules = newRules; - serversProvider.setFilteringStatus(newObj); + statusProvider.setFilteringStatus(newObj); final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); @@ -46,7 +46,7 @@ Future> blockUnblock(BuildContext context, String domain, S } else { appConfigProvider.addLog(result['log']); - serversProvider.setFilteringStatus(oldStatus); + statusProvider.setFilteringStatus(oldStatus); return { 'success': false, 'message': AppLocalizations.of(context)!.userFilteringRulesNotUpdated diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 771bbaf..6a8b391 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -5,10 +5,7 @@ import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; -import 'package:adguard_home_manager/models/filtering_status.dart'; -import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/blocked_services.dart'; -import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -62,8 +59,6 @@ class ServersProvider with ChangeNotifier { data: null, ); - FilteringStatus? _filteringStatus; - List get serversList { return _serversList; } @@ -72,10 +67,6 @@ class ServersProvider with ChangeNotifier { return _selectedServer; } - FilteringStatus? get filteringStatus { - return _filteringStatus; - } - Filtering get filtering { return _filtering; } @@ -114,11 +105,6 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setFilteringStatus(FilteringStatus status) { - _filteringStatus = status; - notifyListeners(); - } - void setFilteringData(FilteringData data) { _filtering.data = data; notifyListeners(); @@ -132,7 +118,7 @@ class ServersProvider with ChangeNotifier { } void setFilteringProtectionStatus(bool status) { - _statusProvider!.setFilteringStatus(status); + _statusProvider!.setFilteringEnabledStatus(status); _filtering.data!.enabled = status; notifyListeners(); } diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 26bdfe2..43d3ee4 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:flutter/material.dart'; import 'package:adguard_home_manager/models/server_status.dart'; @@ -18,9 +19,13 @@ class StatusProvider with ChangeNotifier { } LoadStatus _loadStatus = LoadStatus.loading; + ServerStatus? _serverStatus; // serverStatus != null means server is connected + List _protectionsManagementProcess = []; // protections that are currenty being enabled or disabled + FilteringStatus? _filteringStatus; + LoadStatus get loadStatus { return _loadStatus; } @@ -33,6 +38,10 @@ class StatusProvider with ChangeNotifier { return _protectionsManagementProcess; } + FilteringStatus? get filteringStatus { + return _filteringStatus; + } + void setServerStatusData({ required ServerStatus data, }) { @@ -45,6 +54,11 @@ class StatusProvider with ChangeNotifier { notifyListeners(); } + void setFilteringStatus(FilteringStatus status) { + _filteringStatus = status; + notifyListeners(); + } + Future updateBlocking({ required Server server, required String block, @@ -188,7 +202,7 @@ class StatusProvider with ChangeNotifier { } } - void setFilteringStatus(bool status) { + void setFilteringEnabledStatus(bool status) { _serverStatus!.filteringEnabled = status; } } \ No newline at end of file diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 04f8851..6356b7a 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -74,7 +74,7 @@ class TopItems extends StatelessWidget { } FilteringStatus newObj = statusProvider.serverStatus!.filteringStatus; newObj.userRules = newRules; - serversProvider.setFilteringStatus(newObj); + statusProvider.setFilteringStatus(newObj); final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); @@ -90,7 +90,7 @@ class TopItems extends StatelessWidget { } else { appConfigProvider.addLog(result['log']); - serversProvider.setFilteringStatus(oldStatus); + statusProvider.setFilteringStatus(oldStatus); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 1dafc64..1f6c100 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -10,6 +10,7 @@ import 'package:adguard_home_manager/screens/logs/log_list_tile.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; @@ -31,11 +32,12 @@ class LogDetailsScreen extends StatelessWidget { Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final statusProvider = Provider.of(context); Filter? getList(int id) { try { - return serversProvider.filteringStatus!.filters.firstWhere((filter) => filter.id == id, orElse: () { - return serversProvider.filteringStatus!.whitelistFilters.firstWhere((filter) => filter.id == id); + return statusProvider.filteringStatus!.filters.firstWhere((filter) => filter.id == id, orElse: () { + return statusProvider.filteringStatus!.whitelistFilters.firstWhere((filter) => filter.id == id); }); } catch (_) { return null; @@ -60,7 +62,7 @@ class LogDetailsScreen extends StatelessWidget { final rules = await getFilteringRules(server: serversProvider.selectedServer!); if (rules['result'] == 'success') { - FilteringStatus oldStatus = serversProvider.filteringStatus!; + FilteringStatus oldStatus = statusProvider.filteringStatus!; List newRules = rules['data'].userRules.where((domain) => !domain.contains(log.question.name)).toList(); if (newStatus == 'block') { @@ -69,9 +71,9 @@ class LogDetailsScreen extends StatelessWidget { else if (newStatus == 'unblock') { newRules.add("@@||${log.question.name}^"); } - FilteringStatus newObj = serversProvider.filteringStatus!; + FilteringStatus newObj = statusProvider.filteringStatus!; newObj.userRules = newRules; - serversProvider.setFilteringStatus(newObj); + statusProvider.setFilteringStatus(newObj); final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); @@ -87,7 +89,7 @@ class LogDetailsScreen extends StatelessWidget { } else { appConfigProvider.addLog(result['log']); - serversProvider.setFilteringStatus(oldStatus); + statusProvider.setFilteringStatus(oldStatus); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), @@ -298,7 +300,7 @@ class LogDetailsScreen extends StatelessWidget { centerTitle: false, title: Text(AppLocalizations.of(context)!.logDetails), actions: [ - if (serversProvider.filteringStatus != null) IconButton( + if (statusProvider.filteringStatus != null) IconButton( onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), icon: Icon( getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 7a6afd6..b70e7b7 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -22,46 +22,14 @@ import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class Logs extends StatelessWidget { +class Logs extends StatefulWidget { const Logs({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); - - return LogsWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - logsProvider: logsProvider, - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: logsProvider.appliedFilters.searchText, - ); - } + State createState() => _LogsState(); } -class LogsWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - final LogsProvider logsProvider; - final String selectedResultStatus; - final String? searchText; - - const LogsWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - required this.logsProvider, - required this.selectedResultStatus, - required this.searchText, - }) : super(key: key); - - @override - State createState() => _LogsWidgetState(); -} - -class _LogsWidgetState extends State { +class _LogsState extends State { late ScrollController scrollController; bool isLoadingMore = false; @@ -76,20 +44,24 @@ class _LogsWidgetState extends State { String? responseStatus, String? searchText, }) async { - int offst = inOffset ?? widget.logsProvider.offset; + final logsProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + final serversProvider = Provider.of(context, listen: false); - String resStatus = responseStatus ?? widget.selectedResultStatus; - String? search = searchText ?? widget.searchText; + int offst = inOffset ?? logsProvider.offset; + + String resStatus = responseStatus ?? logsProvider.selectedResultStatus; + String? search = searchText ?? logsProvider.searchText; if (loadingMore != null && loadingMore == true) { setState(() => isLoadingMore = true); } final result = await getLogs( - server: widget.serversProvider.selectedServer!, - count: widget.logsProvider.logsQuantity, + server: serversProvider.selectedServer!, + count: logsProvider.logsQuantity, offset: offst, - olderThan: widget.logsProvider.logsOlderThan, + olderThan: logsProvider.logsOlderThan, responseStatus: resStatus, search: search ); @@ -100,43 +72,47 @@ class _LogsWidgetState extends State { if (mounted) { if (result['result'] == 'success') { - widget.logsProvider.setOffset(inOffset != null ? inOffset+widget.logsProvider.logsQuantity : widget.logsProvider.offset+widget.logsProvider.logsQuantity); - if (loadingMore != null && loadingMore == true && widget.logsProvider.logsData != null) { + logsProvider.setOffset(inOffset != null ? inOffset+logsProvider.logsQuantity : logsProvider.offset+logsProvider.logsQuantity); + if (loadingMore != null && loadingMore == true && logsProvider.logsData != null) { LogsData newLogsData = result['data']; - newLogsData.data = [...widget.logsProvider.logsData!.data, ...result['data'].data]; - if (widget.logsProvider.appliedFilters.clients != null) { + newLogsData.data = [...logsProvider.logsData!.data, ...result['data'].data]; + if (logsProvider.appliedFilters.clients != null) { newLogsData.data = newLogsData.data.where( - (item) => widget.logsProvider.appliedFilters.clients!.contains(item.client) + (item) => logsProvider.appliedFilters.clients!.contains(item.client) ).toList(); } - widget.logsProvider.setLogsData(newLogsData); + logsProvider.setLogsData(newLogsData); } else { LogsData newLogsData = result['data']; - if (widget.logsProvider.appliedFilters.clients != null) { + if (logsProvider.appliedFilters.clients != null) { newLogsData.data = newLogsData.data.where( - (item) => widget.logsProvider.appliedFilters.clients!.contains(item.client) + (item) => logsProvider.appliedFilters.clients!.contains(item.client) ).toList(); } - widget.logsProvider.setLogsData(newLogsData); + logsProvider.setLogsData(newLogsData); } - widget.logsProvider.setLoadStatus(1); + logsProvider.setLoadStatus(1); } else { - widget.logsProvider.setLoadStatus(2); - widget.appConfigProvider.addLog(result['log']); + logsProvider.setLoadStatus(2); + appConfigProvider.addLog(result['log']); } } } void fetchFilteringRules() async { - final result = await getFilteringRules(server: widget.serversProvider.selectedServer!); + final appConfigProvider = Provider.of(context, listen: false); + final serversProvider = Provider.of(context, listen: false); + final statusProvider = Provider.of(context, listen: false); + + final result = await getFilteringRules(server: serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { - widget.serversProvider.setFilteringStatus(result['data']); + statusProvider.setFilteringStatus(result['data']); } else { - widget.appConfigProvider.addLog(result['log']); + appConfigProvider.addLog(result['log']); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(AppLocalizations.of(context)!.couldntGetFilteringStatus), @@ -148,15 +124,19 @@ class _LogsWidgetState extends State { } Future fetchClients() async { - final result = await getClients(widget.serversProvider.selectedServer!); + final logsProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + final serversProvider = Provider.of(context, listen: false); + + final result = await getClients(serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { - widget.logsProvider.setClientsLoadStatus(1); - widget.logsProvider.setClients(result['data'].autoClientsData); + logsProvider.setClientsLoadStatus(1); + logsProvider.setClients(result['data'].autoClients); } else { - widget.logsProvider.setClientsLoadStatus(2); - widget.appConfigProvider.addLog(result['log']); + logsProvider.setClientsLoadStatus(2); + appConfigProvider.addLog(result['log']); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(AppLocalizations.of(context)!.couldntGetFilteringStatus), diff --git a/lib/widgets/domain_options.dart b/lib/widgets/domain_options.dart index 5637e9d..415a8c3 100644 --- a/lib/widgets/domain_options.dart +++ b/lib/widgets/domain_options.dart @@ -59,7 +59,7 @@ class DomainOptions extends StatelessWidget { } FilteringStatus newObj = statusProvider.serverStatus!.filteringStatus; newObj.userRules = newRules; - serversProvider.setFilteringStatus(newObj); + statusProvider.setFilteringStatus(newObj); final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); @@ -75,7 +75,7 @@ class DomainOptions extends StatelessWidget { } else { appConfigProvider.addLog(result['log']); - serversProvider.setFilteringStatus(oldStatus); + statusProvider.setFilteringStatus(oldStatus); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), From 19ac14e49eff9bf0234570e21d0c07b823b93342 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 15:11:24 +0200 Subject: [PATCH 148/676] Moved filtering to separate provider --- lib/main.dart | 22 +---- lib/models/blocked_services.dart | 6 +- lib/models/filtering.dart | 22 +---- lib/providers/clients_provider.dart | 9 --- lib/providers/filters_provider.dart | 80 +++++++++++++++++-- lib/providers/logs_provider.dart | 9 --- lib/providers/servers_provider.dart | 69 ---------------- lib/providers/status_provider.dart | 14 +--- lib/screens/clients/services_modal.dart | 71 ++++++---------- lib/screens/filters/add_button.dart | 16 ++-- .../filters/blocked_services_screen.dart | 76 +++++++----------- lib/screens/filters/filters.dart | 76 +++++++----------- lib/screens/filters/filters_tabs_view.dart | 20 ++--- .../filters/filters_triple_column.dart | 44 +++++----- lib/screens/filters/list_details_screen.dart | 18 ++--- lib/screens/filters/list_functions.dart | 38 +++++---- lib/screens/filters/list_options_menu.dart | 4 - lib/services/http_requests.dart | 2 +- 18 files changed, 240 insertions(+), 356 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 388aff6..ddfbe3e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -49,7 +49,7 @@ void main() async { ServersProvider serversProvider = ServersProvider(); StatusProvider statusProvider = StatusProvider(); ClientsProvider clientsProvider = ClientsProvider(); - FiltersProvider filtersProvider = FiltersProvider(); + FilteringProvider filtersProvider = FilteringProvider(); LogsProvider logsProvider = LogsProvider(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); @@ -112,25 +112,9 @@ void main() async { ChangeNotifierProvider( create: ((context) => appConfigProvider) ), - ChangeNotifierProxyProvider( - create: (context) => serversProvider, - update: (context, status, servers) => servers!..update(status), - ), - ChangeNotifierProxyProvider( - create: (context) => statusProvider, - update: (context, servers, status) => status!..update(servers), - ), - ChangeNotifierProxyProvider( - create: (context) => clientsProvider, - update: (context, servers, clients) => clients!..update(servers), - ), - ChangeNotifierProxyProvider( - create: (context) => logsProvider, - update: (context, servers, logs) => logs!..update(servers), - ), - ChangeNotifierProxyProvider( + ChangeNotifierProxyProvider( create: (context) => filtersProvider, - update: (context, servers, filters) => filters!..update(servers), + update: (context, status, filtering) => filtering!..updateStatus(status), ), ], child: const Main(), diff --git a/lib/models/blocked_services.dart b/lib/models/blocked_services.dart index cb5c78a..659bebc 100644 --- a/lib/models/blocked_services.dart +++ b/lib/models/blocked_services.dart @@ -11,12 +11,10 @@ class BlockedServicesFromApi { } class BlockedServices { - int loadStatus = 0; - List? services; + List services; BlockedServices({ - this.loadStatus = 0, - this.services + required this.services }); } diff --git a/lib/models/filtering.dart b/lib/models/filtering.dart index 74a4710..9b1d6ce 100644 --- a/lib/models/filtering.dart +++ b/lib/models/filtering.dart @@ -1,22 +1,4 @@ -import 'dart:convert'; - -import 'package:adguard_home_manager/constants/enums.dart'; - -FilteringData filteringFromJson(String str) => FilteringData.fromJson(json.decode(str)); - -String filteringToJson(FilteringData data) => json.encode(data.toJson()); - class Filtering { - LoadStatus loadStatus = LoadStatus.loading; - FilteringData? data; - - Filtering({ - required this.loadStatus, - this.data - }); -} - -class FilteringData { final List filters; final List whitelistFilters; List userRules; @@ -24,7 +6,7 @@ class FilteringData { int interval; bool enabled; - FilteringData({ + Filtering({ required this.filters, required this.whitelistFilters, required this.userRules, @@ -33,7 +15,7 @@ class FilteringData { required this.enabled, }); - factory FilteringData.fromJson(Map json) => FilteringData( + factory Filtering.fromJson(Map json) => Filtering( filters: json["filters"] != null ? List.from(json["filters"].map((x) => Filter.fromJson(x))) : [], whitelistFilters: json["whitelist_filters"] != null ? List.from(json["whitelist_filters"].map((x) => Filter.fromJson(x))) : [], userRules: json["user_rules"] != null ? List.from(json["user_rules"].map((x) => x)).where((i) => i != '').toList() : [], diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart index df5d584..ae6955c 100644 --- a/lib/providers/clients_provider.dart +++ b/lib/providers/clients_provider.dart @@ -2,18 +2,9 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; class ClientsProvider with ChangeNotifier { - ServersProvider? _serversProvider; - - update(ServersProvider? serversProvider) { - if (serversProvider != null) { - _serversProvider = serversProvider; - } - } - LoadStatus _loadStatus = LoadStatus.loading; Clients? _clients; String? _searchTermClients; diff --git a/lib/providers/filters_provider.dart b/lib/providers/filters_provider.dart index bb82913..f7734b8 100644 --- a/lib/providers/filters_provider.dart +++ b/lib/providers/filters_provider.dart @@ -1,13 +1,81 @@ import 'package:flutter/material.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/blocked_services.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; -class FiltersProvider with ChangeNotifier { - ServersProvider? _serversProvider; +class FilteringProvider with ChangeNotifier { + StatusProvider? _statusProvider; - update(ServersProvider? serversProvider) { - if (serversProvider != null) { - _serversProvider = serversProvider; + updateStatus(StatusProvider? statusProvider) { + if (statusProvider != null) { + _statusProvider = statusProvider; + } + } + + LoadStatus _loadStatus = LoadStatus.loading; + Filtering? _filtering; + LoadStatus _blockedServicesLoadStatus = LoadStatus.loading; + BlockedServices? _blockedServicesList; + + LoadStatus get loadStatus { + return _loadStatus; + } + + Filtering? get filtering { + return _filtering; + } + + LoadStatus get blockedServicesLoadStatus { + return _blockedServicesLoadStatus; + } + + BlockedServices? get blockedServices { + return _blockedServicesList; + } + + void setFilteringData(Filtering data) { + _filtering = data; + notifyListeners(); + } + + void setFilteringLoadStatus(LoadStatus loadStatus, bool notify) { + _loadStatus = loadStatus; + if (notify == true) { + notifyListeners(); + } + } + + void setFilteringProtectionStatus(bool status) { + _statusProvider!.setFilteringEnabledStatus(status); + _filtering!.enabled = status; + notifyListeners(); + } + + void setFiltersUpdateFrequency(int frequency) { + if (_filtering != null) { + _filtering!.interval = frequency; + notifyListeners(); + } + } + + void setBlockedServices(List blockedServices) { + if (_filtering != null) { + _filtering!.blockedServices = blockedServices; + notifyListeners(); + } + } + + void setBlockedServiceListData(List data) { + _blockedServicesList = BlockedServices(services: data); + notifyListeners(); + } + + void setBlockedServicesListLoadStatus(LoadStatus status, bool notify) { + _blockedServicesLoadStatus = status; + if (notify == true) { + notifyListeners(); } } } \ No newline at end of file diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index fdae694..9c3d3a7 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -3,17 +3,8 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/logs.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class LogsProvider with ChangeNotifier { - ServersProvider? _serversProvider; - - update(ServersProvider? serversProvider) { - if (serversProvider != null) { - _serversProvider = serversProvider; - } - } - int _loadStatus = 0; LogsData? _logsData; List? _clients; diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 6a8b391..c34a27b 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -1,11 +1,9 @@ import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; -import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; -import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -13,27 +11,13 @@ import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/services/db/queries.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; class ServersProvider with ChangeNotifier { - StatusProvider? _statusProvider; - - update(StatusProvider? statusProvider) { - if (statusProvider != null) { - _statusProvider = statusProvider; - } - } - Database? _dbInstance; List _serversList = []; Server? _selectedServer; - final Filtering _filtering = Filtering( - loadStatus: LoadStatus.loading, - data: null - ); - final DhcpModel _dhcp = DhcpModel( loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error data: null @@ -49,11 +33,6 @@ class ServersProvider with ChangeNotifier { data: null ); - final BlockedServices _blockedServicesList = BlockedServices( - loadStatus: 0, - services: null - ); - final UpdateAvailable _updateAvailable = UpdateAvailable( loadStatus: LoadStatus.loading, data: null, @@ -67,10 +46,6 @@ class ServersProvider with ChangeNotifier { return _selectedServer; } - Filtering get filtering { - return _filtering; - } - DhcpModel get dhcp { return _dhcp; } @@ -83,10 +58,6 @@ class ServersProvider with ChangeNotifier { return _dnsInfo; } - BlockedServices get blockedServicesList { - return _blockedServicesList; - } - UpdateAvailable get updateAvailable { return _updateAvailable; } @@ -105,34 +76,6 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setFilteringData(FilteringData data) { - _filtering.data = data; - notifyListeners(); - } - - void setFilteringLoadStatus(LoadStatus loadStatus, bool notify) { - _filtering.loadStatus = loadStatus; - if (notify == true) { - notifyListeners(); - } - } - - void setFilteringProtectionStatus(bool status) { - _statusProvider!.setFilteringEnabledStatus(status); - _filtering.data!.enabled = status; - notifyListeners(); - } - - void setFiltersUpdateFrequency(int frequency) { - _filtering.data!.interval = frequency; - notifyListeners(); - } - - void setBlockedServices(List blockedServices) { - _filtering.data!.blockedServices = blockedServices; - notifyListeners(); - } - void setDhcpData(DhcpData data) { _dhcp.data = data; notifyListeners(); @@ -169,18 +112,6 @@ class ServersProvider with ChangeNotifier { } } - void setBlockedServiceListData(List data) { - _blockedServicesList.services = data; - notifyListeners(); - } - - void setBlockedServicesListLoadStatus(int status, bool notify) { - _blockedServicesList.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } - void setUpdateAvailableLoadStatus(LoadStatus status, bool notify) { _updateAvailable.loadStatus = status; if (notify == true) { diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 43d3ee4..1ba9d30 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -1,8 +1,7 @@ -import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:flutter/material.dart'; import 'package:adguard_home_manager/models/server_status.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/time_server_disabled.dart'; @@ -10,20 +9,9 @@ import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; class StatusProvider with ChangeNotifier { - ServersProvider? _serversProvider; - - update(ServersProvider? serversProvider) { - if (serversProvider != null) { - _serversProvider = serversProvider; - } - } - LoadStatus _loadStatus = LoadStatus.loading; - ServerStatus? _serverStatus; // serverStatus != null means server is connected - List _protectionsManagementProcess = []; // protections that are currenty being enabled or disabled - FilteringStatus? _filteringStatus; LoadStatus get loadStatus { diff --git a/lib/screens/clients/services_modal.dart b/lib/screens/clients/services_modal.dart index fa5c2aa..96dddd2 100644 --- a/lib/screens/clients/services_modal.dart +++ b/lib/screens/clients/services_modal.dart @@ -3,10 +3,12 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; -class ServicesModal extends StatelessWidget { +class ServicesModal extends StatefulWidget { final List blockedServices; final void Function(List) onConfirm; @@ -17,55 +19,33 @@ class ServicesModal extends StatelessWidget { }) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return ServicesModalWidget( - blockedServices: blockedServices, - onConfirm: onConfirm, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _ServicesModalStateWidget(); } -class ServicesModalWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - final List blockedServices; - final void Function(List) onConfirm; - - const ServicesModalWidget({ - Key? key, - required this.blockedServices, - required this.onConfirm, - required this.serversProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _ServicesModalStateWidget(); -} - -class _ServicesModalStateWidget extends State { +class _ServicesModalStateWidget extends State { List blockedServices = []; Future loadBlockedServices() async { - final result = await getBlockedServices(server: widget.serversProvider.selectedServer!); + final filteringProvider = Provider.of(context, listen: false); + final serversProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + + final result = await getBlockedServices(server: serversProvider.selectedServer!); if (result['result'] == 'success') { - widget.serversProvider.setBlockedServicesListLoadStatus(1, true); - widget.serversProvider.setBlockedServiceListData(result['data']); + filteringProvider.setBlockedServicesListLoadStatus(LoadStatus.loaded, true); + filteringProvider.setBlockedServiceListData(result['data']); } else { - widget.serversProvider.setBlockedServicesListLoadStatus(2, true); - widget.appConfigProvider.addLog(result['log']); + filteringProvider.setBlockedServicesListLoadStatus(LoadStatus.error, true); + appConfigProvider.addLog(result['log']); } } @override void initState() { - if (widget.serversProvider.blockedServicesList.loadStatus != 1) { + final filteringProvider = Provider.of(context, listen: false); + + if (filteringProvider.blockedServicesLoadStatus != LoadStatus.loaded) { loadBlockedServices(); } @@ -89,10 +69,11 @@ class _ServicesModalStateWidget extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); Widget content() { - switch (serversProvider.blockedServicesList.loadStatus) { - case 0: + switch (filteringProvider.blockedServicesLoadStatus) { + case LoadStatus.loading: return Padding( padding: const EdgeInsets.all(24), child: SizedBox( @@ -116,34 +97,34 @@ class _ServicesModalStateWidget extends State { ), ); - case 1: + case LoadStatus.loaded: return SizedBox( width: double.minPositive, height: MediaQuery.of(context).size.height*0.5, child: ListView.builder( shrinkWrap: true, - itemCount: serversProvider.blockedServicesList.services!.length, + itemCount: filteringProvider.blockedServices!.services.length, itemBuilder: (context, index) => CheckboxListTile( title: Padding( padding: const EdgeInsets.only(left: 10), child: Text( - serversProvider.blockedServicesList.services![index].name, + filteringProvider.blockedServices!.services[index].name, style: TextStyle( fontWeight: FontWeight.normal, color: Theme.of(context).colorScheme.onSurface ), ), ), - value: blockedServices.contains(serversProvider.blockedServicesList.services![index].id), + value: blockedServices.contains(filteringProvider.blockedServices!.services[index].id), checkboxShape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5) ), - onChanged: (value) => checkUncheckService(value!, serversProvider.blockedServicesList.services![index].id) + onChanged: (value) => checkUncheckService(value!, filteringProvider.blockedServices!.services[index].id) ) ), ); - case 2: + case LoadStatus.error: return Padding( padding: const EdgeInsets.all(24), child: SizedBox( diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 1a86671..325709e 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -9,12 +9,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_custom_rule.dart'; import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; +import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class AddFiltersButton extends StatelessWidget { @@ -30,6 +31,7 @@ class AddFiltersButton extends StatelessWidget { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -38,7 +40,7 @@ class AddFiltersButton extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingRule); - final List newRules = serversProvider.filtering.data!.userRules; + final List newRules = filteringProvider.filtering!.userRules; newRules.add(rule); final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules); @@ -46,9 +48,9 @@ class AddFiltersButton extends StatelessWidget { processModal.close(); if (result['result'] == 'success') { - FilteringData filteringData = serversProvider.filtering.data!; + Filtering filteringData = filteringProvider.filtering!; filteringData.userRules = newRules; - serversProvider.setFilteringData(filteringData); + filteringProvider.setFilteringData(filteringData); showSnacbkar( appConfigProvider: appConfigProvider, @@ -107,12 +109,12 @@ class AddFiltersButton extends StatelessWidget { final items = result1['data'].toString().split(' ')[1]; if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + filteringProvider.setFilteringData(result2['data']); + filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, true); } else { appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); + filteringProvider.setFilteringLoadStatus(LoadStatus.error, true); } processModal.close(); diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/blocked_services_screen.dart index 85d2d23..4e9ee03 100644 --- a/lib/screens/filters/blocked_services_screen.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -7,11 +7,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class BlockedServicesScreen extends StatelessWidget { +class BlockedServicesScreen extends StatefulWidget { final bool dialog; const BlockedServicesScreen({ @@ -20,56 +22,37 @@ class BlockedServicesScreen extends StatelessWidget { }) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return BlockedServicesScreenWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - dialog: dialog, - ); - } + State createState() => _BlockedServicesScreenStateWidget(); } -class BlockedServicesScreenWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - final bool dialog; - - const BlockedServicesScreenWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - required this.dialog - }) : super(key: key); - - @override - State createState() => _BlockedServicesScreenStateWidget(); -} - -class _BlockedServicesScreenStateWidget extends State { +class _BlockedServicesScreenStateWidget extends State { List values = []; Future loadBlockedServices() async { - final result = await getBlockedServices(server: widget.serversProvider.selectedServer!); + final serversProvider = Provider.of(context, listen: false); + final filteringProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + + final result = await getBlockedServices(server: serversProvider.selectedServer!); if (result['result'] == 'success') { - widget.serversProvider.setBlockedServicesListLoadStatus(1, true); - widget.serversProvider.setBlockedServiceListData(result['data']); + filteringProvider.setBlockedServicesListLoadStatus(LoadStatus.loaded, true); + filteringProvider.setBlockedServiceListData(result['data']); } else { - widget.serversProvider.setBlockedServicesListLoadStatus(2, true); - widget.appConfigProvider.addLog(result['log']); + filteringProvider.setBlockedServicesListLoadStatus(LoadStatus.loaded, true); + appConfigProvider.addLog(result['log']); } } @override void initState() { - if (widget.serversProvider.blockedServicesList.loadStatus != 1) { + final filteringProvider = Provider.of(context, listen: false); + + if (filteringProvider.blockedServicesLoadStatus != LoadStatus.loaded) { loadBlockedServices(); } - values = widget.serversProvider.filtering.data!.blockedServices; + values = filteringProvider.filtering!.blockedServices; super.initState(); } @@ -77,6 +60,7 @@ class _BlockedServicesScreenStateWidget extends State(context); + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void updateValues(bool value, BlockedService item) { @@ -101,7 +85,7 @@ class _BlockedServicesScreenStateWidget extends State Material( color: Colors.transparent, child: InkWell( onTap: () => updateValues( - values.contains(serversProvider.blockedServicesList.services![index].id), - serversProvider.blockedServicesList.services![index] + values.contains(filteringProvider.blockedServices!.services![index].id), + filteringProvider.blockedServices!.services![index] ), child: Padding( padding: const EdgeInsets.only( @@ -163,17 +147,17 @@ class _BlockedServicesScreenStateWidget extends State updateValues( value!, - serversProvider.blockedServicesList.services![index] + filteringProvider.blockedServices!.services![index] ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5) @@ -186,7 +170,7 @@ class _BlockedServicesScreenStateWidget extends State(context); - final appConfigProvider = Provider.of(context); - - return FiltersWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider - ); - } + State createState() => _FiltersState(); } -class FiltersWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const FiltersWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _FiltersWidgetState(); -} - -class _FiltersWidgetState extends State { +class _FiltersState extends State { Future fetchFilters() async { - widget.serversProvider.setFilteringLoadStatus(LoadStatus.loading, false); + final filteringProvider = Provider.of(context, listen: false); + final serversProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); - final result = await getFiltering(server: widget.serversProvider.selectedServer!); + filteringProvider.setFilteringLoadStatus(LoadStatus.loading, false); + + final result = await getFiltering(server: serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { - widget.serversProvider.setFilteringData(result['data']); - widget.serversProvider.setFilteringLoadStatus(LoadStatus.loaded, false); + filteringProvider.setFilteringData(result['data']); + filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, false); } else { - widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setFilteringLoadStatus(LoadStatus.error, false); + appConfigProvider.addLog(result['log']); + filteringProvider.setFilteringLoadStatus(LoadStatus.error, false); } } } @@ -84,6 +67,7 @@ class _FiltersWidgetState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -96,13 +80,13 @@ class _FiltersWidgetState extends State { final result = await updateLists(server: serversProvider.selectedServer!); if (result['result'] == 'success') { - final result2 = await getFiltering(server: widget.serversProvider.selectedServer!); + final result2 = await getFiltering(server: serversProvider.selectedServer!); processModal.close(); if (mounted) { if (result2['result'] == 'success') { - widget.serversProvider.setFilteringData(result2['data']); + filteringProvider.setFilteringData(result2['data']); showSnacbkar( appConfigProvider: appConfigProvider, @@ -111,7 +95,7 @@ class _FiltersWidgetState extends State { ); } else { - widget.appConfigProvider.addLog(result2['log']); + appConfigProvider.addLog(result2['log']); showSnacbkar( appConfigProvider: appConfigProvider, @@ -173,7 +157,7 @@ class _FiltersWidgetState extends State { processModal.close(); if (result['result'] == 'success') { - serversProvider.setFilteringProtectionStatus(!statusProvider.serverStatus!.filteringEnabled); + filteringProvider.setFilteringProtectionStatus(!statusProvider.serverStatus!.filteringEnabled); showSnacbkar( appConfigProvider: appConfigProvider, @@ -195,14 +179,14 @@ class _FiltersWidgetState extends State { processModal.open(AppLocalizations.of(context)!.changingUpdateFrequency); final result = await requestChangeUpdateFrequency(server: serversProvider.selectedServer!, data: { - "enabled": serversProvider.filtering.data!.enabled, + "enabled": filteringProvider.filtering!.enabled, "interval": value }); processModal.close(); if (result['result'] == 'success') { - serversProvider.setFiltersUpdateFrequency(value); + filteringProvider.setFiltersUpdateFrequency(value); showSnacbkar( appConfigProvider: appConfigProvider, @@ -246,16 +230,16 @@ class _FiltersWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deletingRule); - final List newRules = serversProvider.filtering.data!.userRules.where((r) => r != rule).toList(); + final List newRules = filteringProvider.filtering!.userRules.where((r) => r != rule).toList(); final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules); processModal.close(); if (result['result'] == 'success') { - FilteringData filteringData = serversProvider.filtering.data!; + Filtering filteringData = filteringProvider.filtering!; filteringData.userRules = newRules; - serversProvider.setFilteringData(filteringData); + filteringProvider.setFilteringData(filteringData); showSnacbkar( appConfigProvider: appConfigProvider, @@ -309,11 +293,11 @@ class _FiltersWidgetState extends State { } List actions() { - if (serversProvider.filtering.loadStatus == LoadStatus.loaded) { + if (filteringProvider.loadStatus == LoadStatus.loaded) { return [ IconButton( onPressed: enableDisableFiltering, - tooltip: serversProvider.filtering.data!.enabled == true + tooltip: filteringProvider.filtering!.enabled == true ? AppLocalizations.of(context)!.disableFiltering : AppLocalizations.of(context)!.enableFiltering, icon: Stack( @@ -330,11 +314,11 @@ class _FiltersWidgetState extends State { color: Colors.white ), child: Icon( - serversProvider.filtering.data!.enabled == true + filteringProvider.filtering!.enabled == true ? Icons.check_circle_rounded : Icons.cancel, size: 12, - color: serversProvider.filtering.data!.enabled == true + color: filteringProvider.filtering!.enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -355,7 +339,7 @@ class _FiltersWidgetState extends State { showDialog( context: context, builder: (context) => UpdateIntervalListsModal( - interval: serversProvider.filtering.data!.interval, + interval: filteringProvider.filtering!.interval, onChange: setUpdateFrequency, dialog: true, ), @@ -365,7 +349,7 @@ class _FiltersWidgetState extends State { showModalBottomSheet( context: context, builder: (context) => UpdateIntervalListsModal( - interval: serversProvider.filtering.data!.interval, + interval: filteringProvider.filtering!.interval, onChange: setUpdateFrequency, dialog: false, ), diff --git a/lib/screens/filters/filters_tabs_view.dart b/lib/screens/filters/filters_tabs_view.dart index 17f74a9..9e8a7f9 100644 --- a/lib/screens/filters/filters_tabs_view.dart +++ b/lib/screens/filters/filters_tabs_view.dart @@ -5,6 +5,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/custom_rules_list.dart'; import 'package:adguard_home_manager/screens/filters/filters_list.dart'; +import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -49,6 +50,7 @@ class _FiltersTabsViewState extends State with TickerProviderSt @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); return DefaultTabController( length: 3, @@ -110,28 +112,28 @@ class _FiltersTabsViewState extends State with TickerProviderSt controller: tabController, children: [ FiltersList( - loadStatus: serversProvider.filtering.loadStatus, + loadStatus: filteringProvider.loadStatus, scrollController: scrollController, type: 'whitelist', - data: serversProvider.filtering.loadStatus == LoadStatus.loaded - ? serversProvider.filtering.data!.whitelistFilters : [], + data: filteringProvider.loadStatus == LoadStatus.loaded + ? filteringProvider.filtering!.whitelistFilters : [], fetchData: widget.fetchFilters, onOpenDetailsScreen: widget.onOpenDetailsModal, ), FiltersList( - loadStatus: serversProvider.filtering.loadStatus, + loadStatus: filteringProvider.loadStatus, scrollController: scrollController, type: 'blacklist', - data: serversProvider.filtering.loadStatus == LoadStatus.loaded - ? serversProvider.filtering.data!.filters : [], + data: filteringProvider.loadStatus == LoadStatus.loaded + ? filteringProvider.filtering!.filters : [], fetchData: widget.fetchFilters, onOpenDetailsScreen: widget.onOpenDetailsModal, ), CustomRulesList( - loadStatus: serversProvider.filtering.loadStatus, + loadStatus: filteringProvider.loadStatus, scrollController: scrollController, - data: serversProvider.filtering.loadStatus == LoadStatus.loaded - ? serversProvider.filtering.data!.userRules : [], + data: filteringProvider.loadStatus == LoadStatus.loaded + ? filteringProvider.filtering!.userRules : [], fetchData: widget.fetchFilters, onRemoveCustomRule: widget.onRemoveCustomRule, ), diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index d8bc00a..5cccede 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -15,6 +15,7 @@ import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; +import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -37,6 +38,7 @@ class FiltersTripleColumn extends StatelessWidget { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); bool checkIfComment(String value) { @@ -84,7 +86,7 @@ class FiltersTripleColumn extends StatelessWidget { } Widget content() { - switch (serversProvider.filtering.loadStatus) { + switch (filteringProvider.loadStatus) { case LoadStatus.loading: return Row( mainAxisAlignment: MainAxisAlignment.center, @@ -140,18 +142,18 @@ class FiltersTripleColumn extends StatelessWidget { ), Expanded( child: ListView.builder( - itemCount: serversProvider.filtering.data!.whitelistFilters.length, + itemCount: filteringProvider.filtering!.whitelistFilters.length, itemBuilder: (context, index) => ListOptionsMenu( - list: serversProvider.filtering.data!.whitelistFilters[index], + list: filteringProvider.filtering!.whitelistFilters[index], listType: 'whitelist', child: CustomListTile( - title: serversProvider.filtering.data!.whitelistFilters[index].name, - subtitle: "${intFormat(serversProvider.filtering.data!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + title: filteringProvider.filtering!.whitelistFilters[index].name, + subtitle: "${intFormat(filteringProvider.filtering!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", trailing: Icon( - serversProvider.filtering.data!.whitelistFilters[index].enabled == true + filteringProvider.filtering!.whitelistFilters[index].enabled == true ? Icons.check_circle_rounded : Icons.cancel, - color: serversProvider.filtering.data!.whitelistFilters[index].enabled == true + color: filteringProvider.filtering!.whitelistFilters[index].enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -159,7 +161,7 @@ class FiltersTripleColumn extends StatelessWidget { ? Colors.grey : Colors.red ), - onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.whitelistFilters[index], 'whitelist'), + onTap: () => onOpenDetailsModal(filteringProvider.filtering!.whitelistFilters[index], 'whitelist'), ), ), ), @@ -196,18 +198,18 @@ class FiltersTripleColumn extends StatelessWidget { ), Expanded( child: ListView.builder( - itemCount: serversProvider.filtering.data!.filters.length, + itemCount: filteringProvider.filtering!.filters.length, itemBuilder: (context, index) => ListOptionsMenu( - list: serversProvider.filtering.data!.filters[index], + list: filteringProvider.filtering!.filters[index], listType: 'blacklist', child: CustomListTile( - title: serversProvider.filtering.data!.filters[index].name, - subtitle: "${intFormat(serversProvider.filtering.data!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + title: filteringProvider.filtering!.filters[index].name, + subtitle: "${intFormat(filteringProvider.filtering!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", trailing: Icon( - serversProvider.filtering.data!.filters[index].enabled == true + filteringProvider.filtering!.filters[index].enabled == true ? Icons.check_circle_rounded : Icons.cancel, - color: serversProvider.filtering.data!.filters[index].enabled == true + color: filteringProvider.filtering!.filters[index].enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -215,7 +217,7 @@ class FiltersTripleColumn extends StatelessWidget { ? Colors.grey : Colors.red ), - onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.filters[index], 'blacklist'), + onTap: () => onOpenDetailsModal(filteringProvider.filtering!.filters[index], 'blacklist'), ), ), ), @@ -252,7 +254,7 @@ class FiltersTripleColumn extends StatelessWidget { ), Expanded( child: ListView.builder( - itemCount: serversProvider.filtering.data!.userRules.length, + itemCount: filteringProvider.filtering!.userRules.length, itemBuilder: (context, index) => ContextMenuArea( builder: (context) => [ CustomListTile( @@ -261,7 +263,7 @@ class FiltersTripleColumn extends StatelessWidget { onTap: () { copyToClipboard( context: context, - value: serversProvider.filtering.data!.userRules[index], + value: filteringProvider.filtering!.userRules[index], successMessage: AppLocalizations.of(context)!.copiedClipboard, ); Navigator.pop(context); @@ -278,17 +280,17 @@ class FiltersTripleColumn extends StatelessWidget { icon: Icons.copy_rounded, action: () => copyToClipboard( context: context, - value: serversProvider.filtering.data!.userRules[index], + value: filteringProvider.filtering!.userRules[index], successMessage: AppLocalizations.of(context)!.copiedClipboard, ) ) ] ) ), - title: serversProvider.filtering.data!.userRules[index], - subtitleWidget: generateSubtitle(serversProvider.filtering.data!.userRules[index]), + title: filteringProvider.filtering!.userRules[index], + subtitleWidget: generateSubtitle(filteringProvider.filtering!.userRules[index]), trailing: IconButton( - onPressed: () => onRemoveCustomRule(serversProvider.filtering.data!.userRules[index]), + onPressed: () => onRemoveCustomRule(filteringProvider.filtering!.userRules[index]), icon: const Icon(Icons.delete) ), ), diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 0117390..723c471 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -13,6 +13,7 @@ import 'package:adguard_home_manager/screens/filters/list_functions.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; +import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -61,16 +62,17 @@ class _ListDetailsScreenState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; Filter? list; try { - list = serversProvider.filtering.data != null + list = filteringProvider.filtering != null ? widget.type == 'whitelist' - ? serversProvider.filtering.data!.whitelistFilters.firstWhere((l) => l.id == widget.listId) - : serversProvider.filtering.data!.filters.firstWhere((l) => l.id == widget.listId) + ? filteringProvider.filtering!.whitelistFilters.firstWhere((l) => l.id == widget.listId) + : filteringProvider.filtering!.filters.firstWhere((l) => l.id == widget.listId) : null; } catch (e) { // ------- // @@ -177,8 +179,6 @@ class _ListDetailsScreenState extends State { onEdit: ({required Filter list, required String type}) async { final result = await editList( context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, list: list, type: widget.type ); @@ -210,8 +210,6 @@ class _ListDetailsScreenState extends State { onEdit: ({required Filter list, required String type}) async { final result = await editList( context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, list: list, type: widget.type ); @@ -248,8 +246,6 @@ class _ListDetailsScreenState extends State { onConfirm: () async { final result = await deleteList( context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, list: list!, type: widget.type, ); @@ -315,8 +311,6 @@ class _ListDetailsScreenState extends State { onPressed: () async { final result = await enableDisableList( context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, list: list!, listType: widget.type, ); @@ -402,8 +396,6 @@ class _ListDetailsScreenState extends State { onPressed: () async { final result = await enableDisableList( context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, list: list!, listType: widget.type, ); diff --git a/lib/screens/filters/list_functions.dart b/lib/screens/filters/list_functions.dart index 7db194f..312ac5b 100644 --- a/lib/screens/filters/list_functions.dart +++ b/lib/screens/filters/list_functions.dart @@ -1,9 +1,11 @@ // ignore_for_file: use_build_context_synchronously import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -12,11 +14,13 @@ import 'package:adguard_home_manager/services/http_requests.dart'; Future enableDisableList({ required BuildContext context, - required ServersProvider serversProvider, - required AppConfigProvider appConfigProvider, required Filter list, required String listType, }) async { + final serversProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + final filteringProvider = Provider.of(context, listen: false); + ProcessModal processModal = ProcessModal(context: context); processModal.open( list.enabled == true @@ -40,12 +44,12 @@ Future enableDisableList({ final result2 = await getFiltering(server: serversProvider.selectedServer!); if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + filteringProvider.setFilteringData(result2['data']); + filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, true); } else { appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); + filteringProvider.setFilteringLoadStatus(LoadStatus.error, true); } return true; @@ -59,11 +63,13 @@ Future enableDisableList({ Future editList({ required BuildContext context, - required ServersProvider serversProvider, - required AppConfigProvider appConfigProvider, required Filter list, required String type }) async { + final serversProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + final filteringProvider = Provider.of(context, listen: false); + ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingListData); @@ -81,12 +87,12 @@ Future editList({ final result2 = await getFiltering(server: serversProvider.selectedServer!); if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + filteringProvider.setFilteringData(result2['data']); + filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, true); } else { appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); + filteringProvider.setFilteringLoadStatus(LoadStatus.error, true); } processModal.close(); @@ -103,11 +109,13 @@ Future editList({ Future deleteList({ required BuildContext context, - required ServersProvider serversProvider, - required AppConfigProvider appConfigProvider, required Filter list, required String type }) async { + final serversProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + final filteringProvider = Provider.of(context, listen: false); + ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deletingList); @@ -120,12 +128,12 @@ Future deleteList({ final result2 = await getFiltering(server: serversProvider.selectedServer!); if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); + filteringProvider.setFilteringData(result2['data']); + filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, true); } else { appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.loading, true); + filteringProvider.setFilteringLoadStatus(LoadStatus.loading, true); } processModal.close(); diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index f052890..7a9dc2a 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -14,7 +14,6 @@ import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class ListOptionsMenu extends StatelessWidget { final Filter list; @@ -30,14 +29,11 @@ class ListOptionsMenu extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void enableDisable() async { final result = await enableDisableList( context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, list: list, listType: listType, ); diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index cbc95b5..8016da9 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -895,7 +895,7 @@ Future getFiltering({ if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { return { 'result': 'success', - 'data': FilteringData.fromJson({ + 'data': Filtering.fromJson({ ...jsonDecode(result[0]['body']), "blocked_services": result[1]['body'] != null ? jsonDecode(result[1]['body']) From cd4a8aaf4f8dca6c311825580fd542078aae89f8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 15:12:45 +0200 Subject: [PATCH 149/676] Removed unnecessary stuff --- lib/screens/clients/services_modal.dart | 1 - lib/screens/filters/blocked_services_screen.dart | 12 ++++++------ lib/screens/filters/filters_tabs_view.dart | 2 -- lib/screens/filters/filters_triple_column.dart | 14 +------------- lib/screens/filters/list_details_screen.dart | 2 -- 5 files changed, 7 insertions(+), 24 deletions(-) diff --git a/lib/screens/clients/services_modal.dart b/lib/screens/clients/services_modal.dart index 96dddd2..288de9c 100644 --- a/lib/screens/clients/services_modal.dart +++ b/lib/screens/clients/services_modal.dart @@ -68,7 +68,6 @@ class _ServicesModalStateWidget extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final filteringProvider = Provider.of(context); Widget content() { diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/blocked_services_screen.dart index 4e9ee03..eb1bcfe 100644 --- a/lib/screens/filters/blocked_services_screen.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -128,13 +128,13 @@ class _BlockedServicesScreenStateWidget extends State { case LoadStatus.loaded: return ListView.builder( - itemCount: filteringProvider.blockedServices!.services!.length, + itemCount: filteringProvider.blockedServices!.services.length, itemBuilder: (context, index) => Material( color: Colors.transparent, child: InkWell( onTap: () => updateValues( - values.contains(filteringProvider.blockedServices!.services![index].id), - filteringProvider.blockedServices!.services![index] + values.contains(filteringProvider.blockedServices!.services[index].id), + filteringProvider.blockedServices!.services[index] ), child: Padding( padding: const EdgeInsets.only( @@ -147,17 +147,17 @@ class _BlockedServicesScreenStateWidget extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - filteringProvider.blockedServices!.services![index].name, + filteringProvider.blockedServices!.services[index].name, style: TextStyle( fontSize: 16, color: Theme.of(context).colorScheme.onSurface ), ), Checkbox( - value: values.contains(filteringProvider.blockedServices!.services![index].id), + value: values.contains(filteringProvider.blockedServices!.services[index].id), onChanged: (value) => updateValues( value!, - filteringProvider.blockedServices!.services![index] + filteringProvider.blockedServices!.services[index] ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5) diff --git a/lib/screens/filters/filters_tabs_view.dart b/lib/screens/filters/filters_tabs_view.dart index 9e8a7f9..6a36eaf 100644 --- a/lib/screens/filters/filters_tabs_view.dart +++ b/lib/screens/filters/filters_tabs_view.dart @@ -9,7 +9,6 @@ import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class FiltersTabsView extends StatefulWidget { final AppConfigProvider appConfigProvider; @@ -49,7 +48,6 @@ class _FiltersTabsViewState extends State with TickerProviderSt @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final filteringProvider = Provider.of(context); return DefaultTabController( diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 5cccede..d60a237 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -19,7 +19,6 @@ import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class FiltersTripleColumn extends StatelessWidget { final void Function(String) onRemoveCustomRule; @@ -37,20 +36,9 @@ class FiltersTripleColumn extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - - bool checkIfComment(String value) { - final regex = RegExp(r'^(!|#).*$'); - if (regex.hasMatch(value)) { - return true; - } - else { - return false; - } - } - + Widget? generateSubtitle(String rule) { final allowRegex = RegExp(r'^@@.*$'); final blockRegex = RegExp(r'^\|\|.*$'); diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 723c471..9c970a7 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -16,7 +16,6 @@ import 'package:adguard_home_manager/functions/format_time.dart'; import 'package:adguard_home_manager/providers/filters_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; class ListDetailsScreen extends StatefulWidget { @@ -61,7 +60,6 @@ class _ListDetailsScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); From 9460da6dcb642a7a7549b97a18c0f47b3b3e18c2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 18:22:13 +0200 Subject: [PATCH 150/676] Extracted dhcp to external provider --- lib/main.dart | 26 ++++---- lib/models/dhcp.dart | 13 +--- lib/providers/dhcp_provider.dart | 29 +++++++++ lib/providers/servers_provider.dart | 21 ------ lib/screens/settings/dhcp/dhcp.dart | 76 +++++++++------------- lib/screens/settings/dhcp/dhcp_leases.dart | 10 +-- lib/screens/settings/settings.dart | 2 +- lib/services/http_requests.dart | 2 +- 8 files changed, 83 insertions(+), 96 deletions(-) create mode 100644 lib/providers/dhcp_provider.dart diff --git a/lib/main.dart b/lib/main.dart index ddfbe3e..6ea9fb4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,6 +21,7 @@ import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/colors.dart'; @@ -30,7 +31,6 @@ import 'package:adguard_home_manager/config/theme.dart'; import 'package:adguard_home_manager/classes/http_override.dart'; import 'package:adguard_home_manager/services/db/database.dart'; - void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -50,6 +50,7 @@ void main() async { StatusProvider statusProvider = StatusProvider(); ClientsProvider clientsProvider = ClientsProvider(); FilteringProvider filtersProvider = FilteringProvider(); + DhcpProvider dhcpProvider = DhcpProvider(); LogsProvider logsProvider = LogsProvider(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); @@ -97,6 +98,9 @@ void main() async { ChangeNotifierProvider( create: ((context) => serversProvider) ), + ChangeNotifierProvider( + create: ((context) => appConfigProvider) + ), ChangeNotifierProvider( create: ((context) => statusProvider) ), @@ -110,7 +114,7 @@ void main() async { create: ((context) => filtersProvider) ), ChangeNotifierProvider( - create: ((context) => appConfigProvider) + create: ((context) => dhcpProvider) ), ChangeNotifierProxyProvider( create: (context) => filtersProvider, @@ -181,15 +185,15 @@ class _MainState extends State
{ builder: (lightDynamic, darkDynamic) => MaterialApp( title: 'AdGuard Home Manager', theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? lightTheme(lightDynamic) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]), - darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? darkTheme(darkDynamic) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]), + ? appConfigProvider.useDynamicColor == true + ? lightTheme(lightDynamic) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]), + darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 + ? appConfigProvider.useDynamicColor == true + ? darkTheme(darkDynamic) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]), themeMode: appConfigProvider.selectedTheme, debugShowCheckedModeBanner: false, localizationsDelegates: const [ diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index 4910e68..c870b9b 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -1,20 +1,9 @@ import 'dart:convert'; - class DhcpModel { - int loadStatus = 0; - DhcpData? data; - - DhcpModel({ - required this.loadStatus, - this.data, - }); -} - -class DhcpData { List networkInterfaces; DhcpStatus dhcpStatus; - DhcpData({ + DhcpModel({ required this.networkInterfaces, required this.dhcpStatus, }); diff --git a/lib/providers/dhcp_provider.dart b/lib/providers/dhcp_provider.dart new file mode 100644 index 0000000..d03759b --- /dev/null +++ b/lib/providers/dhcp_provider.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/dhcp.dart'; + +class DhcpProvider with ChangeNotifier { + LoadStatus _loadStatus = LoadStatus.loading; + DhcpModel? _dhcp; + + DhcpModel? get dhcp { + return _dhcp; + } + + LoadStatus get loadStatus { + return _loadStatus; + } + + void setDhcpData(DhcpModel data) { + _dhcp = data; + notifyListeners(); + } + + void setDhcpLoadStatus(LoadStatus status, bool notify) { + _loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } +} \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index c34a27b..eb795a8 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -18,11 +18,6 @@ class ServersProvider with ChangeNotifier { List _serversList = []; Server? _selectedServer; - final DhcpModel _dhcp = DhcpModel( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error - data: null - ); - final RewriteRules _rewriteRules = RewriteRules( loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error data: null @@ -46,10 +41,6 @@ class ServersProvider with ChangeNotifier { return _selectedServer; } - DhcpModel get dhcp { - return _dhcp; - } - RewriteRules get rewriteRules { return _rewriteRules; } @@ -75,18 +66,6 @@ class ServersProvider with ChangeNotifier { _selectedServer = server; notifyListeners(); } - - void setDhcpData(DhcpData data) { - _dhcp.data = data; - notifyListeners(); - } - - void setDhcpLoadStatus(int status, bool notify) { - _dhcp.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } void setRewriteRulesData(List data) { _rewriteRules.data = data; diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index c45dfd7..1e9d796 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -13,42 +13,22 @@ import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_leases.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/select_interface_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class Dhcp extends StatelessWidget { - const Dhcp({Key? key}) : super(key: key); +class DhcpScreen extends StatefulWidget { + const DhcpScreen({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return DhcpWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider - ); - } + State createState() => _DhcpScreenState(); } -class DhcpWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const DhcpWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _DhcpWidgetState(); -} - -class _DhcpWidgetState extends State { +class _DhcpScreenState extends State { NetworkInterface? selectedInterface; bool enabled = false; @@ -74,17 +54,20 @@ class _DhcpWidgetState extends State { bool dataValid = false; void loadDhcpStatus() async { - widget.serversProvider.setDhcpLoadStatus(0, false); + final serversProvider = Provider.of(context, listen: false); + final dhcpProvider = Provider.of(context, listen: false); - final result = await getDhcpData(server: widget.serversProvider.selectedServer!); + dhcpProvider.setDhcpLoadStatus(LoadStatus.loading, false); + + final result = await getDhcpData(server: serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { - widget.serversProvider.setDhcpLoadStatus(1, true); - widget.serversProvider.setDhcpData(result['data']); + dhcpProvider.setDhcpData(result['data']); + dhcpProvider.setDhcpLoadStatus(LoadStatus.loaded, true); setState(() { if (result['data'].dhcpStatus.interfaceName != '') { - selectedInterface = result['data'].networkInterfaces.firstWhere((interface) => interface.name == result['data'].dhcpStatus.interfaceName); + selectedInterface = result['data'].networkInterfaces.firstWhere((iface) => iface.name == result['data'].dhcpStatus.interfaceName); enabled = result['data'].dhcpStatus.enabled; ipv4StartRangeController.text = result['data'].dhcpStatus.v4.rangeStart; @@ -97,7 +80,7 @@ class _DhcpWidgetState extends State { }); } else { - widget.serversProvider.setDhcpLoadStatus(2, true); + dhcpProvider.setDhcpLoadStatus(LoadStatus.error, true); } } checkDataValid(); @@ -213,6 +196,7 @@ class _DhcpWidgetState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dhcpProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -298,10 +282,10 @@ class _DhcpWidgetState extends State { processModal.close(); if (result['result'] == 'success') { - DhcpData data = serversProvider.dhcp.data!; + DhcpModel data = dhcpProvider.dhcp!; data.dhcpStatus.staticLeases = []; data.dhcpStatus.leases = []; - serversProvider.setDhcpData(data); + dhcpProvider.setDhcpData(data); showSnacbkar( appConfigProvider: appConfigProvider, @@ -356,7 +340,7 @@ class _DhcpWidgetState extends State { showDialog( context: context, builder: (context) => SelectInterfaceModal( - interfaces: serversProvider.dhcp.data!.networkInterfaces, + interfaces: dhcpProvider.dhcp!.networkInterfaces, onSelect: (interface) => setState(() { clearAll(); selectedInterface = interface; @@ -369,7 +353,7 @@ class _DhcpWidgetState extends State { showModalBottomSheet( context: context, builder: (context) => SelectInterfaceModal( - interfaces: serversProvider.dhcp.data!.networkInterfaces, + interfaces: dhcpProvider.dhcp!.networkInterfaces, onSelect: (i) => setState(() { clearAll(); selectedInterface = i; @@ -383,8 +367,8 @@ class _DhcpWidgetState extends State { } Widget generateBody() { - switch (serversProvider.dhcp.loadStatus) { - case 0: + switch (dhcpProvider.loadStatus) { + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -404,7 +388,7 @@ class _DhcpWidgetState extends State { ), ); - case 1: + case LoadStatus.loaded: if (selectedInterface != null) { return SingleChildScrollView( child: Wrap( @@ -683,7 +667,7 @@ class _DhcpWidgetState extends State { onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.leases, + items: dhcpProvider.dhcp!.dhcpStatus.leases, staticLeases: false, ) )); @@ -716,7 +700,7 @@ class _DhcpWidgetState extends State { onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, staticLeases: true, ) )); @@ -751,7 +735,7 @@ class _DhcpWidgetState extends State { if (!(Platform.isAndroid || Platform.isIOS)) { SplitView.of(context).push( DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.leases, + items: dhcpProvider.dhcp!.dhcpStatus.leases, staticLeases: false, ) ); @@ -759,7 +743,7 @@ class _DhcpWidgetState extends State { else { Navigator.push(context, MaterialPageRoute( builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.leases, + items: dhcpProvider.dhcp!.dhcpStatus.leases, staticLeases: false, ) )); @@ -778,7 +762,7 @@ class _DhcpWidgetState extends State { if (!(Platform.isAndroid || Platform.isIOS)) { SplitView.of(context).push( DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, staticLeases: true, ) ); @@ -786,7 +770,7 @@ class _DhcpWidgetState extends State { else { Navigator.push(context, MaterialPageRoute( builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, staticLeases: true, ) )); @@ -840,7 +824,7 @@ class _DhcpWidgetState extends State { ); } - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index 39a3303..ede2ef1 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -10,6 +10,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/delete_static_lease_modal.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/add_static_lease_modal.dart'; +import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -30,6 +31,7 @@ class DhcpLeases extends StatelessWidget { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dhcpProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -47,9 +49,9 @@ class DhcpLeases extends StatelessWidget { processModal.close(); if (result['result'] == 'success') { - DhcpData data = serversProvider.dhcp.data!; + DhcpModel data = dhcpProvider.dhcp!; data.dhcpStatus.staticLeases = data.dhcpStatus.staticLeases.where((l) => l.mac != lease.mac).toList(); - serversProvider.setDhcpData(data); + dhcpProvider.setDhcpData(data); showSnacbkar( appConfigProvider: appConfigProvider, @@ -80,9 +82,9 @@ class DhcpLeases extends StatelessWidget { processModal.close(); if (result['result'] == 'success') { - DhcpData data = serversProvider.dhcp.data!; + DhcpModel data = dhcpProvider.dhcp!; data.dhcpStatus.staticLeases.add(lease); - serversProvider.setDhcpData(data); + dhcpProvider.setDhcpData(data); showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 4586b28..d08c322 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -156,7 +156,7 @@ class SettingsWidget extends StatelessWidget { title: AppLocalizations.of(context)!.dhcpSettings, subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, thisItem: 2, - screenToNavigate: const Dhcp(), + screenToNavigate: const DhcpScreen(), ), settingsTile( icon: Icons.dns_rounded, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 8016da9..3997dfd 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1289,7 +1289,7 @@ Future getDhcpData({ return { 'result': 'success', - 'data': DhcpData( + 'data': DhcpModel( networkInterfaces: interfaces, dhcpStatus: DhcpStatus.fromJson(jsonDecode(result[1]['body'])) ) From 5afe912e7e62669f0cb065f76fb72bfd860354e5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 19:12:11 +0200 Subject: [PATCH 151/676] Extracted dns rewrites --- lib/main.dart | 19 +++-- lib/models/rewrite_rules.dart | 20 +---- lib/providers/rewrute_rules_provider.dart | 29 +++++++ lib/providers/servers_provider.dart | 22 ------ .../dns_rewrites/add_dns_rewrite_modal.dart | 4 +- .../settings/dns_rewrites/dns_rewrites.dart | 79 ++++++++----------- lib/screens/settings/settings.dart | 2 +- lib/services/http_requests.dart | 4 +- 8 files changed, 80 insertions(+), 99 deletions(-) create mode 100644 lib/providers/rewrute_rules_provider.dart diff --git a/lib/main.dart b/lib/main.dart index 6ea9fb4..7582e48 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,6 +21,7 @@ import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/rewrute_rules_provider.dart'; import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -45,13 +46,14 @@ void main() async { await dotenv.load(fileName: '.env'); - AppConfigProvider appConfigProvider = AppConfigProvider(); - ServersProvider serversProvider = ServersProvider(); - StatusProvider statusProvider = StatusProvider(); - ClientsProvider clientsProvider = ClientsProvider(); - FilteringProvider filtersProvider = FilteringProvider(); - DhcpProvider dhcpProvider = DhcpProvider(); - LogsProvider logsProvider = LogsProvider(); + final AppConfigProvider appConfigProvider = AppConfigProvider(); + final ServersProvider serversProvider = ServersProvider(); + final StatusProvider statusProvider = StatusProvider(); + final ClientsProvider clientsProvider = ClientsProvider(); + final FilteringProvider filtersProvider = FilteringProvider(); + final DhcpProvider dhcpProvider = DhcpProvider(); + final RewriteRulesProvider rewriteRulesProvider = RewriteRulesProvider(); + final LogsProvider logsProvider = LogsProvider(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); if (Platform.isAndroid) { @@ -116,6 +118,9 @@ void main() async { ChangeNotifierProvider( create: ((context) => dhcpProvider) ), + ChangeNotifierProvider( + create: ((context) => rewriteRulesProvider) + ), ChangeNotifierProxyProvider( create: (context) => filtersProvider, update: (context, status, filtering) => filtering!..updateStatus(status), diff --git a/lib/models/rewrite_rules.dart b/lib/models/rewrite_rules.dart index 44bef8d..5af2851 100644 --- a/lib/models/rewrite_rules.dart +++ b/lib/models/rewrite_rules.dart @@ -1,29 +1,13 @@ -import 'dart:convert'; - class RewriteRules { - int loadStatus = 0; - List? data; - - RewriteRules({ - required this.loadStatus, - this.data - }); -} - -List rewriteRulesDataFromJson(String str) => List.from(json.decode(str).map((x) => RewriteRulesData.fromJson(x))); - -String rewriteRulesDataToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); - -class RewriteRulesData { final String domain; final String answer; - RewriteRulesData({ + RewriteRules({ required this.domain, required this.answer, }); - factory RewriteRulesData.fromJson(Map json) => RewriteRulesData( + factory RewriteRules.fromJson(Map json) => RewriteRules( domain: json["domain"], answer: json["answer"], ); diff --git a/lib/providers/rewrute_rules_provider.dart b/lib/providers/rewrute_rules_provider.dart new file mode 100644 index 0000000..a4c6825 --- /dev/null +++ b/lib/providers/rewrute_rules_provider.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/rewrite_rules.dart'; + +class RewriteRulesProvider with ChangeNotifier { + LoadStatus _loadStatus = LoadStatus.loading; + List? _rewriteRules; + + LoadStatus get loadStatus { + return _loadStatus; + } + + List? get rewriteRules { + return _rewriteRules; + } + + void setRewriteRulesData(List data) { + _rewriteRules = data; + notifyListeners(); + } + + void setRewriteRulesLoadStatus(LoadStatus status, bool notify) { + _loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } +} \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index eb795a8..6536cd4 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; -import 'package:adguard_home_manager/models/dhcp.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; import 'package:adguard_home_manager/models/server.dart'; @@ -18,11 +17,6 @@ class ServersProvider with ChangeNotifier { List _serversList = []; Server? _selectedServer; - final RewriteRules _rewriteRules = RewriteRules( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error - data: null - ); - final DnsInfo _dnsInfo = DnsInfo( loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error data: null @@ -41,10 +35,6 @@ class ServersProvider with ChangeNotifier { return _selectedServer; } - RewriteRules get rewriteRules { - return _rewriteRules; - } - DnsInfo get dnsInfo { return _dnsInfo; } @@ -66,19 +56,7 @@ class ServersProvider with ChangeNotifier { _selectedServer = server; notifyListeners(); } - - void setRewriteRulesData(List data) { - _rewriteRules.data = data; - notifyListeners(); - } - void setRewriteRulesLoadStatus(int status, bool notify) { - _rewriteRules.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } - void setDnsInfoData(DnsInfoData data) { _dnsInfo.data = data; notifyListeners(); diff --git a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart index edff851..24ee717 100644 --- a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart @@ -6,7 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; class AddDnsRewriteModal extends StatefulWidget { - final void Function(RewriteRulesData) onConfirm; + final void Function(RewriteRules) onConfirm; final bool dialog; const AddDnsRewriteModal({ @@ -143,7 +143,7 @@ class _AddDnsRewriteModalState extends State { ? () { Navigator.pop(context); widget.onConfirm( - RewriteRulesData( + RewriteRules( domain: domainController.text, answer: answerController.text ) diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 203c068..6fce727 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -12,52 +12,36 @@ import 'package:adguard_home_manager/screens/settings/dns_rewrites/delete_dns_re import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/rewrute_rules_provider.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -class DnsRewrites extends StatelessWidget { - const DnsRewrites({Key? key}) : super(key: key); +class DnsRewritesScreen extends StatefulWidget { + const DnsRewritesScreen({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return DnsRewritesWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _DnsRewritesScreenState(); } -class DnsRewritesWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const DnsRewritesWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _DnsRewritesWidgetState(); -} - -class _DnsRewritesWidgetState extends State { +class _DnsRewritesScreenState extends State { Future fetchData() async { - widget.serversProvider.setRewriteRulesLoadStatus(0, false); + final rewriteRulesProvider = Provider.of(context, listen: false); + final serversProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); - final result = await getDnsRewriteRules(server: widget.serversProvider.selectedServer!); + rewriteRulesProvider.setRewriteRulesLoadStatus(LoadStatus.loading, false); + + final result = await getDnsRewriteRules(server: serversProvider.selectedServer!); if (result['result'] == 'success') { - widget.serversProvider.setRewriteRulesData(result['data']); - widget.serversProvider.setRewriteRulesLoadStatus(1, true); + rewriteRulesProvider.setRewriteRulesData(result['data']); + rewriteRulesProvider.setRewriteRulesLoadStatus(LoadStatus.loaded, true); } else { - widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setRewriteRulesLoadStatus(2, true); + appConfigProvider.addLog(result['log']); + rewriteRulesProvider.setRewriteRulesLoadStatus(LoadStatus.error, true); } } @@ -70,11 +54,12 @@ class _DnsRewritesWidgetState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final rewriteRulesProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; - void deleteDnsRewrite(RewriteRulesData rule) async { + void deleteDnsRewrite(RewriteRules rule) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deleting); @@ -86,9 +71,9 @@ class _DnsRewritesWidgetState extends State { processModal.close(); if (result['result'] == 'success') { - List data = serversProvider.rewriteRules.data!; + List data = rewriteRulesProvider.rewriteRules!; data = data.where((item) => item.domain != rule.domain).toList(); - serversProvider.setRewriteRulesData(data); + rewriteRulesProvider.setRewriteRulesData(data); showSnacbkar( appConfigProvider: appConfigProvider, @@ -106,7 +91,7 @@ class _DnsRewritesWidgetState extends State { } } - void addDnsRewrite(RewriteRulesData rule) async { + void addDnsRewrite(RewriteRules rule) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingRewrite); @@ -118,9 +103,9 @@ class _DnsRewritesWidgetState extends State { processModal.close(); if (result['result'] == 'success') { - List data = serversProvider.rewriteRules.data!; + List data = rewriteRulesProvider.rewriteRules!; data.add(rule); - serversProvider.setRewriteRulesData(data); + rewriteRulesProvider.setRewriteRulesData(data); showSnacbkar( appConfigProvider: appConfigProvider, @@ -139,8 +124,8 @@ class _DnsRewritesWidgetState extends State { } Widget generateBody() { - switch (serversProvider.rewriteRules.loadStatus) { - case 0: + switch (rewriteRulesProvider.loadStatus) { + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -160,15 +145,15 @@ class _DnsRewritesWidgetState extends State { ), ); - case 1: - if (serversProvider.rewriteRules.data!.isNotEmpty) { + case LoadStatus.loaded: + if (rewriteRulesProvider.rewriteRules!.isNotEmpty) { return RefreshIndicator( onRefresh: () async { await fetchData(); }, child: ListView.builder( padding: const EdgeInsets.only(top: 0), - itemCount: serversProvider.rewriteRules.data!.length, + itemCount: rewriteRulesProvider.rewriteRules!.length, itemBuilder: (context, index) => Container( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10), decoration: BoxDecoration( @@ -195,7 +180,7 @@ class _DnsRewritesWidgetState extends State { ), ), Text( - serversProvider.rewriteRules.data![index].domain, + rewriteRulesProvider.rewriteRules![index].domain, style: TextStyle( color: Theme.of(context).colorScheme.onSurface ), @@ -213,7 +198,7 @@ class _DnsRewritesWidgetState extends State { ), ), Text( - serversProvider.rewriteRules.data![index].answer, + rewriteRulesProvider.rewriteRules![index].answer, style: TextStyle( color: Theme.of(context).colorScheme.onSurface ), @@ -227,7 +212,7 @@ class _DnsRewritesWidgetState extends State { showDialog( context: context, builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(serversProvider.rewriteRules.data![index]) + onConfirm: () => deleteDnsRewrite(rewriteRulesProvider.rewriteRules![index]) ) ) }, @@ -251,7 +236,7 @@ class _DnsRewritesWidgetState extends State { ); } - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index d08c322..08b9d8c 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -177,7 +177,7 @@ class SettingsWidget extends StatelessWidget { title: AppLocalizations.of(context)!.dnsRewrites, subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, thisItem: 5, - screenToNavigate: const DnsRewrites(), + screenToNavigate: const DnsRewritesScreen(), ), if (serversProvider.updateAvailable.data != null) settingsTile( icon: Icons.system_update_rounded, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 3997dfd..ac85f0a 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1528,8 +1528,8 @@ Future getDnsRewriteRules({ if (result['hasResponse'] == true) { if (result['statusCode'] == 200) { - final List data = List.from( - jsonDecode(result['body']).map((item) => RewriteRulesData.fromJson(item)) + final List data = List.from( + jsonDecode(result['body']).map((item) => RewriteRules.fromJson(item)) ); return { From 9e0eae7c57bd6b1a9a371dd56b77825797f641d7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 May 2023 20:40:45 +0200 Subject: [PATCH 152/676] Extracted dns --- lib/main.dart | 9 +- lib/models/dns_info.dart | 22 +---- lib/providers/dns_provider.dart | 29 +++++++ ..._provider.dart => filtering_provider.dart} | 0 ...vider.dart => rewrite_rules_provider.dart} | 0 lib/providers/servers_provider.dart | 22 ----- lib/screens/clients/services_modal.dart | 2 +- lib/screens/filters/add_button.dart | 2 +- .../filters/blocked_services_screen.dart | 2 +- lib/screens/filters/filters.dart | 2 +- lib/screens/filters/filters_tabs_view.dart | 2 +- .../filters/filters_triple_column.dart | 2 +- lib/screens/filters/list_details_screen.dart | 2 +- lib/screens/filters/list_functions.dart | 2 +- lib/screens/settings/dns/bootstrap_dns.dart | 17 ++-- lib/screens/settings/dns/cache_config.dart | 24 +++--- lib/screens/settings/dns/dns.dart | 84 ++++++------------- .../settings/dns/dns_server_settings.dart | 31 ++++--- .../settings/dns/private_reverse_servers.dart | 25 +++--- lib/screens/settings/dns/upstream_dns.dart | 19 ++--- .../settings/dns_rewrites/dns_rewrites.dart | 2 +- lib/services/http_requests.dart | 2 +- 22 files changed, 129 insertions(+), 173 deletions(-) create mode 100644 lib/providers/dns_provider.dart rename lib/providers/{filters_provider.dart => filtering_provider.dart} (100%) rename lib/providers/{rewrute_rules_provider.dart => rewrite_rules_provider.dart} (100%) diff --git a/lib/main.dart b/lib/main.dart index 7582e48..c1017f0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -20,8 +20,9 @@ import 'package:adguard_home_manager/base.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; -import 'package:adguard_home_manager/providers/filters_provider.dart'; -import 'package:adguard_home_manager/providers/rewrute_rules_provider.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; +import 'package:adguard_home_manager/providers/rewrite_rules_provider.dart'; import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -53,6 +54,7 @@ void main() async { final FilteringProvider filtersProvider = FilteringProvider(); final DhcpProvider dhcpProvider = DhcpProvider(); final RewriteRulesProvider rewriteRulesProvider = RewriteRulesProvider(); + final DnsProvider dnsProvider = DnsProvider(); final LogsProvider logsProvider = LogsProvider(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); @@ -121,6 +123,9 @@ void main() async { ChangeNotifierProvider( create: ((context) => rewriteRulesProvider) ), + ChangeNotifierProvider( + create: ((context) => dnsProvider) + ), ChangeNotifierProxyProvider( create: (context) => filtersProvider, update: (context, status, filtering) => filtering!..updateStatus(status), diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index de2e308..1fc1979 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -1,20 +1,4 @@ -import 'dart:convert'; - class DnsInfo { - int loadStatus = 0; - DnsInfoData? data; - - DnsInfo({ - required this.loadStatus, - this.data - }); -} - -DnsInfoData dnsInfoDataFromJson(String str) => DnsInfoData.fromJson(json.decode(str)); - -String dnsInfoDataToJson(DnsInfoData data) => json.encode(data.toJson()); - -class DnsInfoData { List upstreamDns; String upstreamDnsFile; List bootstrapDns; @@ -34,9 +18,9 @@ class DnsInfoData { List localPtrUpstreams; String blockingIpv4; String blockingIpv6; - List defaultLocalPtrUpstreams; - DnsInfoData({ + + DnsInfo({ required this.upstreamDns, required this.upstreamDnsFile, required this.bootstrapDns, @@ -59,7 +43,7 @@ class DnsInfoData { required this.defaultLocalPtrUpstreams, }); - factory DnsInfoData.fromJson(Map json) => DnsInfoData( + factory DnsInfo.fromJson(Map json) => DnsInfo( upstreamDns: json["upstream_dns"] != null ? List.from(json["upstream_dns"].map((x) => x)) : [], upstreamDnsFile: json["upstream_dns_file"], bootstrapDns: List.from(json["bootstrap_dns"].map((x) => x)), diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart new file mode 100644 index 0000000..7db23dc --- /dev/null +++ b/lib/providers/dns_provider.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/dns_info.dart'; + +class DnsProvider with ChangeNotifier { + LoadStatus _loadStatus = LoadStatus.loading; + DnsInfo? _dnsInfo; + + LoadStatus get loadStatus { + return _loadStatus; + } + + DnsInfo? get dnsInfo { + return _dnsInfo; + } + + void setDnsInfoData(DnsInfo data) { + _dnsInfo = data; + notifyListeners(); + } + + void setDnsInfoLoadStatus(LoadStatus status, bool notify) { + _loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } +} \ No newline at end of file diff --git a/lib/providers/filters_provider.dart b/lib/providers/filtering_provider.dart similarity index 100% rename from lib/providers/filters_provider.dart rename to lib/providers/filtering_provider.dart diff --git a/lib/providers/rewrute_rules_provider.dart b/lib/providers/rewrite_rules_provider.dart similarity index 100% rename from lib/providers/rewrute_rules_provider.dart rename to lib/providers/rewrite_rules_provider.dart diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 6536cd4..25b3480 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; -import 'package:adguard_home_manager/models/rewrite_rules.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -17,11 +16,6 @@ class ServersProvider with ChangeNotifier { List _serversList = []; Server? _selectedServer; - final DnsInfo _dnsInfo = DnsInfo( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error - data: null - ); - final UpdateAvailable _updateAvailable = UpdateAvailable( loadStatus: LoadStatus.loading, data: null, @@ -35,10 +29,6 @@ class ServersProvider with ChangeNotifier { return _selectedServer; } - DnsInfo get dnsInfo { - return _dnsInfo; - } - UpdateAvailable get updateAvailable { return _updateAvailable; } @@ -57,18 +47,6 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setDnsInfoData(DnsInfoData data) { - _dnsInfo.data = data; - notifyListeners(); - } - - void setDnsInfoLoadStatus(int status, bool notify) { - _dnsInfo.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } - void setUpdateAvailableLoadStatus(LoadStatus status, bool notify) { _updateAvailable.loadStatus = status; if (notify == true) { diff --git a/lib/screens/clients/services_modal.dart b/lib/screens/clients/services_modal.dart index 288de9c..827f2d3 100644 --- a/lib/screens/clients/services_modal.dart +++ b/lib/screens/clients/services_modal.dart @@ -4,7 +4,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 325709e..34bf53e 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -9,7 +9,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_custom_rule.dart'; import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; -import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/filtering.dart'; diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/blocked_services_screen.dart index eb1bcfe..786711a 100644 --- a/lib/screens/filters/blocked_services_screen.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -8,7 +8,7 @@ import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 194cf0b..763eb95 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -17,7 +17,7 @@ import 'package:adguard_home_manager/screens/filters/update_interval_lists_modal import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/constants/enums.dart'; diff --git a/lib/screens/filters/filters_tabs_view.dart b/lib/screens/filters/filters_tabs_view.dart index 6a36eaf..a4c08cd 100644 --- a/lib/screens/filters/filters_tabs_view.dart +++ b/lib/screens/filters/filters_tabs_view.dart @@ -5,7 +5,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/custom_rules_list.dart'; import 'package:adguard_home_manager/screens/filters/filters_list.dart'; -import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index d60a237..ba65e12 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -15,7 +15,7 @@ import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; -import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 9c970a7..f68693b 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -13,7 +13,7 @@ import 'package:adguard_home_manager/screens/filters/list_functions.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; -import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; diff --git a/lib/screens/filters/list_functions.dart b/lib/screens/filters/list_functions.dart index 312ac5b..2075495 100644 --- a/lib/screens/filters/list_functions.dart +++ b/lib/screens/filters/list_functions.dart @@ -5,7 +5,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/providers/filters_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index fa538dd..389ceae 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -6,18 +6,14 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; class BootstrapDnsScreen extends StatefulWidget { - final ServersProvider serversProvider; - - const BootstrapDnsScreen({ - Key? key, - required this.serversProvider, - }) : super(key: key); + const BootstrapDnsScreen({Key? key}) : super(key: key); @override State createState() => _BootstrapDnsScreenState(); @@ -54,7 +50,9 @@ class _BootstrapDnsScreenState extends State { @override void initState() { - for (var item in widget.serversProvider.dnsInfo.data!.bootstrapDns) { + final dnsProvider = Provider.of(context, listen: false); + + for (var item in dnsProvider.dnsInfo!.bootstrapDns) { final controller = TextEditingController(); controller.text = item; bootstrapControllers.add({ @@ -69,6 +67,7 @@ class _BootstrapDnsScreenState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveData() async { @@ -82,9 +81,9 @@ class _BootstrapDnsScreenState extends State { processModal.close(); if (result['result'] == 'success') { - DnsInfoData data = serversProvider.dnsInfo.data!; + DnsInfo data = dnsProvider.dnsInfo!; data.bootstrapDns = List.from(bootstrapControllers.map((e) => e['controller'].text)); - serversProvider.setDnsInfoData(data); + dnsProvider.setDnsInfoData(data); showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index 32ae872..313919f 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -8,7 +8,7 @@ import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/screens/settings/dns/clear_dns_cache_dialog.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; - +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/clear_dns_cache.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -17,12 +17,7 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; class CacheConfigDnsScreen extends StatefulWidget { - final ServersProvider serversProvider; - - const CacheConfigDnsScreen({ - Key? key, - required this.serversProvider - }) : super(key: key); + const CacheConfigDnsScreen({Key? key}) : super(key: key); @override State createState() => _CacheConfigDnsScreenState(); @@ -60,10 +55,12 @@ class _CacheConfigDnsScreenState extends State { @override void initState() { - cacheSizeController.text = widget.serversProvider.dnsInfo.data!.cacheSize.toString(); - overrideMinTtlController.text = widget.serversProvider.dnsInfo.data!.cacheTtlMin.toString(); - overrideMaxTtlController.text = widget.serversProvider.dnsInfo.data!.cacheTtlMax.toString(); - optimisticCache = widget.serversProvider.dnsInfo.data!.cacheOptimistic; + final dnsProvider = Provider.of(context, listen: false); + + cacheSizeController.text = dnsProvider.dnsInfo!.cacheSize.toString(); + overrideMinTtlController.text = dnsProvider.dnsInfo!.cacheTtlMin.toString(); + overrideMaxTtlController.text = dnsProvider.dnsInfo!.cacheTtlMax.toString(); + optimisticCache = dnsProvider.dnsInfo!.cacheOptimistic; validData = true; super.initState(); } @@ -71,6 +68,7 @@ class _CacheConfigDnsScreenState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveData() async { @@ -87,12 +85,12 @@ class _CacheConfigDnsScreenState extends State { processModal.close(); if (result['result'] == 'success') { - DnsInfoData data = serversProvider.dnsInfo.data!; + DnsInfo data = dnsProvider.dnsInfo!; data.cacheSize = int.parse(cacheSizeController.text); data.cacheTtlMin = int.parse(overrideMinTtlController.text); data.cacheTtlMax = int.parse(overrideMaxTtlController.text); data.cacheOptimistic = optimisticCache; - serversProvider.setDnsInfoData(data); + dnsProvider.setDnsInfoData(data); showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index be7eb79..bd1feee 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -2,6 +2,8 @@ import 'dart:io'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:flutter/material.dart'; import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; @@ -21,49 +23,32 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; -class DnsSettings extends StatelessWidget { +class DnsSettings extends StatefulWidget { const DnsSettings({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return DnsSettingsWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } -} -class DnsSettingsWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const DnsSettingsWidget({ - required this.serversProvider, - required this.appConfigProvider, - Key? key - }) : super(key: key); - - @override - State createState() => _DnsSettingsWidgetState(); + State createState() => _DnsSettingsState(); } -class _DnsSettingsWidgetState extends State { +class _DnsSettingsState extends State { void fetchData({bool? showRefreshIndicator}) async { - widget.serversProvider.setDnsInfoLoadStatus(0, showRefreshIndicator ?? false); + final dnsProvider = Provider.of(context, listen: false); + final serversProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); - final result = await getDnsInfo(server: widget.serversProvider.selectedServer!); + dnsProvider.setDnsInfoLoadStatus(LoadStatus.loading, showRefreshIndicator ?? false); + + final result = await getDnsInfo(server: serversProvider.selectedServer!); if (mounted) { if (result['result'] == 'success') { - widget.serversProvider.setDnsInfoData(result['data']); - widget.serversProvider.setDnsInfoLoadStatus(1, true); + dnsProvider.setDnsInfoData(result['data']); + dnsProvider.setDnsInfoLoadStatus(LoadStatus.loaded, true); } else { - widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setDnsInfoLoadStatus(2, true); + appConfigProvider.addLog(result['log']); + dnsProvider.setDnsInfoLoadStatus(LoadStatus.error, true); } } } @@ -77,6 +62,7 @@ class _DnsSettingsWidgetState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -93,8 +79,8 @@ class _DnsSettingsWidgetState extends State { } Widget generateBody() { - switch (widget.serversProvider.dnsInfo.loadStatus) { - case 0: + switch (dnsProvider.loadStatus) { + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -115,63 +101,43 @@ class _DnsSettingsWidgetState extends State { ) ); - case 1: + case LoadStatus.loaded: return ListView( children: [ CustomListTile( title: AppLocalizations.of(context)!.upstreamDns, subtitle: AppLocalizations.of(context)!.upstreamDnsDescription, - onTap: () => navigate( - UpstreamDnsScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const UpstreamDnsScreen()), icon: Icons.upload_rounded, ), CustomListTile( title: AppLocalizations.of(context)!.bootstrapDns, subtitle: AppLocalizations.of(context)!.bootstrapDnsDescription, - onTap: () => navigate( - BootstrapDnsScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const BootstrapDnsScreen()), icon: Icons.dns_rounded, ), CustomListTile( title: AppLocalizations.of(context)!.privateReverseDnsServers, subtitle: AppLocalizations.of(context)!.privateReverseDnsDescription, - onTap: () => navigate( - PrivateReverseDnsServersScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const PrivateReverseDnsServersScreen()), icon: Icons.person_rounded, ), CustomListTile( title: AppLocalizations.of(context)!.dnsServerSettings, subtitle: AppLocalizations.of(context)!.dnsServerSettingsDescription, - onTap: () => navigate( - DnsServerSettingsScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const DnsServerSettingsScreen()), icon: Icons.settings, ), CustomListTile( title: AppLocalizations.of(context)!.dnsCacheConfig, subtitle: AppLocalizations.of(context)!.dnsCacheConfigDescription, - onTap: () => navigate( - CacheConfigDnsScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const CacheConfigDnsScreen()), icon: Icons.storage_rounded, ), ], ); - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index d0d3ecd..cc1db2a 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -10,18 +10,14 @@ import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; class DnsServerSettingsScreen extends StatefulWidget { - final ServersProvider serversProvider; - - const DnsServerSettingsScreen({ - Key? key, - required this.serversProvider - }) : super(key: key); + const DnsServerSettingsScreen({Key? key}) : super(key: key); @override State createState() => _DnsServerSettingsScreenState(); @@ -89,13 +85,15 @@ class _DnsServerSettingsScreenState extends State { @override void initState() { - limitRequestsController.text = widget.serversProvider.dnsInfo.data!.ratelimit.toString(); - enableEdns = widget.serversProvider.dnsInfo.data!.ednsCsEnabled; - enableDnssec = widget.serversProvider.dnsInfo.data!.dnssecEnabled; - disableIpv6Resolving = widget.serversProvider.dnsInfo.data!.disableIpv6; - blockingMode = widget.serversProvider.dnsInfo.data!.blockingMode; - ipv4controller.text = widget.serversProvider.dnsInfo.data!.blockingIpv4; - ipv6controller.text = widget.serversProvider.dnsInfo.data!.blockingIpv6; + final dnsProvider = Provider.of(context, listen: false); + + limitRequestsController.text = dnsProvider.dnsInfo!.ratelimit.toString(); + enableEdns = dnsProvider.dnsInfo!.ednsCsEnabled; + enableDnssec = dnsProvider.dnsInfo!.dnssecEnabled; + disableIpv6Resolving = dnsProvider.dnsInfo!.disableIpv6; + blockingMode = dnsProvider.dnsInfo!.blockingMode; + ipv4controller.text = dnsProvider.dnsInfo!.blockingIpv4; + ipv6controller.text = dnsProvider.dnsInfo!.blockingIpv6; isDataValid = true; super.initState(); } @@ -103,6 +101,7 @@ class _DnsServerSettingsScreenState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveData() async { @@ -120,7 +119,7 @@ class _DnsServerSettingsScreenState extends State { processModal.close(); if (result['result'] == 'success') { - DnsInfoData data = serversProvider.dnsInfo.data!; + DnsInfo data = dnsProvider.dnsInfo!; data.ratelimit = int.parse(limitRequestsController.text); data.ednsCsEnabled = enableEdns; data.dnssecEnabled = enableDnssec; @@ -128,7 +127,7 @@ class _DnsServerSettingsScreenState extends State { data.blockingMode = blockingMode; data.blockingIpv4 = ipv4controller.text; data.blockingIpv6 = ipv6controller.text; - serversProvider.setDnsInfoData(data); + dnsProvider.setDnsInfoData(data); showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index 6081278..5bab4c0 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -7,6 +7,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; @@ -14,12 +15,7 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; class PrivateReverseDnsServersScreen extends StatefulWidget { - final ServersProvider serversProvider; - - const PrivateReverseDnsServersScreen({ - Key? key, - required this.serversProvider, - }) : super(key: key); + const PrivateReverseDnsServersScreen({Key? key}) : super(key: key); @override State createState() => _PrivateReverseDnsServersScreenState(); @@ -69,10 +65,12 @@ class _PrivateReverseDnsServersScreenState extends State(context, listen: false); + + for (var item in dnsProvider.dnsInfo!.defaultLocalPtrUpstreams) { defaultReverseResolvers.add(item); } - for (var item in widget.serversProvider.dnsInfo.data!.localPtrUpstreams) { + for (var item in dnsProvider.dnsInfo!.localPtrUpstreams) { final controller = TextEditingController(); controller.text = item; reverseResolversControllers = [{ @@ -80,11 +78,11 @@ class _PrivateReverseDnsServersScreenState extends State(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveData() async { @@ -111,13 +110,13 @@ class _PrivateReverseDnsServersScreenState extends State.from(reverseResolversControllers.map((e) => e['controller'].text)); } data.usePrivatePtrResolvers = usePrivateReverseDnsResolvers; data.resolveClients = enableReverseResolve; - serversProvider.setDnsInfoData(data); + dnsProvider.setDnsInfoData(data); showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 9ce5962..cf9a884 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -12,18 +12,14 @@ import 'package:adguard_home_manager/widgets/custom_radio_list_tile.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class UpstreamDnsScreen extends StatefulWidget { - final ServersProvider serversProvider; - - const UpstreamDnsScreen({ - Key? key, - required this.serversProvider, - }) : super(key: key); + const UpstreamDnsScreen({Key? key}) : super(key: key); @override State createState() => _UpstreamDnsScreenState(); @@ -50,7 +46,9 @@ class _UpstreamDnsScreenState extends State { @override void initState() { - for (var item in widget.serversProvider.dnsInfo.data!.upstreamDns) { + final dnsProvider = Provider.of(context, listen: false); + + for (var item in dnsProvider.dnsInfo!.upstreamDns) { if (item == '#') { dnsServers.add({ 'comment': item @@ -64,7 +62,7 @@ class _UpstreamDnsScreenState extends State { }); } } - upstreamMode = widget.serversProvider.dnsInfo.data!.upstreamMode; + upstreamMode = dnsProvider.dnsInfo!.upstreamMode; validValues = true; super.initState(); } @@ -72,6 +70,7 @@ class _UpstreamDnsScreenState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -154,10 +153,10 @@ class _UpstreamDnsScreenState extends State { processModal.close(); if (result['result'] == 'success') { - DnsInfoData data = serversProvider.dnsInfo.data!; + DnsInfo data = dnsProvider.dnsInfo!; data.upstreamDns = List.from(dnsServers.map((e) => e['controller'] != null ? e['controller'].text : e['comment'])); data.upstreamMode = upstreamMode; - serversProvider.setDnsInfoData(data); + dnsProvider.setDnsInfoData(data); showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 6fce727..923580d 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -13,7 +13,7 @@ import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/rewrute_rules_provider.dart'; +import 'package:adguard_home_manager/providers/rewrite_rules_provider.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index ac85f0a..b9cda5c 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1808,7 +1808,7 @@ Future getDnsInfo({ if (result['statusCode'] == 200) { return { 'result': 'success' , - 'data': DnsInfoData.fromJson(jsonDecode(result['body'])) + 'data': DnsInfo.fromJson(jsonDecode(result['body'])) }; } else { From 90fa963cfc77789efeefd59c3a42fabdde19d2be Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 15:06:21 +0200 Subject: [PATCH 153/676] Changed http requests to http client class --- lib/functions/block_unblock_domain.dart | 63 - lib/functions/clear_dns_cache.dart | 6 +- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/main.dart | 41 +- lib/models/server_info.dart | 4 +- lib/providers/clients_provider.dart | 202 +- lib/providers/dhcp_provider.dart | 86 + lib/providers/dns_provider.dart | 170 + lib/providers/filtering_provider.dart | 318 +- lib/providers/logs_provider.dart | 161 +- lib/providers/rewrite_rules_provider.dart | 71 + lib/providers/servers_provider.dart | 40 +- lib/providers/status_provider.dart | 120 +- lib/screens/clients/added_list.dart | 56 +- lib/screens/clients/clients.dart | 29 +- lib/screens/clients/clients_desktop_view.dart | 6 - lib/screens/clients/clients_list.dart | 15 +- lib/screens/clients/fab.dart | 24 +- lib/screens/clients/logs_list_client.dart | 7 +- lib/screens/clients/search_clients.dart | 44 +- lib/screens/clients/services_modal.dart | 21 +- lib/screens/filters/add_button.dart | 69 +- .../filters/blocked_services_screen.dart | 38 +- lib/screens/filters/check_host_modal.dart | 43 +- lib/screens/filters/custom_rules_list.dart | 31 +- lib/screens/filters/filters.dart | 106 +- lib/screens/filters/filters_list.dart | 27 +- lib/screens/filters/filters_tabs_view.dart | 6 - .../filters/filters_triple_column.dart | 14 +- lib/screens/filters/list_details_screen.dart | 139 +- lib/screens/filters/list_functions.dart | 149 - lib/screens/filters/list_options_menu.dart | 24 +- lib/screens/home/home.dart | 15 +- lib/screens/home/management_modal.dart | 18 +- lib/screens/home/top_items.dart | 73 +- lib/screens/logs/clients_modal.dart | 18 +- lib/screens/logs/log_details_screen.dart | 77 +- lib/screens/logs/logs.dart | 156 +- lib/screens/logs/logs_config_modal.dart | 7 +- lib/screens/logs/logs_filters_modal.dart | 99 +- .../access_settings/access_settings.dart | 25 +- .../access_settings/clients_list.dart | 77 +- lib/screens/settings/advanced_setings.dart | 46 +- lib/screens/settings/dhcp/dhcp.dart | 79 +- lib/screens/settings/dhcp/dhcp_leases.dart | 35 +- lib/screens/settings/dns/bootstrap_dns.dart | 18 +- lib/screens/settings/dns/cache_config.dart | 17 +- lib/screens/settings/dns/dns.dart | 27 +- .../settings/dns/dns_server_settings.dart | 25 +- .../settings/dns/private_reverse_servers.dart | 40 +- lib/screens/settings/dns/upstream_dns.dart | 17 +- .../settings/dns_rewrites/dns_rewrites.dart | 57 +- .../settings/encryption/encryption.dart | 59 +- .../settings/safe_search_settings.dart | 130 +- .../settings/server_info/server_info.dart | 17 +- lib/screens/settings/settings.dart | 6 +- .../settings/update_server/update.dart | 8 +- lib/screens/top_items/top_items.dart | 10 +- lib/services/http_requests.dart | 3669 ++++++++--------- lib/widgets/add_server_modal.dart | 8 +- lib/widgets/bottom_nav_bar.dart | 11 +- lib/widgets/domain_options.dart | 63 +- lib/widgets/navigation_rail.dart | 8 +- .../servers_list/servers_list_item.dart | 4 +- .../servers_list/servers_tile_item.dart | 4 +- 66 files changed, 3584 insertions(+), 3477 deletions(-) delete mode 100644 lib/functions/block_unblock_domain.dart delete mode 100644 lib/screens/filters/list_functions.dart diff --git a/lib/functions/block_unblock_domain.dart b/lib/functions/block_unblock_domain.dart deleted file mode 100644 index 0049564..0000000 --- a/lib/functions/block_unblock_domain.dart +++ /dev/null @@ -1,63 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/filtering_status.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; - -Future> blockUnblock(BuildContext context, String domain, String newStatus) async { - final serversProvider = Provider.of(context, listen: false); - final statusProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - final ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.savingUserFilters); - - final rules = await getFilteringRules(server: serversProvider.selectedServer!); - - if (rules['result'] == 'success') { - FilteringStatus oldStatus = statusProvider.serverStatus!.filteringStatus; - List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); - if (newStatus == 'block') { - newRules.add("||$domain^"); - } - else if (newStatus == 'unblock') { - newRules.add("@@||$domain^"); - } - FilteringStatus newObj = statusProvider.serverStatus!.filteringStatus; - newObj.userRules = newRules; - statusProvider.setFilteringStatus(newObj); - - final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); - - processModal.close(); - - if (result['result'] == 'success') { - return { - 'success': true, - 'message': AppLocalizations.of(context)!.userFilteringRulesUpdated - }; - } - else { - appConfigProvider.addLog(result['log']); - statusProvider.setFilteringStatus(oldStatus); - return { - 'success': false, - 'message': AppLocalizations.of(context)!.userFilteringRulesNotUpdated - }; - } - } - else { - appConfigProvider.addLog(rules['log']); - return { - 'success': false, - 'message': AppLocalizations.of(context)!.userFilteringRulesNotUpdated - }; - } -} \ No newline at end of file diff --git a/lib/functions/clear_dns_cache.dart b/lib/functions/clear_dns_cache.dart index 44c81d9..0ff1606 100644 --- a/lib/functions/clear_dns_cache.dart +++ b/lib/functions/clear_dns_cache.dart @@ -5,15 +5,17 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; Future clearDnsCache(BuildContext context, Server server) async { + final serversProvider = Provider.of(context, listen: false); + final ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.clearingDnsCache); - final result = await resetDnsCache(server: server); + final result = await serversProvider.apiClient!.resetDnsCache(); processModal.close(); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index a96efab..1504716 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -628,5 +628,7 @@ "application": "Application", "combinedChart": "Combined chart", "combinedChartDescription": "Combine all charts into one", - "statistics": "Statistics" + "statistics": "Statistics", + "errorLoadFilters": "Error when loading filters.", + "clientRemovedSuccessfully": "Client removed successfully." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 4739f4b..88d248f 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -628,5 +628,7 @@ "application": "Aplicación", "combinedChart": "Gráfico combinado", "combinedChartDescription": "Combina todos los gráficos en uno solo", - "statistics": "Estadísticas" + "statistics": "Estadísticas", + "errorLoadFilters": "Error al cargar los filtros.", + "clientRemovedSuccessfully": "Cliente eliminado correctamente." } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index c1017f0..4ab8db5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -80,18 +80,7 @@ void main() async { serversProvider.setDbInstance(dbData['dbInstance']); appConfigProvider.saveFromDb(dbData['dbInstance'], dbData['appConfig']); - final result = await serversProvider.saveFromDb(dbData['servers']); - if (result != null) { - if (result['success'] == true) { - statusProvider.setServerStatusData( - data: result['serverData'], - ); - statusProvider.setServerStatusLoad(LoadStatus.loaded); - } - else { - statusProvider.setServerStatusLoad(LoadStatus.error); - } - } + serversProvider.saveFromDb(dbData['servers']); PackageInfo appInfo = await PackageInfo.fromPlatform(); appConfigProvider.setAppInfo(appInfo); @@ -126,9 +115,33 @@ void main() async { ChangeNotifierProvider( create: ((context) => dnsProvider) ), - ChangeNotifierProxyProvider( + ChangeNotifierProxyProvider2( + create: (context) => clientsProvider, + update: (context, servers, status, clients) => clients!..update(servers, status), + ), + ChangeNotifierProxyProvider2( create: (context) => filtersProvider, - update: (context, status, filtering) => filtering!..updateStatus(status), + update: (context, servers, status, filtering) => filtering!..update(servers, status), + ), + ChangeNotifierProxyProvider( + create: (context) => statusProvider, + update: (context, servers, status) => status!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => logsProvider, + update: (context, servers, logs) => logs!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => dhcpProvider, + update: (context, servers, dhcp) => dhcp!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => rewriteRulesProvider, + update: (context, servers, rewrite) => rewrite!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => dnsProvider, + update: (context, servers, dns) => dns!..update(servers), ), ], child: const Main(), diff --git a/lib/models/server_info.dart b/lib/models/server_info.dart index 6e170a5..84f9a57 100644 --- a/lib/models/server_info.dart +++ b/lib/models/server_info.dart @@ -1,7 +1,9 @@ import 'dart:convert'; +import 'package:adguard_home_manager/constants/enums.dart'; + class ServerInfo { - int loadStatus = 0; + LoadStatus loadStatus = LoadStatus.loading; ServerInfoData? data; ServerInfo({ diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart index ae6955c..8cf79a5 100644 --- a/lib/providers/clients_provider.dart +++ b/lib/providers/clients_provider.dart @@ -1,10 +1,22 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/functions/maps_fns.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/constants/enums.dart'; class ClientsProvider with ChangeNotifier { + ServersProvider? _serversProvider; + StatusProvider? _statusProvider; + + update(ServersProvider? servers, StatusProvider? status) { + _serversProvider = servers; + _statusProvider = status; + } + LoadStatus _loadStatus = LoadStatus.loading; Clients? _clients; String? _searchTermClients; @@ -38,7 +50,7 @@ class ClientsProvider with ChangeNotifier { } } - void setClientsData(Clients data) { + void setClientsData(Clients data, bool notify) { _clients = data; if (_searchTermClients != null && _searchTermClients != '') { _filteredActiveClients = _clients!.autoClients.where( @@ -55,7 +67,7 @@ class ClientsProvider with ChangeNotifier { _filteredActiveClients = data.autoClients; _filteredAddedClients = data.clients; } - notifyListeners(); + if (notify == true) notifyListeners(); } void setSearchTermClients(String? value) { @@ -84,4 +96,190 @@ class ClientsProvider with ChangeNotifier { _clients?.clientsAllowedBlocked = data; notifyListeners(); } + + Future fetchClients({ + bool? updateLoading + }) async { + if (updateLoading == true) { + _loadStatus = LoadStatus.loading; + } + final result = await _serversProvider!.apiClient!.getClients(); + if (result['result'] == 'success') { + setClientsData(result['data'], false); + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (updateLoading == true) { + _loadStatus = LoadStatus.error; + notifyListeners(); + } + return false; + } + } + + Future deleteClient(Client client) async { + final result = await _serversProvider!.apiClient!.postDeleteClient(name: client.name); + + if (result['result'] == 'success') { + Clients clientsData = clients!; + clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); + setClientsData(clientsData, false); + + notifyListeners(); + return true; + } + else { + return false; + } + } + + Future editClient(Client client) async { + final result = await _serversProvider!.apiClient!.postUpdateClient( + data: { + 'name': client.name, + 'data': serverVersionIsAhead( + currentVersion: _statusProvider!.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == false + ? removePropFromMap(client.toJson(), 'safesearch_enabled') + : removePropFromMap(client.toJson(), 'safe_search') + } + ); + + if (result['result'] == 'success') { + Clients clientsData = clients!; + clientsData.clients = clientsData.clients.map((e) { + if (e.name == client.name) { + return client; + } + else { + return e; + } + }).toList(); + setClientsData(clientsData, false); + + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future addClient(Client client) async { + final result = await _serversProvider!.apiClient!.postAddClient( + data: serverVersionIsAhead( + currentVersion: _statusProvider!.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == false + ? removePropFromMap(client.toJson(), 'safesearch_enabled') + : removePropFromMap(client.toJson(), 'safe_search') + ); + + if (result['result'] == 'success') { + Clients clientsData = clients!; + clientsData.clients.add(client); + setClientsData(clientsData, false); + + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future> addClientList(String item, String type) async { + Map> body = { + "allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [], + "disallowed_clients": clients!.clientsAllowedBlocked?.disallowedClients ?? [], + "blocked_hosts": clients!.clientsAllowedBlocked?.blockedHosts ?? [], + }; + + if (type == 'allowed') { + body['allowed_clients']!.add(item); + } + else if (type == 'disallowed') { + body['disallowed_clients']!.add(item); + } + else if (type == 'domains') { + body['blocked_hosts']!.add(item); + } + + final result = await _serversProvider!.apiClient!.requestAllowedBlockedClientsHosts(body); + + if (result['result'] == 'success') { + _clients?.clientsAllowedBlocked = ClientsAllowedBlocked( + allowedClients: body['allowed_clients'] ?? [], + disallowedClients: body['disallowed_clients'] ?? [], + blockedHosts: body['blocked_hosts'] ?? [], + ); + notifyListeners(); + return { 'success': true }; + } + else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + notifyListeners(); + return { + 'success': false, + 'error': 'client_another_list' + }; + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } + + Future> removeClientList(String client, String type) async { + Map> body = { + "allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [], + "disallowed_clients": clients!.clientsAllowedBlocked?.disallowedClients ?? [], + "blocked_hosts": clients!.clientsAllowedBlocked?.blockedHosts ?? [], + }; + + if (type == 'allowed') { + body['allowed_clients'] = body['allowed_clients']!.where((c) => c != client).toList(); + } + else if (type == 'disallowed') { + body['disallowed_clients'] = body['disallowed_clients']!.where((c) => c != client).toList(); + } + else if (type == 'domains') { + body['blocked_hosts'] = body['blocked_hosts']!.where((c) => c != client).toList(); + } + + final result = await _serversProvider!.apiClient!.requestAllowedBlockedClientsHosts(body); + + if (result['result'] == 'success') { + _clients?.clientsAllowedBlocked = ClientsAllowedBlocked( + allowedClients: body['allowed_clients'] ?? [], + disallowedClients: body['disallowed_clients'] ?? [], + blockedHosts: body['blocked_hosts'] ?? [], + ); + notifyListeners(); + return { 'success': true }; + } + else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + notifyListeners(); + return { + 'success': false, + 'error': 'client_another_list' + }; + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } } \ No newline at end of file diff --git a/lib/providers/dhcp_provider.dart b/lib/providers/dhcp_provider.dart index d03759b..2c2e7d9 100644 --- a/lib/providers/dhcp_provider.dart +++ b/lib/providers/dhcp_provider.dart @@ -1,9 +1,16 @@ import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; class DhcpProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + LoadStatus _loadStatus = LoadStatus.loading; DhcpModel? _dhcp; @@ -26,4 +33,83 @@ class DhcpProvider with ChangeNotifier { notifyListeners(); } } + + Future loadDhcpStatus({ + bool? showLoading + }) async { + if (showLoading == true) { + _loadStatus = LoadStatus.loading; + notifyListeners(); + } + final result = await _serversProvider!.apiClient!.getDhcpData(); + if (result['result'] == 'success') { + _dhcp = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (showLoading == true) { + _loadStatus = LoadStatus.error; + notifyListeners(); + } + return false; + } + } + + Future deleteLease(Lease lease) async { + final result = await _serversProvider!.apiClient!.deleteStaticLease( + data: { + "mac": lease.mac, + "ip": lease.ip, + "hostname": lease.hostname + } + ); + + if (result['result'] == 'success') { + DhcpModel data = dhcp!; + data.dhcpStatus.staticLeases = data.dhcpStatus.staticLeases.where((l) => l.mac != lease.mac).toList(); + setDhcpData(data); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future> createLease(Lease lease) async { + final result = await _serversProvider!.apiClient!.createStaticLease( + data: { + "mac": lease.mac, + "ip": lease.ip, + "hostname": lease.hostname, + } + ); + + if (result['result'] == 'success') { + DhcpModel data = dhcp!; + data.dhcpStatus.staticLeases.add(lease); + setDhcpData(data); + return { 'success': true }; + } + else if (result['result'] == 'error' && result['message'] == 'already_exists' ) { + return { + 'success': false, + 'error': 'already_exists' + }; + } + else if (result['result'] == 'error' && result['message'] == 'server_not_configured' ) { + return { + 'success': false, + 'error': 'server_not_configured' + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } } \ No newline at end of file diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index 7db23dc..1468f18 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -1,9 +1,16 @@ import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; class DnsProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + LoadStatus _loadStatus = LoadStatus.loading; DnsInfo? _dnsInfo; @@ -26,4 +33,167 @@ class DnsProvider with ChangeNotifier { notifyListeners(); } } + + Future fetchDnsData({ + bool? showLoading + }) async { + if (showLoading == true) { + _loadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getDnsInfo(); + + if (result['result'] == 'success') { + _dnsInfo = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (showLoading == false) { + _loadStatus = LoadStatus.loaded; + notifyListeners(); + } + return false; + } + } + + Future> savePrivateReverseServersConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + if (value['local_ptr_upstreams'] != null) { + data.localPtrUpstreams = value['local_ptr_upsreams']; + } + data.usePrivatePtrResolvers = value['use_private_ptr_resolvers']; + data.resolveClients = value['resolve_clients']; + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } + + Future> saveUpstreamDnsConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + data.upstreamDns = List.from(value['upstream_dns']); + data.upstreamMode = value['upstream_mode']; + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } + + Future> saveBootstrapDnsConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + data.bootstrapDns = List.from(value['bootstrap_dns']); + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } + + Future> saveCacheCacheConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + data.cacheSize = value['cache_size']; + data.cacheTtlMin = value['cache_ttl_min']; + data.cacheTtlMax = value['cache_ttl_max']; + data.cacheOptimistic = value['cache_optimistic']; + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } + + Future> saveDnsServerConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + data.ratelimit = value['ratelimit']; + data.ednsCsEnabled = value['edns_cs_enabled']; + data.dnssecEnabled = value['dnssec_enabled']; + data.disableIpv6 = value['disable_ipv6']; + data.blockingMode = value['blocking_mode']; + data.blockingIpv4 = value['blocking_ipv4']; + data.blockingIpv6 = value['blocking_ipv6']; + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } } \ No newline at end of file diff --git a/lib/providers/filtering_provider.dart b/lib/providers/filtering_provider.dart index f7734b8..8b2d459 100644 --- a/lib/providers/filtering_provider.dart +++ b/lib/providers/filtering_provider.dart @@ -1,17 +1,20 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; +enum FilteringListActions { edit, enable, disable } + class FilteringProvider with ChangeNotifier { StatusProvider? _statusProvider; + ServersProvider? _serversProvider; - updateStatus(StatusProvider? statusProvider) { - if (statusProvider != null) { - _statusProvider = statusProvider; - } + update(ServersProvider? servers, StatusProvider? status) { + _serversProvider = servers; + _statusProvider = status; } LoadStatus _loadStatus = LoadStatus.loading; @@ -47,10 +50,10 @@ class FilteringProvider with ChangeNotifier { } } - void setFilteringProtectionStatus(bool status) { + void setFilteringProtectionStatus(bool status, bool notify) { _statusProvider!.setFilteringEnabledStatus(status); _filtering!.enabled = status; - notifyListeners(); + if (notify == true) notifyListeners(); } void setFiltersUpdateFrequency(int frequency) { @@ -78,4 +81,307 @@ class FilteringProvider with ChangeNotifier { notifyListeners(); } } + + Future getBlockedServices({ + bool? showLoader + }) async { + _blockedServicesLoadStatus = LoadStatus.loading; + if (showLoader == true) notifyListeners(); + + final result = await _serversProvider!.apiClient!.getBlockedServices(); + if (result['result'] == 'success') { + _blockedServicesLoadStatus = LoadStatus.loaded; + _blockedServicesList = BlockedServices(services: result['data']); + + notifyListeners(); + return true; + } + else { + if (showLoader == true) { + _blockedServicesLoadStatus = LoadStatus.error; + notifyListeners(); + } + return false; + } + } + + Future fetchFilters({ + bool? showLoading + }) async { + if (showLoading == true) { + _loadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getFiltering(); + if (result['result'] == 'success') { + _filtering = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future> updateLists() async { + final result = await _serversProvider!.apiClient!.updateLists(); + if (result['result'] == 'success') { + final result2 = await _serversProvider!.apiClient!.getFiltering(); + if (result2['result'] == 'success') { + _filtering = result2['data']; + notifyListeners(); + return { + "success": true, + "data": result['data'] + }; + } + else { + notifyListeners(); + return { "success": false }; + } + } + else { + notifyListeners(); + return { "success": false }; + } + } + + Future enableDisableFiltering() async { + final newValue = !_statusProvider!.serverStatus!.filteringEnabled; + final result = await _serversProvider!.apiClient!.updateFiltering( + enable: newValue + ); + if (result['result'] == 'success') { + setFilteringProtectionStatus(newValue, false); + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future changeUpdateFrequency(int value) async { + final result = await _serversProvider!.apiClient!.requestChangeUpdateFrequency( + data: { + "enabled": filtering!.enabled, + "interval": value + } + ); + if (result['result'] == 'success') { + setFiltersUpdateFrequency(value); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future removeCustomRule(String rule) async { + final List newRules = filtering!.userRules.where((r) => r != rule).toList(); + + final result = await _serversProvider!.apiClient!.setCustomRules(rules: newRules); + + if (result['result'] == 'success') { + Filtering filteringData = filtering!; + filteringData.userRules = newRules; + _filtering = filteringData; + + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future deleteList({ + required String listUrl, + required String type + }) async { + final result1 = await _serversProvider!.apiClient!.deleteFilterList( + data: { + "url": listUrl, + "whitelist": type == 'whitelist' ? true : false + } + ); + + if (result1['result'] == 'success') { + final result2 = await _serversProvider!.apiClient!.getFiltering(); + + if (result2['result'] == 'success') { + _filtering = result2['data']; + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + else { + notifyListeners(); + return false; + } + } + + Future updateList({ + required Filter list, + required String type, + required FilteringListActions action + }) async { + final result1 = await _serversProvider!.apiClient!.updateFilterList( + data: { + "data": { + "enabled": action == FilteringListActions.disable || action == FilteringListActions.enable + ? !list.enabled + : list.enabled, + "name": list.name, + "url": list.url + }, + "url": list.url, + "whitelist": type == 'whitelist' ? true : false + } + ); + + if (result1['result'] == 'success') { + final result2 = await _serversProvider!.apiClient!.getFiltering(); + + if (result2['result'] == 'success') { + _filtering = result2['data']; + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + else { + notifyListeners(); + return false; + } + } + + Future addCustomRule(String rule) async { + final List newRules = filtering!.userRules; + newRules.add(rule); + + final result = await _serversProvider!.apiClient!.setCustomRules(rules: newRules); + + if (result['result'] == 'success') { + Filtering filteringData = filtering!; + filteringData.userRules = newRules; + _filtering = filteringData; + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + Future> addList({required String name, required String url, required String type}) async { + final result1 = await _serversProvider!.apiClient!.addFilteringList( + data: { + 'name': name, + 'url': url, + 'whitelist': type == 'whitelist' ? true : false + } + ); + + if (result1['result'] == 'success') { + if (result1['data'].toString().contains("OK")) { + final result2 = await _serversProvider!.apiClient!.getFiltering(); + final items = result1['data'].toString().split(' ')[1]; + + if (result2['result'] == 'success') { + _filtering = result2['data']; + notifyListeners(); + return { + 'success': true, + 'data': items + }; + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } + else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains("Couldn't fetch filter from url")) { + notifyListeners(); + return { + 'success': false, + 'error': 'invalid_url' + }; + } + else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains('Filter URL already added')) { + notifyListeners(); + return { + 'success': false, + 'error': 'url_exists' + }; + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } + + Future loadBlockedServices({ + bool? showLoading + }) async { + if (showLoading == true) { + _blockedServicesLoadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getBlockedServices(); + if (result['result'] == 'success') { + _blockedServicesList = BlockedServices(services: result['data']); + _blockedServicesLoadStatus = LoadStatus.loaded; + + notifyListeners(); + return true; + } + else { + if (showLoading == true) _blockedServicesLoadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future updateBlockedServices(List values) async { + final result = await _serversProvider!.apiClient!.setBlockedServices( + data: values + ); + + if (result['result'] == 'success') { + setBlockedServices(values); + return true; + } + else { + notifyListeners(); + return false; + } + } } \ No newline at end of file diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index 9c3d3a7..e999470 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -1,14 +1,21 @@ import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/logs.dart'; class LogsProvider with ChangeNotifier { - int _loadStatus = 0; + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + + LoadStatus _loadStatus = LoadStatus.loading; LogsData? _logsData; List? _clients; - int _clientsLoadStatus = 0; DateTime? _logsOlderThan; String _selectedResultStatus = 'all'; @@ -18,13 +25,15 @@ class LogsProvider with ChangeNotifier { int _logsQuantity = 100; int _offset = 0; + bool _isLoadingMore = false; + AppliedFiters _appliedFilters = AppliedFiters( selectedResultStatus: 'all', searchText: null, clients: null ); - int get loadStatus { + LoadStatus get loadStatus { return _loadStatus; } @@ -60,16 +69,15 @@ class LogsProvider with ChangeNotifier { return _selectedClients; } - int get clientsLoadStatus { - return _clientsLoadStatus; - } - AppliedFiters get appliedFilters { return _appliedFilters; } + bool get isLoadingMore { + return _isLoadingMore; + } - void setLoadStatus(int value) { + void setLoadStatus(LoadStatus value) { _loadStatus = value; notifyListeners(); } @@ -83,11 +91,6 @@ class LogsProvider with ChangeNotifier { _clients = clients; notifyListeners(); } - - void setClientsLoadStatus(int status) { - _clientsLoadStatus = status; - notifyListeners(); - } void setLogsOlderThan(DateTime? value) { _logsOlderThan = value; @@ -130,4 +133,136 @@ class LogsProvider with ChangeNotifier { _appliedFilters = value; notifyListeners(); } + + void setIsLoadingMore(bool status) { + _isLoadingMore = status; + } + + Future fetchLogs({ + int? inOffset, + bool? loadingMore, + String? responseStatus, + String? searchText, + }) async { + int offst = inOffset ?? offset; + + String resStatus = responseStatus ?? selectedResultStatus; + String? search = searchText ?? searchText; + + if (loadingMore != null && loadingMore == true) { + _isLoadingMore = true; + notifyListeners(); + } + + final result = await _serversProvider!.apiClient!.getLogs( + count: logsQuantity, + offset: offst, + olderThan: logsOlderThan, + responseStatus: resStatus, + search: search + ); + + if (loadingMore != null && loadingMore == true) { + _isLoadingMore = false; + notifyListeners(); + } + + if (result['result'] == 'success') { + _offset = inOffset != null ? inOffset+logsQuantity : offset+logsQuantity; + if (loadingMore != null && loadingMore == true && logsData != null) { + LogsData newLogsData = result['data']; + newLogsData.data = [...logsData!.data, ...result['data'].data]; + if (appliedFilters.clients != null) { + newLogsData.data = newLogsData.data.where( + (item) => appliedFilters.clients!.contains(item.client) + ).toList(); + } + _logsData = newLogsData; + } + else { + LogsData newLogsData = result['data']; + if (appliedFilters.clients != null) { + newLogsData.data = newLogsData.data.where( + (item) => appliedFilters.clients!.contains(item.client) + ).toList(); + } + _logsData = newLogsData; + } + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future requestResetFilters() async { + _loadStatus = LoadStatus.loading; + notifyListeners(); + + resetFilters(); + + final result = await _serversProvider!.apiClient!.getLogs( + count: logsQuantity + ); + + _appliedFilters = AppliedFiters( + selectedResultStatus: 'all', + searchText: null, + clients: null + ); + + if (result['result'] == 'success') { + _logsData = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future filterLogs() async { + _loadStatus = LoadStatus.loading; + notifyListeners(); + + setOffset(0); + + final result = await _serversProvider!.apiClient!.getLogs( + count: logsQuantity, + olderThan: logsOlderThan, + responseStatus: selectedResultStatus, + search: searchText, + ); + + _appliedFilters = AppliedFiters( + selectedResultStatus: selectedResultStatus, + searchText: searchText, + clients: selectedClients + ); + + if (result['result'] == 'success') { + LogsData newLogsData = result['data']; + if (appliedFilters.clients != null) { + newLogsData.data = newLogsData.data.where( + (item) => appliedFilters.clients!.contains(item.client) + ).toList(); + } + _logsData = newLogsData; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } } \ No newline at end of file diff --git a/lib/providers/rewrite_rules_provider.dart b/lib/providers/rewrite_rules_provider.dart index a4c6825..1db40c5 100644 --- a/lib/providers/rewrite_rules_provider.dart +++ b/lib/providers/rewrite_rules_provider.dart @@ -1,9 +1,16 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; class RewriteRulesProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + LoadStatus _loadStatus = LoadStatus.loading; List? _rewriteRules; @@ -26,4 +33,68 @@ class RewriteRulesProvider with ChangeNotifier { notifyListeners(); } } + + Future addDnsRewrite(RewriteRules rule) async { + final result = await _serversProvider!.apiClient!.addDnsRewriteRule( + data: { + "domain": rule.domain, + "answer": rule.answer + } + ); + + if (result['result'] == 'success') { + List data = rewriteRules!; + data.add(rule); + setRewriteRulesData(data); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future deleteDnsRewrite(RewriteRules rule) async { + final result = await _serversProvider!.apiClient!.deleteDnsRewriteRule( + data: { + "domain": rule.domain, + "answer": rule.answer + } + ); + + if (result['result'] == 'success') { + List data = rewriteRules!; + data = data.where((item) => item.domain != rule.domain).toList(); + setRewriteRulesData(data); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future fetchRules({ + bool? showLoading + }) async { + if (showLoading == true) { + _loadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getDnsRewriteRules(); + + if (result['result'] == 'success') { + _rewriteRules = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (showLoading == true) { + _loadStatus = LoadStatus.error; + notifyListeners(); + } + return false; + } + } } \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 25b3480..2ed27be 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -15,12 +14,17 @@ class ServersProvider with ChangeNotifier { List _serversList = []; Server? _selectedServer; + ApiClient? _apiClient; final UpdateAvailable _updateAvailable = UpdateAvailable( loadStatus: LoadStatus.loading, data: null, ); + ApiClient? get apiClient { + return _apiClient; + } + List get serversList { return _serversList; } @@ -59,6 +63,11 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } + void setApiClient(ApiClient client) { + _apiClient = client; + notifyListeners(); + } + Future createServer(Server server) async { final saved = await saveServerQuery(_dbInstance!, server); if (saved == null) { @@ -118,6 +127,11 @@ class ServersProvider with ChangeNotifier { } }).toList(); _serversList = newServers; + + if (selectedServer != null &&server.id == selectedServer!.id) { + _apiClient = ApiClient(server: server); + } + notifyListeners(); return null; } @@ -130,6 +144,7 @@ class ServersProvider with ChangeNotifier { final result = await removeServerQuery(_dbInstance!, server.id); if (result == true) { _selectedServer = null; + _apiClient = null; List newServers = _serversList.where((s) => s.id != server.id).toList(); _serversList = newServers; notifyListeners(); @@ -142,10 +157,10 @@ class ServersProvider with ChangeNotifier { void checkServerUpdatesAvailable(Server server) async { setUpdateAvailableLoadStatus(LoadStatus.loading, true); - final result = await checkServerUpdates(server: server); + final result = await _apiClient!.checkServerUpdates(); if (result['result'] == 'success') { UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); - final gitHubResult = await getUpdateChangelog(server: server, releaseTag: data.newVersion ?? data.currentVersion); + final gitHubResult = await _apiClient!.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); if (gitHubResult['result'] == 'success') { data.changelog = gitHubResult['body']; } @@ -171,21 +186,11 @@ class ServersProvider with ChangeNotifier { } } - Future> initializateServer(Server server) async { - _selectedServer = server; - final serverStatus = await getServerStatus(server); + Future initializateServer(Server server) async { + final serverStatus = await _apiClient!.getServerStatus(); if (serverStatus['result'] == 'success') { checkServerUpdatesAvailable(server); // Do not await - return { - "success": true, - "serverData": serverStatus['data'] - }; } - else { - return { - "success": false - }; - } } Future?> saveFromDb(List>? data) async { @@ -214,8 +219,9 @@ class ServersProvider with ChangeNotifier { notifyListeners(); if (defaultServer != null) { - final result = await initializateServer(defaultServer); - return result; + _selectedServer = defaultServer; + _apiClient = ApiClient(server: defaultServer); + initializateServer(defaultServer); } else { return null; diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 1ba9d30..006a753 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -3,12 +3,17 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/time_server_disabled.dart'; -import 'package:adguard_home_manager/models/server.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class StatusProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + LoadStatus _loadStatus = LoadStatus.loading; ServerStatus? _serverStatus; // serverStatus != null means server is connected List _protectionsManagementProcess = []; // protections that are currenty being enabled or disabled @@ -48,7 +53,6 @@ class StatusProvider with ChangeNotifier { } Future updateBlocking({ - required Server server, required String block, required bool newStatus, int? time @@ -58,8 +62,7 @@ class StatusProvider with ChangeNotifier { _protectionsManagementProcess.add('general'); notifyListeners(); - final result = await updateGeneralProtection( - server: server, + final result = await _serversProvider!.apiClient!.updateGeneralProtection( enable: newStatus, time: time ); @@ -88,7 +91,7 @@ class StatusProvider with ChangeNotifier { _protectionsManagementProcess.add('general'); notifyListeners(); - final result = await updateGeneralProtectionLegacy(server, newStatus); + final result = await _serversProvider!.apiClient!.updateGeneralProtectionLegacy(newStatus); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); @@ -107,8 +110,7 @@ class StatusProvider with ChangeNotifier { _protectionsManagementProcess.add('filtering'); notifyListeners(); - final result = await updateFiltering( - server: server, + final result = await _serversProvider!.apiClient!.updateFiltering( enable: newStatus, ); @@ -134,8 +136,8 @@ class StatusProvider with ChangeNotifier { referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true - ? await updateSafeSearchSettings(server: server, body: { 'enabled': newStatus }) - : await updateSafeSearchLegacy(server, newStatus); + ? await _serversProvider!.apiClient!.updateSafeSearchSettings(body: { 'enabled': newStatus }) + : await _serversProvider!.apiClient!.updateSafeSearchLegacy(newStatus); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeSearch').toList(); @@ -153,7 +155,7 @@ class StatusProvider with ChangeNotifier { _protectionsManagementProcess.add('safeBrowsing'); notifyListeners(); - final result = await updateSafeBrowsing(server, newStatus); + final result = await _serversProvider!.apiClient!.updateSafeBrowsing(newStatus); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeBrowsing').toList(); @@ -171,7 +173,7 @@ class StatusProvider with ChangeNotifier { _protectionsManagementProcess.add('parentalControl'); notifyListeners(); - final result = await updateParentalControl(server, newStatus); + final result = await _serversProvider!.apiClient!.updateParentalControl(newStatus); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'parentalControl').toList(); @@ -193,4 +195,98 @@ class StatusProvider with ChangeNotifier { void setFilteringEnabledStatus(bool status) { _serverStatus!.filteringEnabled = status; } + + Future getFilteringRules() async { + final result = await _serversProvider!.apiClient!.getFilteringRules(); + if (result['result'] == 'success') { + _filteringStatus = result['data']; + notifyListeners(); + return true; + } + else { + return false; + } + } + + Future getServerStatus({ + bool? withLoadingIndicator + }) async { + if (withLoadingIndicator == true) { + _loadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getServerStatus(); + if (result['result'] == 'success') { + setServerStatusData( + data: result['data'] + ); + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (withLoadingIndicator == true) _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future blockUnblockDomain({ + required String domain, + required String newStatus + }) async { + final rules = await _serversProvider!.apiClient!.getFilteringRules(); + + if (rules['result'] == 'success') { + FilteringStatus oldStatus = serverStatus!.filteringStatus; + + List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); + if (newStatus == 'block') { + newRules.add("||$domain^"); + } + else if (newStatus == 'unblock') { + newRules.add("@@||$domain^"); + } + FilteringStatus newObj = serverStatus!.filteringStatus; + newObj.userRules = newRules; + _filteringStatus = newObj; + + final result = await _serversProvider!.apiClient!.postFilteringRules(data: {'rules': newRules}); + + if (result['result'] == 'success') { + return true; + } + else { + _filteringStatus = oldStatus; + return false; + } + } + else { + return false; + } + } + + Future updateSafeSearchConfig(Map status) async { + final result = await _serversProvider!.apiClient!.updateSafeSearchSettings( + body: status + ); + + if (result['result'] == 'success') { + ServerStatus data = serverStatus!; + data.safeSearchEnabled = status['enabled'] ?? false; + data.safeSeachBing = status['bing'] ?? false; + data.safeSearchDuckduckgo = status['duckduckgo'] ?? false; + data.safeSearchGoogle = status['google'] ?? false; + data.safeSearchPixabay = status['pixabay'] ?? false; + data.safeSearchYandex = status['yandex'] ?? false; + data.safeSearchYoutube = status['youtube'] ?? false; + + setServerStatusData(data: data); + return true; + } + else { + notifyListeners(); + return false; + } + } } \ No newline at end of file diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 5c876f0..6b7f33c 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -17,22 +17,16 @@ import 'package:adguard_home_manager/screens/clients/options_modal.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/functions/maps_fns.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class AddedList extends StatefulWidget { final ScrollController scrollController; - final LoadStatus loadStatus; final List data; - final Future Function() fetchClients; final void Function(Client) onClientSelected; final Client? selectedClient; final bool splitView; @@ -40,9 +34,7 @@ class AddedList extends StatefulWidget { const AddedList({ Key? key, required this.scrollController, - required this.loadStatus, required this.data, - required this.fetchClients, required this.onClientSelected, this.selectedClient, required this.splitView @@ -78,7 +70,6 @@ class _AddedListState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -89,31 +80,11 @@ class _AddedListState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingClient); - final result = await postUpdateClient(server: serversProvider.selectedServer!, data: { - 'name': client.name, - 'data': serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == false - ? removePropFromMap(client.toJson(), 'safesearch_enabled') - : removePropFromMap(client.toJson(), 'safe_search') - }); + final result = await clientsProvider.editClient(client); processModal.close(); - if (result['result'] == 'success') { - Clients clientsData = clientsProvider.clients!; - clientsData.clients = clientsData.clients.map((e) { - if (e.name == client.name) { - return client; - } - else { - return e; - } - }).toList(); - clientsProvider.setClientsData(clientsData); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientUpdatedSuccessfully, @@ -121,8 +92,6 @@ class _AddedListState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotUpdated, @@ -135,19 +104,14 @@ class _AddedListState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); - final result = await postDeleteClient(server: serversProvider.selectedServer!, name: client.name); + final result = await clientsProvider.deleteClient(client); processModal.close(); - if (result['result'] == 'success') { - Clients clientsData = clientsProvider.clients!; - clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); - clientsProvider.setClientsData(clientsData); - + if (result == true) { if (widget.splitView == true) { SplitView.of(context).popUntil(0); } - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientDeletedSuccessfully, @@ -155,15 +119,13 @@ class _AddedListState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotDeleted, color: Colors.red ); } - } + } void openClientModal(Client client) { if (width > 900 || !(Platform.isAndroid | Platform.isIOS)) { @@ -264,7 +226,7 @@ class _AddedListState extends State { ), const SizedBox(height: 30), TextButton.icon( - onPressed: widget.fetchClients, + onPressed: () => clientsProvider.fetchClients(updateLoading: true), icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh), ) @@ -294,8 +256,10 @@ class _AddedListState extends State { ], ), ), - loadStatus: widget.loadStatus, - onRefresh: widget.fetchClients, + loadStatus: statusProvider.loadStatus == LoadStatus.loading || clientsProvider.loadStatus == LoadStatus.loading + ? LoadStatus.loading + : clientsProvider.loadStatus, + onRefresh: () => clientsProvider.fetchClients(updateLoading: false), fab: const ClientsFab(), fabVisible: isVisible, ); diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 98a9391..1dada10 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -14,7 +14,6 @@ import 'package:adguard_home_manager/screens/clients/added_list.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -32,28 +31,11 @@ class _ClientsState extends State with TickerProviderStateMixin { bool searchMode = false; final TextEditingController searchController = TextEditingController(); - Future fetchClients() async { - final clientsProvider = Provider.of(context, listen: false); - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - clientsProvider.setClientsLoadStatus(LoadStatus.loading, false); - final result = await getClients(serversProvider.selectedServer!); - if (mounted) { - if (result['result'] == 'success') { - clientsProvider.setClientsData(result['data']); - clientsProvider.setClientsLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result['log']); - clientsProvider.setClientsLoadStatus(LoadStatus.error, true); - } - } - } - @override void initState() { - fetchClients(); + final clientsProvider = Provider.of(context, listen: false); + clientsProvider.fetchClients(updateLoading: true); + super.initState(); tabController = TabController( initialIndex: 0, @@ -112,10 +94,8 @@ class _ClientsState extends State with TickerProviderStateMixin { children: [ ClientsList( scrollController: scrollController, - loadStatus: clientsProvider.loadStatus, data: clientsProvider.loadStatus == LoadStatus.loaded ? clientsProvider.filteredActiveClients : [], - fetchClients: fetchClients, onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( builder: (context) => LogsListClient( ip: client.ip, @@ -128,10 +108,8 @@ class _ClientsState extends State with TickerProviderStateMixin { ), AddedList( scrollController: scrollController, - loadStatus: clientsProvider.loadStatus, data: clientsProvider.loadStatus == LoadStatus.loaded ? clientsProvider.filteredAddedClients : [], - fetchClients: fetchClients, onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( builder: (context) => LogsListClient( ip: client.ids[0], @@ -165,7 +143,6 @@ class _ClientsState extends State with TickerProviderStateMixin { child: ClientsDesktopView( serversProvider: serversProvider, appConfigProvider: appConfigProvider, - fetchClients: fetchClients, ) ); } diff --git a/lib/screens/clients/clients_desktop_view.dart b/lib/screens/clients/clients_desktop_view.dart index 04bfc35..d6707ad 100644 --- a/lib/screens/clients/clients_desktop_view.dart +++ b/lib/screens/clients/clients_desktop_view.dart @@ -19,13 +19,11 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; class ClientsDesktopView extends StatefulWidget { final ServersProvider serversProvider; final AppConfigProvider appConfigProvider; - final Future Function() fetchClients; const ClientsDesktopView({ Key? key, required this.serversProvider, required this.appConfigProvider, - required this.fetchClients }) : super(key: key); @override @@ -94,10 +92,8 @@ class _ClientsDesktopViewState extends State with TickerPro children: [ ClientsList( scrollController: scrollController, - loadStatus: clientsProvider.loadStatus, data: clientsProvider.loadStatus == LoadStatus.loaded ? clientsProvider.filteredActiveClients : [], - fetchClients: widget.fetchClients, onClientSelected: (client) => setState(() { selectedAddedClient = null; selectedActiveClient = client; @@ -116,10 +112,8 @@ class _ClientsDesktopViewState extends State with TickerPro ), AddedList( scrollController: scrollController, - loadStatus: clientsProvider.loadStatus, data: clientsProvider.loadStatus == LoadStatus.loaded ? clientsProvider.filteredAddedClients : [], - fetchClients: widget.fetchClients, onClientSelected: (client) => setState(() { selectedActiveClient = null; selectedAddedClient = client; diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index de284c5..4ecd98c 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -1,18 +1,17 @@ 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/active_client_tile.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; class ClientsList extends StatelessWidget { final ScrollController scrollController; - final LoadStatus loadStatus; final List data; - final Future Function() fetchClients; final void Function(AutoClient) onClientSelected; final AutoClient? selectedClient; final bool splitView; @@ -21,9 +20,7 @@ class ClientsList extends StatelessWidget { const ClientsList({ Key? key, required this.scrollController, - required this.loadStatus, required this.data, - required this.fetchClients, required this.onClientSelected, this.selectedClient, required this.splitView, @@ -32,6 +29,8 @@ class ClientsList extends StatelessWidget { @override Widget build(BuildContext context) { + final clientsProvider = Provider.of(context); + return CustomTabContentList( listPadding: splitView == true ? const EdgeInsets.only(top: 8) @@ -79,7 +78,7 @@ class ClientsList extends StatelessWidget { ), const SizedBox(height: 30), TextButton.icon( - onPressed: fetchClients, + onPressed: () => clientsProvider.fetchClients(updateLoading: false), icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh) ) @@ -110,8 +109,8 @@ class ClientsList extends StatelessWidget { ], ), ), - loadStatus: loadStatus, - onRefresh: fetchClients + loadStatus: clientsProvider.loadStatus, + onRefresh: () => clientsProvider.fetchClients(updateLoading: false), ); } } \ No newline at end of file diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 61b2aec..8d73050 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -10,13 +10,9 @@ import 'package:adguard_home_manager/screens/clients/client_screen.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/functions/maps_fns.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class ClientsFab extends StatelessWidget { @@ -24,7 +20,6 @@ class ClientsFab extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final statusProvider = Provider.of(context); final clientsProvider = Provider.of(context); @@ -35,24 +30,11 @@ class ClientsFab extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingClient); - final result = await postAddClient( - server: serversProvider.selectedServer!, - data: serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == false - ? removePropFromMap(client.toJson(), 'safesearch_enabled') - : removePropFromMap(client.toJson(), 'safe_search') - ); + final result = await clientsProvider.addClient(client); processModal.close(); - if (result['result'] == 'success') { - Clients clientsData = clientsProvider.clients!; - clientsData.clients.add(client); - clientsProvider.setClientsData(clientsData); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAddedSuccessfully, @@ -60,8 +42,6 @@ class ClientsFab extends StatelessWidget { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotAdded, diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/logs_list_client.dart index 6fe4782..0ddc99a 100644 --- a/lib/screens/clients/logs_list_client.dart +++ b/lib/screens/clients/logs_list_client.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:async/async.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; @@ -10,7 +11,6 @@ import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class LogsListClient extends StatefulWidget { final String ip; @@ -53,6 +53,8 @@ class _LogsListClientState extends State { String? responseStatus, String? searchText, }) async { + final serversProvider = Provider.of(context, listen: false); + int offst = inOffset ?? offset; if (loadingMore != null && loadingMore == true) { @@ -62,8 +64,7 @@ class _LogsListClientState extends State { if (cancelableRequest != null) cancelableRequest!.cancel(); cancelableRequest = CancelableOperation.fromFuture( - getLogs( - server: widget.serversProvider.selectedServer!, + serversProvider.apiClient!.getLogs( count: logsQuantity, offset: offst, search: '"${widget.ip}"' diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index 569d50c..4d2c754 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -14,7 +14,6 @@ import 'package:adguard_home_manager/screens/clients/options_modal.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/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -22,7 +21,6 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class SearchClients extends StatefulWidget { const SearchClients({Key? key}) : super(key: key); @@ -84,7 +82,6 @@ class _SearchClientsState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -95,19 +92,11 @@ class _SearchClientsState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); - final result = await postDeleteClient(server: serversProvider.selectedServer!, name: client.name); + final result = await clientsProvider.deleteClient(client); processModal.close(); - if (result['result'] == 'success') { - Clients clientsData = clientsProvider.clients!; - clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); - clientsProvider.setClientsData(clientsData); - setState(() { - clients = clientsData.clients; - }); - search(searchController.text); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientDeletedSuccessfully, @@ -115,44 +104,23 @@ class _SearchClientsState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotDeleted, color: Colors.red ); } - } + } void confirmEditClient(Client client) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingClient); - final result = await postUpdateClient(server: serversProvider.selectedServer!, data: { - 'name': client.name, - 'data': client.toJson() - }); + final result = await clientsProvider.editClient(client); processModal.close(); - if (result['result'] == 'success') { - Clients clientsData = clientsProvider.clients!; - clientsData.clients = clientsData.clients.map((e) { - if (e.name == client.name) { - return client; - } - else { - return e; - } - }).toList(); - clientsProvider.setClientsData(clientsData); - - setState(() { - clients = clientsData.clients; - }); - search(searchController.text); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientUpdatedSuccessfully, @@ -160,8 +128,6 @@ class _SearchClientsState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotUpdated, diff --git a/lib/screens/clients/services_modal.dart b/lib/screens/clients/services_modal.dart index 827f2d3..1a98275 100644 --- a/lib/screens/clients/services_modal.dart +++ b/lib/screens/clients/services_modal.dart @@ -2,11 +2,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class ServicesModal extends StatefulWidget { final List blockedServices; @@ -25,28 +22,14 @@ class ServicesModal extends StatefulWidget { class _ServicesModalStateWidget extends State { List blockedServices = []; - Future loadBlockedServices() async { - final filteringProvider = Provider.of(context, listen: false); - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - final result = await getBlockedServices(server: serversProvider.selectedServer!); - if (result['result'] == 'success') { - filteringProvider.setBlockedServicesListLoadStatus(LoadStatus.loaded, true); - filteringProvider.setBlockedServiceListData(result['data']); - } - else { - filteringProvider.setBlockedServicesListLoadStatus(LoadStatus.error, true); - appConfigProvider.addLog(result['log']); - } - } + @override void initState() { final filteringProvider = Provider.of(context, listen: false); if (filteringProvider.blockedServicesLoadStatus != LoadStatus.loaded) { - loadBlockedServices(); + filteringProvider.getBlockedServices(); } blockedServices = widget.blockedServices; diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 34bf53e..0292d3a 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -40,18 +40,11 @@ class AddFiltersButton extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingRule); - final List newRules = filteringProvider.filtering!.userRules; - newRules.add(rule); - - final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules); + final result = await filteringProvider.addCustomRule(rule); processModal.close(); - if (result['result'] == 'success') { - Filtering filteringData = filteringProvider.filtering!; - filteringData.userRules = newRules; - filteringProvider.setFilteringData(filteringData); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleAddedSuccessfully, @@ -59,8 +52,6 @@ class AddFiltersButton extends StatelessWidget { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleNotAdded, @@ -97,58 +88,25 @@ class AddFiltersButton extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingList); - final result1 = await addFilteringList(server: serversProvider.selectedServer!, data: { - 'name': name, - 'url': url, - 'whitelist': type == 'whitelist' ? true : false - }); + final result = await filteringProvider.addList(name: name, url: url, type: type); - if (result1['result'] == 'success') { - if (result1['data'].toString().contains("OK")) { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - final items = result1['data'].toString().split(' ')[1]; + processModal.close(); - if (result2['result'] == 'success') { - filteringProvider.setFilteringData(result2['data']); - filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - filteringProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - processModal.close(); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: "${AppLocalizations.of(context)!.listAdded} $items.", - color: Colors.green - ); - } - else { - processModal.close(); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listNotAdded, - color: Colors.red - ); - } + if (result['success'] == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: "${AppLocalizations.of(context)!.listAdded} ${result['data']}.", + color: Colors.green + ); } - else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains("Couldn't fetch filter from url")) { - processModal.close(); - appConfigProvider.addLog(result1['log']); - + else if (result['success'] == false && result['error'] == 'invalid_url') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listUrlInvalid, color: Colors.red ); } - else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains('Filter URL already added')) { - processModal.close(); - appConfigProvider.addLog(result1['log']); - + else if (result['success'] == false && result['error'] == 'url_exists') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listAlreadyAdded, @@ -156,9 +114,6 @@ class AddFiltersButton extends StatelessWidget { ); } else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listNotAdded, diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/blocked_services_screen.dart index 786711a..75d941b 100644 --- a/lib/screens/filters/blocked_services_screen.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -9,9 +9,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class BlockedServicesScreen extends StatefulWidget { final bool dialog; @@ -28,28 +26,12 @@ class BlockedServicesScreen extends StatefulWidget { class _BlockedServicesScreenStateWidget extends State { List values = []; - Future loadBlockedServices() async { - final serversProvider = Provider.of(context, listen: false); - final filteringProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - final result = await getBlockedServices(server: serversProvider.selectedServer!); - if (result['result'] == 'success') { - filteringProvider.setBlockedServicesListLoadStatus(LoadStatus.loaded, true); - filteringProvider.setBlockedServiceListData(result['data']); - } - else { - filteringProvider.setBlockedServicesListLoadStatus(LoadStatus.loaded, true); - appConfigProvider.addLog(result['log']); - } - } - @override void initState() { final filteringProvider = Provider.of(context, listen: false); if (filteringProvider.blockedServicesLoadStatus != LoadStatus.loaded) { - loadBlockedServices(); + filteringProvider.loadBlockedServices(showLoading: true); } values = filteringProvider.filtering!.blockedServices; @@ -59,7 +41,6 @@ class _BlockedServicesScreenStateWidget extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -80,13 +61,11 @@ class _BlockedServicesScreenStateWidget extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updating); - final result = await setBlockedServices(server: serversProvider.selectedServer!, data: values); + final result = await filteringProvider.updateBlockedServices(values); processModal.close(); - if (result['result'] == 'success') { - filteringProvider.setBlockedServices(values); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.blockedServicesUpdated, @@ -265,7 +244,16 @@ class _BlockedServicesScreenStateWidget extends State { ], ), body: RefreshIndicator( - onRefresh: loadBlockedServices, + onRefresh: () async { + final result = await filteringProvider.loadBlockedServices(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.blockedServicesListNotLoaded, + color: Colors.red + ); + } + }, child: body() ), ); diff --git a/lib/screens/filters/check_host_modal.dart b/lib/screens/filters/check_host_modal.dart index 6678ddb..90e93ab 100644 --- a/lib/screens/filters/check_host_modal.dart +++ b/lib/screens/filters/check_host_modal.dart @@ -6,7 +6,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class CheckHostModal extends StatefulWidget { @@ -57,11 +56,11 @@ class _CheckHostModalState extends State { final appConfigProvider = Provider.of(context); void checkHost() async { + setState(() => resultWidget = checking()); + + final result = await serversProvider.apiClient!.checkHostFiltered(host: domainController.text); + if (mounted) { - setState(() => resultWidget = checking()); - - final result = await checkHostFiltered(server: serversProvider.selectedServer!, host: domainController.text); - if (result['result'] == 'success') { final status = getFilteredStatus(context, appConfigProvider, result['data']['reason'], true); if (mounted) { @@ -98,26 +97,24 @@ class _CheckHostModalState extends State { } } else { - if (mounted) { - setState(() => resultWidget = Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.cancel, - size: 18, + setState(() => resultWidget = Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.cancel, + size: 18, + color: Colors.red, + ), + const SizedBox(width: 10), + Text( + AppLocalizations.of(context)!.check, + style: const TextStyle( color: Colors.red, + fontWeight: FontWeight.w500 ), - const SizedBox(width: 10), - Text( - AppLocalizations.of(context)!.check, - style: const TextStyle( - color: Colors.red, - fontWeight: FontWeight.w500 - ), - ) - ], - )); - } + ) + ], + )); } } } diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 5a96716..8706f1a 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -2,18 +2,21 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_button.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; class CustomRulesList extends StatefulWidget { final LoadStatus loadStatus; final ScrollController scrollController; final List data; - final Future Function() fetchData; final void Function(String) onRemoveCustomRule; const CustomRulesList({ @@ -21,7 +24,6 @@ class CustomRulesList extends StatefulWidget { required this.loadStatus, required this.scrollController, required this.data, - required this.fetchData, required this.onRemoveCustomRule }) : super(key: key); @@ -55,6 +57,9 @@ class _CustomRulesListState extends State { @override Widget build(BuildContext context) { + final filteringProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + bool checkIfComment(String value) { final regex = RegExp(r'^(!|#).*$'); if (regex.hasMatch(value)) { @@ -155,7 +160,16 @@ class _CustomRulesListState extends State { ), const SizedBox(height: 30), TextButton.icon( - onPressed: widget.fetchData, + onPressed: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh), ) @@ -186,7 +200,16 @@ class _CustomRulesListState extends State { ), ), loadStatus: widget.loadStatus, - onRefresh: widget.fetchData, + onRefresh: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, fab: AddFiltersButton( type: 'custom_rule', widget: (fn) => FloatingActionButton( diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 763eb95..00cc214 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -21,9 +21,7 @@ import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class Filters extends StatefulWidget { const Filters({Key? key}) : super(key: key); @@ -33,83 +31,41 @@ class Filters extends StatefulWidget { } class _FiltersState extends State { - Future fetchFilters() async { - final filteringProvider = Provider.of(context, listen: false); - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - filteringProvider.setFilteringLoadStatus(LoadStatus.loading, false); - - final result = await getFiltering(server: serversProvider.selectedServer!); - - if (mounted) { - if (result['result'] == 'success') { - filteringProvider.setFilteringData(result['data']); - filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, false); - } - else { - appConfigProvider.addLog(result['log']); - filteringProvider.setFilteringLoadStatus(LoadStatus.error, false); - } - } - } - List generateClientsList(List clients, List ips) { return clients.where((client) => ips.contains(client.ip)).toList(); } @override void initState() { - fetchFilters(); + final filteringProvider = Provider.of(context, listen: false); + filteringProvider.fetchFilters(showLoading: true); super.initState(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final filteringProvider = Provider.of(context); final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; - void fetchUpdateLists() async { + void updateLists() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingLists); - final result = await updateLists(server: serversProvider.selectedServer!); + final result = await filteringProvider.updateLists(); - if (result['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); + processModal.close(); - processModal.close(); - - if (mounted) { - if (result2['result'] == 'success') { - filteringProvider.setFilteringData(result2['data']); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: "${result['data']['updated']} ${AppLocalizations.of(context)!.listsUpdated}", - color: Colors.green - ); - } - else { - appConfigProvider.addLog(result2['log']); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listsNotLoaded, - color: Colors.red - ); - } - } - + if (result['success'] == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: "${result['data']['updated']} ${AppLocalizations.of(context)!.listsUpdated}", + color: Colors.green + ); } else { - processModal.close(); - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listsNotUpdated, @@ -149,16 +105,11 @@ class _FiltersState extends State { : AppLocalizations.of(context)!.enableFiltering ); - final result = await updateFiltering( - server: serversProvider.selectedServer!, - enable: !statusProvider.serverStatus!.filteringEnabled - ); + final result = await filteringProvider.enableDisableFiltering(); processModal.close(); - if (result['result'] == 'success') { - filteringProvider.setFilteringProtectionStatus(!statusProvider.serverStatus!.filteringEnabled); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.filteringStatusUpdated, @@ -178,16 +129,11 @@ class _FiltersState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.changingUpdateFrequency); - final result = await requestChangeUpdateFrequency(server: serversProvider.selectedServer!, data: { - "enabled": filteringProvider.filtering!.enabled, - "interval": value - }); + final result = await filteringProvider.changeUpdateFrequency(value); processModal.close(); - if (result['result'] == 'success') { - filteringProvider.setFiltersUpdateFrequency(value); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.updateFrequencyChanged, @@ -230,17 +176,11 @@ class _FiltersState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deletingRule); - final List newRules = filteringProvider.filtering!.userRules.where((r) => r != rule).toList(); - - final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules); + final result = await filteringProvider.removeCustomRule(rule); processModal.close(); - if (result['result'] == 'success') { - Filtering filteringData = filteringProvider.filtering!; - filteringData.userRules = newRules; - filteringProvider.setFilteringData(filteringData); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleRemovedSuccessfully, @@ -248,13 +188,11 @@ class _FiltersState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleNotRemoved, color: Colors.red - ); + ); } } @@ -295,7 +233,7 @@ class _FiltersState extends State { List actions() { if (filteringProvider.loadStatus == LoadStatus.loaded) { return [ - IconButton( + if (statusProvider.loadStatus == LoadStatus.loaded) IconButton( onPressed: enableDisableFiltering, tooltip: filteringProvider.filtering!.enabled == true ? AppLocalizations.of(context)!.disableFiltering @@ -364,7 +302,7 @@ class _FiltersState extends State { PopupMenuButton( itemBuilder: (context) => [ PopupMenuItem( - onTap: fetchUpdateLists, + onTap: updateLists, child: Row( children: [ const Icon(Icons.sync_rounded), @@ -408,13 +346,11 @@ class _FiltersState extends State { onRemoveCustomRule: openRemoveCustomRuleModal, onOpenDetailsModal: openListDetails, actions: actions(), - refreshData: fetchFilters, ); } else { return FiltersTabsView( - appConfigProvider: appConfigProvider, - fetchFilters: fetchFilters, + appConfigProvider: appConfigProvider, actions: actions(), onRemoveCustomRule: openRemoveCustomRuleModal, onOpenDetailsModal: openListDetails, diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index 8f87b34..3fdf3d5 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -14,6 +14,8 @@ import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/models/filtering.dart'; @@ -21,7 +23,6 @@ class FiltersList extends StatefulWidget { final LoadStatus loadStatus; final ScrollController scrollController; final List data; - final Future Function() fetchData; final String type; final void Function(Filter, String) onOpenDetailsScreen; @@ -30,7 +31,6 @@ class FiltersList extends StatefulWidget { required this.loadStatus, required this.scrollController, required this.data, - required this.fetchData, required this.type, required this.onOpenDetailsScreen }) : super(key: key); @@ -65,6 +65,7 @@ class _FiltersListState extends State { @override Widget build(BuildContext context) { + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); return CustomTabContentList( @@ -129,7 +130,16 @@ class _FiltersListState extends State { ), const SizedBox(height: 30), TextButton.icon( - onPressed: widget.fetchData, + onPressed: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh), ) @@ -160,7 +170,16 @@ class _FiltersListState extends State { ), ), loadStatus: widget.loadStatus, - onRefresh: widget.fetchData, + onRefresh: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, fab: AddFiltersButton( type: widget.type, widget: (fn) => FloatingActionButton( diff --git a/lib/screens/filters/filters_tabs_view.dart b/lib/screens/filters/filters_tabs_view.dart index a4c08cd..81cd67a 100644 --- a/lib/screens/filters/filters_tabs_view.dart +++ b/lib/screens/filters/filters_tabs_view.dart @@ -12,7 +12,6 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; class FiltersTabsView extends StatefulWidget { final AppConfigProvider appConfigProvider; - final Future Function() fetchFilters; final List actions; final void Function(String) onRemoveCustomRule; final void Function(Filter, String) onOpenDetailsModal; @@ -20,7 +19,6 @@ class FiltersTabsView extends StatefulWidget { const FiltersTabsView({ Key? key, required this.appConfigProvider, - required this.fetchFilters, required this.actions, required this.onOpenDetailsModal, required this.onRemoveCustomRule @@ -36,7 +34,6 @@ class _FiltersTabsViewState extends State with TickerProviderSt @override void initState() { - widget.fetchFilters(); super.initState(); tabController = TabController( initialIndex: 0, @@ -115,7 +112,6 @@ class _FiltersTabsViewState extends State with TickerProviderSt type: 'whitelist', data: filteringProvider.loadStatus == LoadStatus.loaded ? filteringProvider.filtering!.whitelistFilters : [], - fetchData: widget.fetchFilters, onOpenDetailsScreen: widget.onOpenDetailsModal, ), FiltersList( @@ -124,7 +120,6 @@ class _FiltersTabsViewState extends State with TickerProviderSt type: 'blacklist', data: filteringProvider.loadStatus == LoadStatus.loaded ? filteringProvider.filtering!.filters : [], - fetchData: widget.fetchFilters, onOpenDetailsScreen: widget.onOpenDetailsModal, ), CustomRulesList( @@ -132,7 +127,6 @@ class _FiltersTabsViewState extends State with TickerProviderSt scrollController: scrollController, data: filteringProvider.loadStatus == LoadStatus.loaded ? filteringProvider.filtering!.userRules : [], - fetchData: widget.fetchFilters, onRemoveCustomRule: widget.onRemoveCustomRule, ), ] diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index ba65e12..c481749 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -14,6 +14,7 @@ import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; @@ -24,14 +25,12 @@ class FiltersTripleColumn extends StatelessWidget { final void Function(String) onRemoveCustomRule; final void Function(Filter, String) onOpenDetailsModal; final List actions; - final Future Function() refreshData; const FiltersTripleColumn({ Key? key, required this.onRemoveCustomRule, required this.onOpenDetailsModal, required this.actions, - required this.refreshData }) : super(key: key); @override @@ -330,7 +329,16 @@ class FiltersTripleColumn extends StatelessWidget { title: Text(AppLocalizations.of(context)!.filters), actions: [ IconButton( - onPressed: refreshData, + onPressed: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, icon: const Icon(Icons.refresh_rounded), tooltip: AppLocalizations.of(context)!.refresh, ), diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index f68693b..42464ec 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -9,11 +9,11 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart'; -import 'package:adguard_home_manager/screens/filters/list_functions.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; @@ -76,6 +76,35 @@ class _ListDetailsScreenState extends State { // ------- // } + void updateList(FilteringListActions action) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open( + list!.enabled == true + ? AppLocalizations.of(context)!.disablingList + : AppLocalizations.of(context)!.enablingList, + ); + final result = await filteringProvider.updateList( + list: list, + type: widget.type, + action: action + ); + processModal.close(); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + } + List content() { return [ CustomListTile( @@ -174,27 +203,9 @@ class _ListDetailsScreenState extends State { builder: (ctx) => AddListModal( list: list, type: widget.type, - onEdit: ({required Filter list, required String type}) async { - final result = await editList( - context: context, - list: list, - type: widget.type - ); - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - }, + onEdit: ({required Filter list, required String type}) async => updateList( + FilteringListActions.edit + ), dialog: true, ), ) @@ -205,27 +216,9 @@ class _ListDetailsScreenState extends State { builder: (ctx) => AddListModal( list: list, type: widget.type, - onEdit: ({required Filter list, required String type}) async { - final result = await editList( - context: context, - list: list, - type: widget.type - ); - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - }, + onEdit: ({required Filter list, required String type}) async => updateList( + FilteringListActions.edit + ), dialog: false, ), isScrollControlled: true, @@ -242,11 +235,13 @@ class _ListDetailsScreenState extends State { context: context, builder: (c) => DeleteListModal( onConfirm: () async { - final result = await deleteList( - context: context, - list: list!, + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.deletingList); + final result = await filteringProvider.deleteList( + listUrl: list!.url, type: widget.type, ); + processModal.close(); if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, @@ -306,27 +301,11 @@ class _ListDetailsScreenState extends State { if (list != null) Row( children: [ IconButton( - onPressed: () async { - final result = await enableDisableList( - context: context, - list: list!, - listType: widget.type, - ); - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - }, + onPressed: () => updateList( + list!.enabled == true + ? FilteringListActions.disable + : FilteringListActions.enable + ), icon: Icon( list.enabled == true ? Icons.gpp_bad_rounded @@ -391,27 +370,11 @@ class _ListDetailsScreenState extends State { : -70, right: 20, child: FloatingActionButton( - onPressed: () async { - final result = await enableDisableList( - context: context, - list: list!, - listType: widget.type, - ); - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - }, + onPressed: () => updateList( + list!.enabled == true + ? FilteringListActions.disable + : FilteringListActions.enable + ), child: Icon( list.enabled == true ? Icons.gpp_bad_rounded diff --git a/lib/screens/filters/list_functions.dart b/lib/screens/filters/list_functions.dart deleted file mode 100644 index 2075495..0000000 --- a/lib/screens/filters/list_functions.dart +++ /dev/null @@ -1,149 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/providers/filtering_provider.dart'; -import 'package:adguard_home_manager/models/filtering.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; - -Future enableDisableList({ - required BuildContext context, - required Filter list, - required String listType, -}) async { - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - final filteringProvider = Provider.of(context, listen: false); - - ProcessModal processModal = ProcessModal(context: context); - processModal.open( - list.enabled == true - ? AppLocalizations.of(context)!.disablingList - : AppLocalizations.of(context)!.enablingList, - ); - - final result = await updateFilterList(server: serversProvider.selectedServer!, data: { - "data": { - "enabled": !list.enabled, - "name": list.name, - "url": list.url - }, - "url": list.url, - "whitelist": listType == 'whitelist' ? true : false - }); - - processModal.close(); - - if (result['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - filteringProvider.setFilteringData(result2['data']); - filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - filteringProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - return true; - } - else { - appConfigProvider.addLog(result['log']); - - return false; - } -} - -Future editList({ - required BuildContext context, - required Filter list, - required String type -}) async { - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - final filteringProvider = Provider.of(context, listen: false); - - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.updatingListData); - - final result1 = await updateFilterList(server: serversProvider.selectedServer!, data: { - "data": { - "enabled": list.enabled, - "name": list.name, - "url": list.url - }, - "url": list.url, - "whitelist": type == 'whitelist' ? true : false - }); - - if (result1['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - filteringProvider.setFilteringData(result2['data']); - filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - filteringProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - processModal.close(); - - return true; - } - else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - - return false; - } -} - -Future deleteList({ - required BuildContext context, - required Filter list, - required String type -}) async { - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - final filteringProvider = Provider.of(context, listen: false); - - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.deletingList); - - final result1 = await deleteFilterList(server: serversProvider.selectedServer!, data: { - "url": list.url, - "whitelist": type == 'whitelist' ? true : false - }); - - if (result1['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - filteringProvider.setFilteringData(result2['data']); - filteringProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - filteringProvider.setFilteringLoadStatus(LoadStatus.loading, true); - } - - processModal.close(); - - return true; - } - else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - - return false; - } -} \ No newline at end of file diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 7a9dc2a..6482ecd 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -1,16 +1,17 @@ // ignore_for_file: use_build_context_synchronously +import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:flutter/material.dart'; import 'package:contextmenu/contextmenu.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/filters/list_functions.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -29,14 +30,27 @@ class ListOptionsMenu extends StatelessWidget { @override Widget build(BuildContext context) { + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void enableDisable() async { - final result = await enableDisableList( - context: context, - list: list, - listType: listType, + ProcessModal processModal = ProcessModal(context: context); + processModal.open( + list.enabled == true + ? AppLocalizations.of(context)!.disablingList + : AppLocalizations.of(context)!.enablingList ); + + final result = await filteringProvider.updateList( + list: list, + type: listType, + action: list.enabled == true + ? FilteringListActions.disable + : FilteringListActions.enable + ); + + processModal.close(); + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 31912e9..e288175 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -18,9 +18,7 @@ import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class Home extends StatefulWidget { const Home({Key? key}) : super(key: key); @@ -35,6 +33,8 @@ class _HomeState extends State { @override initState(){ + Provider.of(context, listen: false).getServerStatus(); + super.initState(); isVisible = true; @@ -56,7 +56,6 @@ class _HomeState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -280,14 +279,8 @@ class _HomeState extends State { builder: (context) => RefreshIndicator( color: Theme.of(context).colorScheme.primary, onRefresh: () async { - final result = await getServerStatus(serversProvider.selectedServer!); - if (result['result'] == 'success') { - statusProvider.setServerStatusData( - data: result['data'] - ); - } - else { - appConfigProvider.addLog(result['log']); + final result = await statusProvider.getServerStatus(); + if (result == false) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverStatusNotRefreshed, diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 5329d3c..f35820c 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -13,8 +13,6 @@ import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class ManagementModal extends StatefulWidget { final bool dialog; @@ -74,7 +72,6 @@ class _ManagementModalState extends State with SingleTickerProv @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -92,16 +89,12 @@ class _ManagementModalState extends State with SingleTickerProv setState(() { timer.cancel(); }); - final result = await getServerStatus(serversProvider.selectedServer!); - if (result['result'] == 'success') { - statusProvider.setServerStatusData( - data: result['data'] - ); + final result = await statusProvider.getServerStatus(); + if (result == false) { + setState(() { + start = start - 1; + }); } - } else { - setState(() { - start = start - 1; - }); } }, ); @@ -133,7 +126,6 @@ class _ManagementModalState extends State with SingleTickerProv int? time }) async { final result = await statusProvider.updateBlocking( - server: serversProvider.selectedServer!, block: filter, newStatus: value, time: time diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 6356b7a..f2b836c 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -9,17 +9,14 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/domain_options.dart'; import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; -import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/filtering_status.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class TopItems extends StatelessWidget { final String type; @@ -37,7 +34,6 @@ class TopItems extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); @@ -60,52 +56,26 @@ class TopItems extends StatelessWidget { final ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingUserFilters); - final rules = await getFilteringRules(server: serversProvider.selectedServer!); + final rules = await statusProvider.blockUnblockDomain( + domain: domain, + newStatus: newStatus + ); - if (rules['result'] == 'success') { - FilteringStatus oldStatus = statusProvider.serverStatus!.filteringStatus; + processModal.close(); - List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); - if (newStatus == 'block') { - newRules.add("||$domain^"); - } - else if (newStatus == 'unblock') { - newRules.add("@@||$domain^"); - } - FilteringStatus newObj = statusProvider.serverStatus!.filteringStatus; - newObj.userRules = newRules; - statusProvider.setFilteringStatus(newObj); - - final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); - - processModal.close(); - - if (result['result'] == 'success') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesUpdated), - backgroundColor: Colors.green, - ) - ); - } - else { - appConfigProvider.addLog(result['log']); - statusProvider.setFilteringStatus(oldStatus); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) - ); - } + if (rules == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesUpdated, + color: Colors.green + ); } else { - appConfigProvider.addLog(rules['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, + color: Colors.red + ); } } @@ -143,15 +113,6 @@ class TopItems extends StatelessWidget { ]; } - void openOptionsModal(String domain, String type) { - showDialog( - context: context, - builder: (context) => OptionsModal( - options: generateOptions(domain), - ) - ); - } - Widget rowItem(Map item) { String? name; if (clients != null && clients == true) { diff --git a/lib/screens/logs/clients_modal.dart b/lib/screens/logs/clients_modal.dart index bd39541..fcd9d74 100644 --- a/lib/screens/logs/clients_modal.dart +++ b/lib/screens/logs/clients_modal.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; class ClientsModal extends StatefulWidget { @@ -32,6 +33,7 @@ class _ClientsModalState extends State { @override Widget build(BuildContext context) { final logsProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final height = MediaQuery.of(context).size.height; @@ -86,7 +88,7 @@ class _ClientsModalState extends State { void selectAll() { setState(() { - selectedClients = logsProvider.clients!.map((item) => item.ip).toList(); + selectedClients = clientsProvider.clients!.autoClients.map((item) => item.ip).toList(); }); } @@ -126,20 +128,20 @@ class _ClientsModalState extends State { ), Flexible( child: ListView.builder( - itemCount: logsProvider.clients!.length, + itemCount: clientsProvider.clients!.autoClients.length, itemBuilder: (context, index) => listItem( - label: logsProvider.clients![index].ip, + label: clientsProvider.clients!.autoClients[index].ip, onChanged: () { - if (selectedClients.contains(logsProvider.clients![index].ip)) { + if (selectedClients.contains(clientsProvider.clients!.autoClients[index].ip)) { setState(() { selectedClients = selectedClients.where( - (item) => item != logsProvider.clients![index].ip + (item) => item != clientsProvider.clients!.autoClients[index].ip ).toList(); }); } else { setState(() { - selectedClients.add(logsProvider.clients![index].ip); + selectedClients.add(clientsProvider.clients!.autoClients[index].ip); }); } } @@ -152,11 +154,11 @@ class _ClientsModalState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton( - onPressed: selectedClients.length == logsProvider.clients!.length + onPressed: selectedClients.length == clientsProvider.clients!.autoClients.length ? () => unselectAll() : () => selectAll(), child: Text( - selectedClients.length == logsProvider.clients!.length + selectedClients.length == clientsProvider.clients!.autoClients.length ? AppLocalizations.of(context)!.unselectAll : AppLocalizations.of(context)!.selectAll ) diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 1f6c100..32fbd73 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -10,12 +10,11 @@ import 'package:adguard_home_manager/screens/logs/log_list_tile.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/logs.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class LogDetailsScreen extends StatelessWidget { @@ -30,7 +29,6 @@ class LogDetailsScreen extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final statusProvider = Provider.of(context); @@ -55,56 +53,29 @@ class LogDetailsScreen extends StatelessWidget { ); } - void blockUnblock(Log log, String newStatus) async { + void blockUnblock(String domain, String newStatus) async { final ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingUserFilters); - final rules = await getFilteringRules(server: serversProvider.selectedServer!); + final rules = await statusProvider.blockUnblockDomain( + domain: domain, + newStatus: newStatus + ); - if (rules['result'] == 'success') { - FilteringStatus oldStatus = statusProvider.filteringStatus!; + processModal.close(); - List newRules = rules['data'].userRules.where((domain) => !domain.contains(log.question.name)).toList(); - if (newStatus == 'block') { - newRules.add("||${log.question.name}^"); - } - else if (newStatus == 'unblock') { - newRules.add("@@||${log.question.name}^"); - } - FilteringStatus newObj = statusProvider.filteringStatus!; - newObj.userRules = newRules; - statusProvider.setFilteringStatus(newObj); - - final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); - - processModal.close(); - - if (result['result'] == 'success') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesUpdated), - backgroundColor: Colors.green, - ) - ); - } - else { - appConfigProvider.addLog(result['log']); - statusProvider.setFilteringStatus(oldStatus); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) - ); - } + if (rules == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesUpdated, + color: Colors.green + ); } else { - appConfigProvider.addLog(rules['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, + color: Colors.red ); } } @@ -268,7 +239,12 @@ class LogDetailsScreen extends StatelessWidget { Row( children: [ IconButton( - onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), + onPressed: log.question.name != null + ? () => blockUnblock( + log.question.name!, + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' + ) + : null, icon: Icon( getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? Icons.check_circle_rounded @@ -301,7 +277,12 @@ class LogDetailsScreen extends StatelessWidget { title: Text(AppLocalizations.of(context)!.logDetails), actions: [ if (statusProvider.filteringStatus != null) IconButton( - onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), + onPressed: log.question.name != null + ? () => blockUnblock( + log.question.name!, + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' + ) + : null, icon: Icon( getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? Icons.check_circle_rounded diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index b70e7b7..a48024c 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -15,10 +15,11 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -31,125 +32,44 @@ class Logs extends StatefulWidget { class _LogsState extends State { late ScrollController scrollController; - - bool isLoadingMore = false; bool showDivider = true; Log? selectedLog; - Future fetchLogs({ - int? inOffset, - bool? loadingMore, - String? responseStatus, - String? searchText, - }) async { - final logsProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - final serversProvider = Provider.of(context, listen: false); - - int offst = inOffset ?? logsProvider.offset; - - String resStatus = responseStatus ?? logsProvider.selectedResultStatus; - String? search = searchText ?? logsProvider.searchText; - - if (loadingMore != null && loadingMore == true) { - setState(() => isLoadingMore = true); - } - - final result = await getLogs( - server: serversProvider.selectedServer!, - count: logsProvider.logsQuantity, - offset: offst, - olderThan: logsProvider.logsOlderThan, - responseStatus: resStatus, - search: search - ); - - if (loadingMore != null && loadingMore == true) { - setState(() => isLoadingMore = false); - } - - if (mounted) { - if (result['result'] == 'success') { - logsProvider.setOffset(inOffset != null ? inOffset+logsProvider.logsQuantity : logsProvider.offset+logsProvider.logsQuantity); - if (loadingMore != null && loadingMore == true && logsProvider.logsData != null) { - LogsData newLogsData = result['data']; - newLogsData.data = [...logsProvider.logsData!.data, ...result['data'].data]; - if (logsProvider.appliedFilters.clients != null) { - newLogsData.data = newLogsData.data.where( - (item) => logsProvider.appliedFilters.clients!.contains(item.client) - ).toList(); - } - logsProvider.setLogsData(newLogsData); - } - else { - LogsData newLogsData = result['data']; - if (logsProvider.appliedFilters.clients != null) { - newLogsData.data = newLogsData.data.where( - (item) => logsProvider.appliedFilters.clients!.contains(item.client) - ).toList(); - } - logsProvider.setLogsData(newLogsData); - } - logsProvider.setLoadStatus(1); - } - else { - logsProvider.setLoadStatus(2); - appConfigProvider.addLog(result['log']); - } - } - } - void fetchFilteringRules() async { final appConfigProvider = Provider.of(context, listen: false); - final serversProvider = Provider.of(context, listen: false); final statusProvider = Provider.of(context, listen: false); - final result = await getFilteringRules(server: serversProvider.selectedServer!); - if (mounted) { - if (result['result'] == 'success') { - statusProvider.setFilteringStatus(result['data']); - } - else { - appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.couldntGetFilteringStatus), - backgroundColor: Colors.red, - ) - ); - } + final result = await statusProvider.getFilteringRules(); + if (mounted && result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.couldntGetFilteringStatus, + color: Colors.red + ); } } Future fetchClients() async { - final logsProvider = Provider.of(context, listen: false); + final clientsProvider = Provider.of(context, listen: false); final appConfigProvider = Provider.of(context, listen: false); - final serversProvider = Provider.of(context, listen: false); - final result = await getClients(serversProvider.selectedServer!); - if (mounted) { - if (result['result'] == 'success') { - logsProvider.setClientsLoadStatus(1); - logsProvider.setClients(result['data'].autoClients); - } - else { - logsProvider.setClientsLoadStatus(2); - appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.couldntGetFilteringStatus), - backgroundColor: Colors.red, - ) - ); - } + final result = await clientsProvider.fetchClients(); + if (mounted && result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.couldntGetFilteringStatus, + color: Colors.red + ); } } void scrollListener() { - if (scrollController.position.extentAfter < 500 && isLoadingMore == false) { - fetchLogs(loadingMore: true); + final logsProvider = Provider.of(context, listen: false); + + if (scrollController.position.extentAfter < 500 && logsProvider.isLoadingMore == false) { + logsProvider.fetchLogs(loadingMore: true); } if (scrollController.position.pixels > 0) { setState(() => showDivider = false); @@ -161,8 +81,10 @@ class _LogsState extends State { @override void initState() { + final logsProvider = Provider.of(context, listen: false); + scrollController = ScrollController()..addListener(scrollListener); - fetchLogs(inOffset: 0); + logsProvider.fetchLogs(inOffset: 0); fetchFilteringRules(); fetchClients(); super.initState(); @@ -186,8 +108,8 @@ class _LogsState extends State { referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true - ? await updateQueryLogParameters(server: serversProvider.selectedServer!, data: data) - : await updateQueryLogParametersLegacy(server: serversProvider.selectedServer!, data: data); + ? await serversProvider.apiClient!.updateQueryLogParameters(data: data) + : await serversProvider.apiClient!.updateQueryLogParametersLegacy(data: data); processModal.close(); @@ -213,7 +135,7 @@ class _LogsState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingSettings); - final result = await clearLogs(server: serversProvider.selectedServer!); + final result = await serversProvider.apiClient!.clearLogs(); processModal.close(); @@ -225,8 +147,6 @@ class _LogsState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsNotCleared, @@ -271,7 +191,7 @@ class _LogsState extends State { Widget generateBody() { switch (logsProvider.loadStatus) { - case 0: + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -291,20 +211,20 @@ class _LogsState extends State { ), ); - case 1: + case LoadStatus.loaded: return RefreshIndicator( onRefresh: () async { - await fetchLogs(inOffset: 0); + await logsProvider.fetchLogs(inOffset: 0); }, child: logsProvider.logsData!.data.isNotEmpty ? ListView.builder( controller: scrollController, padding: const EdgeInsets.only(top: 0), - itemCount: isLoadingMore == true + itemCount: logsProvider.isLoadingMore == true ? logsProvider.logsData!.data.length+1 : logsProvider.logsData!.data.length, itemBuilder: (context, index) { - if (isLoadingMore == true && index == logsProvider.logsData!.data.length) { + if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { return const Padding( padding: EdgeInsets.symmetric(vertical: 20), child: Center( @@ -367,7 +287,7 @@ class _LogsState extends State { ) ); - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( @@ -403,11 +323,11 @@ class _LogsState extends State { centerTitle: false, actions: [ if (!(Platform.isAndroid || Platform.isIOS)) IconButton( - onPressed: () => fetchLogs(inOffset: 0), + onPressed: () => logsProvider.fetchLogs(inOffset: 0), icon: const Icon(Icons.refresh_rounded), tooltip: AppLocalizations.of(context)!.refresh, ), - logsProvider.loadStatus == 1 + logsProvider.loadStatus == LoadStatus.loaded ? IconButton( onPressed: openFilersModal, icon: const Icon(Icons.filter_list_rounded), @@ -492,7 +412,7 @@ class _LogsState extends State { ) ); logsProvider.setSearchText(null); - fetchLogs( + logsProvider.fetchLogs( inOffset: 0, searchText: '' ); @@ -525,7 +445,7 @@ class _LogsState extends State { ) ); logsProvider.setSelectedResultStatus('all'); - fetchLogs( + logsProvider.fetchLogs( inOffset: 0, responseStatus: 'all' ); @@ -560,7 +480,7 @@ class _LogsState extends State { ) ); logsProvider.setSelectedClients(null); - fetchLogs( + logsProvider.fetchLogs( inOffset: 0, responseStatus: logsProvider.appliedFilters.selectedResultStatus ); diff --git a/lib/screens/logs/logs_config_modal.dart b/lib/screens/logs/logs_config_modal.dart index 26ef299..2f16721 100644 --- a/lib/screens/logs/logs_config_modal.dart +++ b/lib/screens/logs/logs_config_modal.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -74,13 +73,15 @@ class _LogsConfigModalWidgetState extends State { int loadStatus = 0; void loadData() async { + final serversProvider = Provider.of(context, listen: false); + final result = serverVersionIsAhead( currentVersion: widget.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true - ? await getQueryLogInfo(server: widget.serversProvider.selectedServer!) - : await getQueryLogInfoLegacy(server: widget.serversProvider.selectedServer!); + ? await serversProvider.apiClient!.getQueryLogInfo() + : await serversProvider.apiClient!.getQueryLogInfoLegacy(); if (mounted) { if (result['result'] == 'success') { diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/logs_filters_modal.dart index 19ba0c0..6b040d3 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/logs_filters_modal.dart @@ -10,11 +10,8 @@ import 'package:adguard_home_manager/screens/logs/clients_modal.dart'; import 'package:adguard_home_manager/screens/logs/filter_status_modal.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/models/logs.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; class LogsFiltersModal extends StatelessWidget { @@ -62,8 +59,7 @@ class _LogsFiltersModalWidgetState extends State { @override Widget build(BuildContext context) { final logsProvider = Provider.of(context); - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -78,38 +74,6 @@ class _LogsFiltersModalWidgetState extends State { "safe_search": AppLocalizations.of(context)!.blockedSafeSearchRow, }; - void resetFilters() async { - setState(() { - searchController.text = ''; - }); - - logsProvider.setLoadStatus(0); - - logsProvider.resetFilters(); - - final result = await getLogs( - server: serversProvider.selectedServer!, - count: logsProvider.logsQuantity - ); - - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: null, - clients: null - ) - ); - - if (result['result'] == 'success') { - logsProvider.setLogsData(result['data']); - logsProvider.setLoadStatus(1); - } - else { - appConfigProvider.addLog(result['log']); - logsProvider.setLoadStatus(2); - } - } - void openSelectFilterStatus() { if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { showDialog( @@ -158,45 +122,6 @@ class _LogsFiltersModalWidgetState extends State { } } - void filterLogs() async { - Navigator.pop(context); - - logsProvider.setLoadStatus(0); - - logsProvider.setOffset(0); - - final result = await getLogs( - server: serversProvider.selectedServer!, - count: logsProvider.logsQuantity, - olderThan: logsProvider.logsOlderThan, - responseStatus: logsProvider.selectedResultStatus, - search: logsProvider.searchText, - ); - - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.selectedResultStatus, - searchText: logsProvider.searchText, - clients: logsProvider.selectedClients - ) - ); - - if (result['result'] == 'success') { - LogsData newLogsData = result['data']; - if (widget.logsProvider.appliedFilters.clients != null) { - newLogsData.data = newLogsData.data.where( - (item) => widget.logsProvider.appliedFilters.clients!.contains(item.client) - ).toList(); - } - logsProvider.setLogsData(newLogsData); - logsProvider.setLoadStatus(1); - } - else { - appConfigProvider.addLog(result['log']); - logsProvider.setLoadStatus(2); - } - } - Widget content() { return Column( mainAxisSize: MainAxisSize.min, @@ -273,13 +198,13 @@ class _LogsFiltersModalWidgetState extends State { subtitle: logsProvider.selectedClients != null ? "${logsProvider.selectedClients!.length} ${AppLocalizations.of(context)!.clientsSelected}" : AppLocalizations.of(context)!.all, - onTap: logsProvider.clientsLoadStatus == 1 + onTap: clientsProvider.loadStatus == LoadStatus.loaded ? openSelectClients : null, - disabled: logsProvider.clientsLoadStatus != 1 , + disabled: clientsProvider.loadStatus != LoadStatus.loaded, icon: Icons.smartphone_rounded, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - trailing: logsProvider.clientsLoadStatus == 0 + trailing: clientsProvider.loadStatus == LoadStatus.loading ? const SizedBox( width: 20, height: 20, @@ -287,7 +212,7 @@ class _LogsFiltersModalWidgetState extends State { strokeWidth: 2, ), ) - : logsProvider.clientsLoadStatus == 2 + : clientsProvider.loadStatus == LoadStatus.error ? const Icon( Icons.error_rounded, color: Colors.red, @@ -311,11 +236,17 @@ class _LogsFiltersModalWidgetState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton( - onPressed: resetFilters, + onPressed: () { + searchController.text = ""; + logsProvider.requestResetFilters(); + }, child: Text(AppLocalizations.of(context)!.resetFilters) ), TextButton( - onPressed: () => filterLogs(), + onPressed: () { + Navigator.pop(context); + logsProvider.filterLogs(); + }, child: Text(AppLocalizations.of(context)!.apply) ), ], diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index 6b3e046..46ea0f3 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -23,29 +23,9 @@ class _AccessSettingsState extends State with TickerProviderStat final ScrollController scrollController = ScrollController(); late TabController tabController; - Future fetchClients() async { - final clientsProvider = Provider.of(context, listen: false); - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - clientsProvider.setClientsLoadStatus(LoadStatus.loading, false); - final result = await getClients(serversProvider.selectedServer!); - if (mounted) { - if (result['result'] == 'success') { - clientsProvider.setClientsData(result['data']); - clientsProvider.setClientsLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result['log']); - clientsProvider.setClientsLoadStatus(LoadStatus.error, true); - } - } - } - - @override void initState() { - fetchClients(); + Provider.of(context, listen: false).fetchClients(updateLoading: true); super.initState(); tabController = TabController( initialIndex: 0, @@ -68,7 +48,6 @@ class _AccessSettingsState extends State with TickerProviderStat loadStatus: clientsProvider.loadStatus, data: clientsProvider.loadStatus == LoadStatus.loaded ? clientsProvider.clients!.clientsAllowedBlocked!.allowedClients : [], - fetchClients: fetchClients ), ClientsList( type: 'disallowed', @@ -76,7 +55,6 @@ class _AccessSettingsState extends State with TickerProviderStat loadStatus: clientsProvider.loadStatus, data: clientsProvider.loadStatus == LoadStatus.loaded ? clientsProvider.clients!.clientsAllowedBlocked!.disallowedClients : [], - fetchClients: fetchClients ), ClientsList( type: 'domains', @@ -84,7 +62,6 @@ class _AccessSettingsState extends State with TickerProviderStat loadStatus: clientsProvider.loadStatus, data: clientsProvider.loadStatus == LoadStatus.loaded ? clientsProvider.clients!.clientsAllowedBlocked!.blockedHosts : [], - fetchClients: fetchClients ), ] ); diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 8e9fb30..2466e11 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -13,11 +13,8 @@ import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; class ClientsList extends StatefulWidget { @@ -25,7 +22,6 @@ class ClientsList extends StatefulWidget { final ScrollController scrollController; final LoadStatus loadStatus; final List data; - final Future Function() fetchClients; const ClientsList({ Key? key, @@ -33,7 +29,6 @@ class ClientsList extends StatefulWidget { required this.scrollController, required this.loadStatus, required this.data, - required this.fetchClients }) : super(key: key); @override @@ -68,12 +63,22 @@ class _ClientsListState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final clientsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; + Future refetchClients() async { + final result = await clientsProvider.fetchClients(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientsNotLoaded, + color: Colors.red + ); + } + } + void confirmRemoveItem(String client, String type) async { Map> body = { "allowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.allowedClients ?? [], @@ -94,20 +99,18 @@ class _ClientsListState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); - final result = await requestAllowedBlockedClientsHosts(serversProvider.selectedServer!, body); + final result = await clientsProvider.removeClientList(client, type); processModal.close(); - if (result['result'] == 'success') { - clientsProvider.setAllowedDisallowedClientsBlockedDomains( - ClientsAllowedBlocked( - allowedClients: body['allowed_clients'] ?? [], - disallowedClients: body['disallowed_clients'] ?? [], - blockedHosts: body['blocked_hosts'] ?? [], - ) + if (result['success'] == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientRemovedSuccessfully, + color: Colors.green ); } - else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + else if (result['success'] == false && result['error'] == 'client_another_list') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, @@ -115,50 +118,32 @@ class _ClientsListState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.clientNotRemoved, + label: type == 'allowed' || type == 'blocked' + ? AppLocalizations.of(context)!.clientNotRemoved + : AppLocalizations.of(context)!.domainNotAdded, color: Colors.red ); } } void confirmAddItem(String item, String type) async { - Map> body = { - "allowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.allowedClients ?? [], - "disallowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.disallowedClients ?? [], - "blocked_hosts": clientsProvider.clients!.clientsAllowedBlocked?.blockedHosts ?? [], - }; - - if (type == 'allowed') { - body['allowed_clients']!.add(item); - } - else if (type == 'disallowed') { - body['disallowed_clients']!.add(item); - } - else if (type == 'domains') { - body['blocked_hosts']!.add(item); - } - ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); - final result = await requestAllowedBlockedClientsHosts(serversProvider.selectedServer!, body); + final result = await clientsProvider.addClientList(item, type); processModal.close(); - if (result['result'] == 'success') { - clientsProvider.setAllowedDisallowedClientsBlockedDomains( - ClientsAllowedBlocked( - allowedClients: body['allowed_clients'] ?? [], - disallowedClients: body['disallowed_clients'] ?? [], - blockedHosts: body['blocked_hosts'] ?? [], - ) + if (result['success'] == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientAddedSuccessfully, + color: Colors.green ); } - else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + else if (result['success'] == false && result['error'] == 'client_another_list') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, @@ -166,8 +151,6 @@ class _ClientsListState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: type == 'allowed' || type == 'blocked' @@ -327,7 +310,7 @@ class _ClientsListState extends State { ), const SizedBox(height: 30), TextButton.icon( - onPressed: widget.fetchClients, + onPressed: refetchClients, icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh), ) @@ -361,7 +344,7 @@ class _ClientsListState extends State { ), ), loadStatus: widget.loadStatus, - onRefresh: widget.fetchClients, + onRefresh: refetchClients, refreshIndicatorOffset: 0, fab: FloatingActionButton( onPressed: () { diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 2ed0ee4..402b69a 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -71,29 +71,29 @@ class AdvancedSettings extends StatelessWidget { right: 10 ) ), - CustomListTile( - icon: Icons.list_rounded, - title: AppLocalizations.of(context)!.logs, - subtitle: AppLocalizations.of(context)!.checkAppLogs, - onTap: () => { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push(const AppLogs()) - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const AppLogs() - ) - ) - } - }, - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 20, - right: 10 - ) - ), + // CustomListTile( + // icon: Icons.list_rounded, + // title: AppLocalizations.of(context)!.logs, + // subtitle: AppLocalizations.of(context)!.checkAppLogs, + // onTap: () => { + // if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + // SplitView.of(context).push(const AppLogs()) + // } + // else { + // Navigator.of(context).push( + // MaterialPageRoute( + // builder: (context) => const AppLogs() + // ) + // ) + // } + // }, + // padding: const EdgeInsets.only( + // top: 10, + // bottom: 10, + // left: 20, + // right: 10 + // ) + // ), ], ) ); diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 1e9d796..49ab29c 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -16,7 +16,6 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -54,34 +53,22 @@ class _DhcpScreenState extends State { bool dataValid = false; void loadDhcpStatus() async { - final serversProvider = Provider.of(context, listen: false); - final dhcpProvider = Provider.of(context, listen: false); - - dhcpProvider.setDhcpLoadStatus(LoadStatus.loading, false); - - final result = await getDhcpData(server: serversProvider.selectedServer!); - - if (mounted) { - if (result['result'] == 'success') { - dhcpProvider.setDhcpData(result['data']); - dhcpProvider.setDhcpLoadStatus(LoadStatus.loaded, true); + final result = await Provider.of(context, listen: false).loadDhcpStatus(); + if (mounted && result == true) { + final dhcpProvider = Provider.of(context, listen: false); + if (dhcpProvider.dhcp != null) { setState(() { - if (result['data'].dhcpStatus.interfaceName != '') { - selectedInterface = result['data'].networkInterfaces.firstWhere((iface) => iface.name == result['data'].dhcpStatus.interfaceName); - - enabled = result['data'].dhcpStatus.enabled; - ipv4StartRangeController.text = result['data'].dhcpStatus.v4.rangeStart; - ipv4StartRangeController.text = result['data'].dhcpStatus.v4.rangeStart; - ipv4EndRangeController.text = result['data'].dhcpStatus.v4.rangeEnd; - ipv4SubnetMaskController.text = result['data'].dhcpStatus.v4.subnetMask; - ipv4GatewayController.text = result['data'].dhcpStatus.v4.gatewayIp; - ipv4LeaseTimeController.text = result['data'].dhcpStatus.v4.leaseDuration.toString(); + if (dhcpProvider.dhcp!.dhcpStatus.interfaceName != '') { + selectedInterface = dhcpProvider.dhcp!.networkInterfaces.firstWhere((iface) => iface.name == dhcpProvider.dhcp!.dhcpStatus.interfaceName); + enabled = dhcpProvider.dhcp!.dhcpStatus.enabled; + ipv4StartRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.rangeStart; + ipv4EndRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.rangeEnd ?? ''; + ipv4SubnetMaskController.text = dhcpProvider.dhcp!.dhcpStatus.v4.subnetMask ?? ''; + ipv4GatewayController.text = dhcpProvider.dhcp!.dhcpStatus.v4.gatewayIp ?? ''; + ipv4LeaseTimeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.leaseDuration.toString(); } }); } - else { - dhcpProvider.setDhcpLoadStatus(LoadStatus.error, true); - } } checkDataValid(); } @@ -205,22 +192,24 @@ class _DhcpScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingSettings); - final result = await saveDhcpConfig(server: serversProvider.selectedServer!, data: { - "enabled": enabled, - "interface_name": selectedInterface!.name, - if (selectedInterface!.ipv4Addresses.isNotEmpty) "v4": { - "gateway_ip": ipv4GatewayController.text, - "subnet_mask": ipv4SubnetMaskController.text, - "range_start": ipv4StartRangeController.text, - "range_end": ipv4EndRangeController.text, - "lease_duration": ipv4LeaseTimeController.text != '' ? int.parse(ipv4LeaseTimeController.text) : null - }, - if (selectedInterface!.ipv6Addresses.isNotEmpty) "v6": { - "range_start": ipv6StartRangeController.text, - "range_end": ipv6EndRangeController.text, - "lease_duration": ipv6LeaseTimeController.text != '' ? int.parse(ipv6LeaseTimeController.text) : null + final result = await serversProvider.apiClient!.saveDhcpConfig( + data: { + "enabled": enabled, + "interface_name": selectedInterface!.name, + if (selectedInterface!.ipv4Addresses.isNotEmpty) "v4": { + "gateway_ip": ipv4GatewayController.text, + "subnet_mask": ipv4SubnetMaskController.text, + "range_start": ipv4StartRangeController.text, + "range_end": ipv4EndRangeController.text, + "lease_duration": ipv4LeaseTimeController.text != '' ? int.parse(ipv4LeaseTimeController.text) : null + }, + if (selectedInterface!.ipv6Addresses.isNotEmpty) "v6": { + "range_start": ipv6StartRangeController.text, + "range_end": ipv6EndRangeController.text, + "lease_duration": ipv6LeaseTimeController.text != '' ? int.parse(ipv6LeaseTimeController.text) : null + } } - }); + ); processModal.close(); @@ -232,8 +221,6 @@ class _DhcpScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsNotSaved, @@ -247,7 +234,7 @@ class _DhcpScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.restoringConfig); - final result = await resetDhcpConfig(server: serversProvider.selectedServer!); + final result = await serversProvider.apiClient!.resetDhcpConfig(); processModal.close(); @@ -261,8 +248,6 @@ class _DhcpScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.configNotRestored, @@ -277,7 +262,7 @@ class _DhcpScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.restoringLeases); - final result = await restoreAllLeases(server: serversProvider.selectedServer!); + final result = await serversProvider.apiClient!.restoreAllLeases(); processModal.close(); @@ -294,8 +279,6 @@ class _DhcpScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.leasesNotRestored, diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index ede2ef1..3763704 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -13,10 +13,8 @@ import 'package:adguard_home_manager/screens/settings/dhcp/add_static_lease_moda import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class DhcpLeases extends StatelessWidget { final List items; @@ -30,7 +28,6 @@ class DhcpLeases extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final dhcpProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -40,19 +37,11 @@ class DhcpLeases extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deleting); - final result = await deleteStaticLease(server: serversProvider.selectedServer!, data: { - "mac": lease.mac, - "ip": lease.ip, - "hostname": lease.hostname - }); + final result = await dhcpProvider.deleteLease(lease); processModal.close(); - if (result['result'] == 'success') { - DhcpModel data = dhcpProvider.dhcp!; - data.dhcpStatus.staticLeases = data.dhcpStatus.staticLeases.where((l) => l.mac != lease.mac).toList(); - dhcpProvider.setDhcpData(data); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseDeleted, @@ -60,7 +49,6 @@ class DhcpLeases extends StatelessWidget { ); } else { - appConfigProvider.addLog(result['log']); showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseNotDeleted, @@ -73,35 +61,25 @@ class DhcpLeases extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.creating); - final result = await createStaticLease(server: serversProvider.selectedServer!, data: { - "mac": lease.mac, - "ip": lease.ip, - "hostname": lease.hostname, - }); + final result = await dhcpProvider.createLease(lease); processModal.close(); - if (result['result'] == 'success') { - DhcpModel data = dhcpProvider.dhcp!; - data.dhcpStatus.staticLeases.add(lease); - dhcpProvider.setDhcpData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseCreated, color: Colors.green ); } - else if (result['result'] == 'error' && result['message'] == 'already_exists' ) { - appConfigProvider.addLog(result['log']); + else if (result['success'] == false && result['error'] == 'already_exists' ) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseExists, color: Colors.red ); } - else if (result['result'] == 'error' && result['message'] == 'server_not_configured' ) { - appConfigProvider.addLog(result['log']); + else if (result['success'] == false && result['error'] == 'server_not_configured' ) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverNotConfigured, @@ -109,7 +87,6 @@ class DhcpLeases extends StatelessWidget { ); } else { - appConfigProvider.addLog(result['log']); showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseNotCreated, diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index 389ceae..055042d 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -4,13 +4,10 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class BootstrapDnsScreen extends StatefulWidget { const BootstrapDnsScreen({Key? key}) : super(key: key); @@ -66,7 +63,6 @@ class _BootstrapDnsScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -74,26 +70,20 @@ class _BootstrapDnsScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + final result = await dnsProvider.saveBootstrapDnsConfig({ "bootstrap_dns": bootstrapControllers.map((e) => e['controller'].text).toList(), }); processModal.close(); - if (result['result'] == 'success') { - DnsInfo data = dnsProvider.dnsInfo!; - data.bootstrapDns = List.from(bootstrapControllers.map((e) => e['controller'].text)); - dnsProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -101,8 +91,6 @@ class _BootstrapDnsScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index 313919f..bbd78c3 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -75,7 +75,7 @@ class _CacheConfigDnsScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + final result = await dnsProvider.saveCacheCacheConfig({ "cache_size": int.parse(cacheSizeController.text), "cache_ttl_min": int.parse(overrideMinTtlController.text), "cache_ttl_max": int.parse(overrideMaxTtlController.text), @@ -84,23 +84,14 @@ class _CacheConfigDnsScreenState extends State { processModal.close(); - if (result['result'] == 'success') { - DnsInfo data = dnsProvider.dnsInfo!; - data.cacheSize = int.parse(cacheSizeController.text); - data.cacheTtlMin = int.parse(overrideMinTtlController.text); - data.cacheTtlMax = int.parse(overrideMaxTtlController.text); - data.cacheOptimistic = optimisticCache; - dnsProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -108,8 +99,6 @@ class _CacheConfigDnsScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index bd1feee..eac3c2c 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -21,7 +21,6 @@ import 'package:adguard_home_manager/functions/clear_dns_cache.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class DnsSettings extends StatefulWidget { const DnsSettings({Key? key}) : super(key: key); @@ -31,31 +30,9 @@ class DnsSettings extends StatefulWidget { } class _DnsSettingsState extends State { - - void fetchData({bool? showRefreshIndicator}) async { - final dnsProvider = Provider.of(context, listen: false); - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - dnsProvider.setDnsInfoLoadStatus(LoadStatus.loading, showRefreshIndicator ?? false); - - final result = await getDnsInfo(server: serversProvider.selectedServer!); - - if (mounted) { - if (result['result'] == 'success') { - dnsProvider.setDnsInfoData(result['data']); - dnsProvider.setDnsInfoLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result['log']); - dnsProvider.setDnsInfoLoadStatus(LoadStatus.error, true); - } - } - } - @override void initState() { - fetchData(); + Provider.of(context, listen: false).fetchDnsData(showLoading: true); super.initState(); } @@ -192,7 +169,7 @@ class _DnsSettingsState extends State { PopupMenuButton( itemBuilder: (context) => [ PopupMenuItem( - onTap: () => fetchData(showRefreshIndicator: true), + onTap: () => dnsProvider.fetchDnsData(), child: Row( children: [ const Icon(Icons.refresh_rounded), diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index cc1db2a..fffd43a 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -100,7 +100,6 @@ class _DnsServerSettingsScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -108,36 +107,26 @@ class _DnsServerSettingsScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + final result = await dnsProvider.saveDnsServerConfig({ "ratelimit": int.parse(limitRequestsController.text), "edns_cs_enabled": enableEdns, "dnssec_enabled": enableDnssec, "disable_ipv6": disableIpv6Resolving, - "blocking_mode": blockingMode + "blocking_mode": blockingMode, + "blocking_ipv4": ipv4controller.text, + "blocking_ipv6": ipv6controller.text }); processModal.close(); - if (result['result'] == 'success') { - DnsInfo data = dnsProvider.dnsInfo!; - data.ratelimit = int.parse(limitRequestsController.text); - data.ednsCsEnabled = enableEdns; - data.dnssecEnabled = enableDnssec; - data.disableIpv6 = disableIpv6Resolving; - data.blockingMode = blockingMode; - data.blockingIpv4 = ipv4controller.text; - data.blockingIpv6 = ipv6controller.text; - dnsProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -145,8 +134,6 @@ class _DnsServerSettingsScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index 5bab4c0..bf6f63b 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -6,13 +6,10 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class PrivateReverseDnsServersScreen extends StatefulWidget { const PrivateReverseDnsServersScreen({Key? key}) : super(key: key); @@ -89,7 +86,6 @@ class _PrivateReverseDnsServersScreenState extends State(context); final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -97,36 +93,28 @@ class _PrivateReverseDnsServersScreenState extends State.from(reverseResolversControllers.map((e) => e['controller'].text)), - "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, - "resolve_clients": enableReverseResolve - } : { - "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, - "resolve_clients": enableReverseResolve - }); + final result = await dnsProvider.savePrivateReverseServersConfig( + editReverseResolvers == true + ? { + "local_ptr_upstreams": List.from(reverseResolversControllers.map((e) => e['controller'].text)), + "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, + "resolve_clients": enableReverseResolve + } : { + "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, + "resolve_clients": enableReverseResolve + } + ); processModal.close(); - if (result['result'] == 'success') { - DnsInfo data = dnsProvider.dnsInfo!; - if (editReverseResolvers == true) { - data.localPtrUpstreams = List.from(reverseResolversControllers.map((e) => e['controller'].text)); - } - data.usePrivatePtrResolvers = usePrivateReverseDnsResolvers; - data.resolveClients = enableReverseResolve; - dnsProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -134,8 +122,6 @@ class _PrivateReverseDnsServersScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + final result = await dnsProvider.saveUpstreamDnsConfig({ "upstream_dns": dnsServers.map((e) => e['controller'] != null ? e['controller'].text : e['comment']).toList(), "upstream_mode": upstreamMode }); processModal.close(); - if (result['result'] == 'success') { - DnsInfo data = dnsProvider.dnsInfo!; - data.upstreamDns = List.from(dnsServers.map((e) => e['controller'] != null ? e['controller'].text : e['comment'])); - data.upstreamMode = upstreamMode; - dnsProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -174,8 +165,6 @@ class _UpstreamDnsScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 923580d..d2ec726 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -9,13 +9,11 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart'; import 'package:adguard_home_manager/screens/settings/dns_rewrites/delete_dns_rewrite.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/rewrite_rules_provider.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; class DnsRewritesScreen extends StatefulWidget { @@ -26,34 +24,14 @@ class DnsRewritesScreen extends StatefulWidget { } class _DnsRewritesScreenState extends State { - Future fetchData() async { - final rewriteRulesProvider = Provider.of(context, listen: false); - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - rewriteRulesProvider.setRewriteRulesLoadStatus(LoadStatus.loading, false); - - final result = await getDnsRewriteRules(server: serversProvider.selectedServer!); - - if (result['result'] == 'success') { - rewriteRulesProvider.setRewriteRulesData(result['data']); - rewriteRulesProvider.setRewriteRulesLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result['log']); - rewriteRulesProvider.setRewriteRulesLoadStatus(LoadStatus.error, true); - } - } - @override void initState() { - fetchData(); + Provider.of(context, listen: false).fetchRules(); super.initState(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final rewriteRulesProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -63,18 +41,11 @@ class _DnsRewritesScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deleting); - final result = await deleteDnsRewriteRule(server: serversProvider.selectedServer!, data: { - "domain": rule.domain, - "answer": rule.answer - }); + final result = await rewriteRulesProvider.deleteDnsRewrite(rule); processModal.close(); - if (result['result'] == 'success') { - List data = rewriteRulesProvider.rewriteRules!; - data = data.where((item) => item.domain != rule.domain).toList(); - rewriteRulesProvider.setRewriteRulesData(data); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleDeleted, @@ -82,7 +53,6 @@ class _DnsRewritesScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleNotDeleted, @@ -95,18 +65,11 @@ class _DnsRewritesScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingRewrite); - final result = await addDnsRewriteRule(server: serversProvider.selectedServer!, data: { - "domain": rule.domain, - "answer": rule.answer - }); + final result = await rewriteRulesProvider.addDnsRewrite(rule); processModal.close(); - if (result['result'] == 'success') { - List data = rewriteRulesProvider.rewriteRules!; - data.add(rule); - rewriteRulesProvider.setRewriteRulesData(data); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleAdded, @@ -114,7 +77,6 @@ class _DnsRewritesScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleNotAdded, @@ -149,7 +111,14 @@ class _DnsRewritesScreenState extends State { if (rewriteRulesProvider.rewriteRules!.isNotEmpty) { return RefreshIndicator( onRefresh: () async { - await fetchData(); + final result = await rewriteRulesProvider.fetchRules(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.rewriteRulesNotLoaded, + color: Colors.red + ); + } }, child: ListView.builder( padding: const EdgeInsets.only(top: 0), diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index b99efd7..1282279 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -16,7 +16,6 @@ import 'package:adguard_home_manager/screens/settings/encryption/error_message.d import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/base64.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -98,7 +97,7 @@ class _EncryptionSettingsWidgetState extends State { void fetchData({bool? showRefreshIndicator}) async { setState(() => loadStatus = 0); - final result = await getEncryptionSettings(server: widget.serversProvider.selectedServer!); + final result = await Provider.of(context, listen: false).apiClient!.getEncryptionSettings(); if (mounted) { if (result['result'] == 'success') { @@ -141,19 +140,21 @@ class _EncryptionSettingsWidgetState extends State { Future checkValidDataApi({Map? data}) async { setState(() => certKeyValidApi = 0); - final result = await checkEncryptionSettings(server: widget.serversProvider.selectedServer!, data: data ?? { - "enabled": enabled, - "server_name": domainNameController.text, - "force_https": redirectHttps, - "port_https": httpsPortController.text != '' ? int.parse(httpsPortController.text) : null, - "port_dns_over_tls": tlsPortController.text != '' ? int.parse(tlsPortController.text) : null, - "port_dns_over_quic": dnsOverQuicPortController.text != '' ? int.parse(dnsOverQuicPortController.text) : null, - if (certificateOption == 1) "certificate_chain": encodeBase64(certificateContentController.text), - if (privateKeyOption == 1 && usePreviouslySavedKey == false) "private_key": encodeBase64(pastePrivateKeyController.text), - "private_key_saved": usePreviouslySavedKey, - if (certificateOption == 0) "certificate_path": certificatePathController.text, - if (privateKeyOption == 0) "private_key_path": privateKeyPathController.text, - }); + final result = await Provider.of(context, listen: false).apiClient!.checkEncryptionSettings( + data: data ?? { + "enabled": enabled, + "server_name": domainNameController.text, + "force_https": redirectHttps, + "port_https": httpsPortController.text != '' ? int.parse(httpsPortController.text) : null, + "port_dns_over_tls": tlsPortController.text != '' ? int.parse(tlsPortController.text) : null, + "port_dns_over_quic": dnsOverQuicPortController.text != '' ? int.parse(dnsOverQuicPortController.text) : null, + if (certificateOption == 1) "certificate_chain": encodeBase64(certificateContentController.text), + if (privateKeyOption == 1 && usePreviouslySavedKey == false) "private_key": encodeBase64(pastePrivateKeyController.text), + "private_key_saved": usePreviouslySavedKey, + if (certificateOption == 0) "certificate_path": certificatePathController.text, + if (privateKeyOption == 0) "private_key_path": privateKeyPathController.text, + } + ); if (mounted) { if (result['result'] == 'success') { @@ -224,19 +225,21 @@ class _EncryptionSettingsWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await saveEncryptionSettings(server: serversProvider.selectedServer!, data: { - "enabled": enabled, - "server_name": domainNameController.text, - "force_https": redirectHttps, - "port_https": int.tryParse(httpsPortController.text), - "port_dns_over_tls": int.tryParse(tlsPortController.text), - "port_dns_over_quic": int.tryParse(dnsOverQuicPortController.text), - "certificate_chain": encodeBase64(certificateContentController.text), - "private_key": encodeBase64(pastePrivateKeyController.text), - "private_key_saved": usePreviouslySavedKey, - "certificate_path": certificatePathController.text, - "private_key_path": privateKeyPathController.text, - }); + final result = await serversProvider.apiClient!.saveEncryptionSettings( + data: { + "enabled": enabled, + "server_name": domainNameController.text, + "force_https": redirectHttps, + "port_https": int.tryParse(httpsPortController.text), + "port_dns_over_tls": int.tryParse(tlsPortController.text), + "port_dns_over_quic": int.tryParse(dnsOverQuicPortController.text), + "certificate_chain": encodeBase64(certificateContentController.text), + "private_key": encodeBase64(pastePrivateKeyController.text), + "private_key_saved": usePreviouslySavedKey, + "certificate_path": certificatePathController.text, + "private_key_path": privateKeyPathController.text, + } + ); processModal.close(); diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 986e7b7..461b6a6 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -10,45 +10,16 @@ import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/server_status.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -class SafeSearchSettingsScreen extends StatelessWidget { +class SafeSearchSettingsScreen extends StatefulWidget { const SafeSearchSettingsScreen({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final statusProviuder = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return SafeSearchSettingsScreenWidget( - serversProvider: serversProvider, - statusProvider: statusProviuder, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _SafeSearchSettingsScreenState(); } -class SafeSearchSettingsScreenWidget extends StatefulWidget { - final ServersProvider serversProvider; - final StatusProvider statusProvider; - final AppConfigProvider appConfigProvider; - - const SafeSearchSettingsScreenWidget({ - Key? key, - required this.serversProvider, - required this.statusProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _SafeSearchSettingsScreenWidgetState(); -} - -class _SafeSearchSettingsScreenWidgetState extends State { +class _SafeSearchSettingsScreenState extends State { bool generalEnabled = false; bool bingEnabled = false; bool duckduckgoEnabled = false; @@ -56,54 +27,46 @@ class _SafeSearchSettingsScreenWidgetState extends State(context, listen: false).getServerStatus(); + if (mounted && result == true) { + final statusProvider = Provider.of(context, listen: false); + if (statusProvider.serverStatus != null) { + setState(() { + generalEnabled = statusProvider.serverStatus!.safeSearchEnabled; + bingEnabled = statusProvider.serverStatus!.safeSeachBing ?? false; + duckduckgoEnabled = statusProvider.serverStatus!.safeSearchDuckduckgo ?? false; + googleEnabled = statusProvider.serverStatus!.safeSearchGoogle ?? false; + pixabayEnabled = statusProvider.serverStatus!.safeSearchPixabay ?? false; + yandexEnabled = statusProvider.serverStatus!.safeSearchYandex ?? false; + youtubeEnabled = statusProvider.serverStatus!.safeSearchYoutube ?? false; + }); } } } @override void initState() { - if (widget.statusProvider.loadStatus == LoadStatus.loading) { + final statusProvider = Provider.of(context, listen: false); + + if (statusProvider.loadStatus == LoadStatus.loading) { requestSafeSearchSettings(); } - else if (widget.statusProvider.loadStatus == LoadStatus.loaded) { - generalEnabled = widget.statusProvider.serverStatus!.safeSearchEnabled; - bingEnabled = widget.statusProvider.serverStatus!.safeSeachBing!; - duckduckgoEnabled = widget.statusProvider.serverStatus!.safeSearchDuckduckgo!; - googleEnabled = widget.statusProvider.serverStatus!.safeSearchGoogle!; - pixabayEnabled = widget.statusProvider.serverStatus!.safeSearchPixabay!; - yandexEnabled = widget.statusProvider.serverStatus!.safeSearchYandex!; - youtubeEnabled = widget.statusProvider.serverStatus!.safeSearchYoutube!; + else if (statusProvider.loadStatus == LoadStatus.loaded) { + generalEnabled = statusProvider.serverStatus!.safeSearchEnabled; + bingEnabled = statusProvider.serverStatus!.safeSeachBing!; + duckduckgoEnabled = statusProvider.serverStatus!.safeSearchDuckduckgo!; + googleEnabled = statusProvider.serverStatus!.safeSearchGoogle!; + pixabayEnabled = statusProvider.serverStatus!.safeSearchPixabay!; + yandexEnabled = statusProvider.serverStatus!.safeSearchYandex!; + youtubeEnabled = statusProvider.serverStatus!.safeSearchYoutube!; } super.initState(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -111,35 +74,19 @@ class _SafeSearchSettingsScreenWidgetState extends State { - ServerInfo serverInfo = ServerInfo(loadStatus: 0); + ServerInfo serverInfo = ServerInfo(loadStatus: LoadStatus.loading); void fetchServerInfo() async { - final result = await getServerInfo(server: widget.serversProvider.selectedServer!); + final result = await Provider.of(context, listen: false).apiClient!.getServerInfo(); if (mounted) { if (result['result'] == 'success') { setState(() { - serverInfo.loadStatus = 1; + serverInfo.loadStatus = LoadStatus.loaded; serverInfo.data = result['data']; }); } else { - widget.appConfigProvider.addLog(result['log']); - setState(() => serverInfo.loadStatus = 2); + setState(() => serverInfo.loadStatus = LoadStatus.loaded); } } } @@ -69,7 +68,7 @@ class _ServerInformationWidgetState extends State { Widget build(BuildContext context) { Widget generateBody() { switch (serverInfo.loadStatus) { - case 0: + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -93,7 +92,7 @@ class _ServerInformationWidgetState extends State { ), ); - case 1: + case LoadStatus.loaded: return ListView( children: [ CustomListTile( @@ -145,7 +144,7 @@ class _ServerInformationWidgetState extends State { ] ); - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 08b9d8c..b0763f6 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -131,7 +131,11 @@ class SettingsWidget extends StatelessWidget { ], body: ListView( children: [ - if (serversProvider.selectedServer != null && statusProvider.serverStatus != null) ...[ + if ( + serversProvider.selectedServer != null && + statusProvider.serverStatus != null && + serversProvider.apiClient != null + ) ...[ SectionLabel(label: AppLocalizations.of(context)!.serverSettings), if (serverVersionIsAhead( currentVersion: statusProvider.serverStatus!.serverVersion, diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index 5e88a2e..f84e01a 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -10,7 +10,6 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; @@ -36,7 +35,7 @@ class UpdateScreen extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.requestingUpdate); - final result = await requestUpdateServer(server: serversProvider.selectedServer!); + final result = await serversProvider.apiClient!.requestUpdateServer(); processModal.close(); @@ -56,7 +55,6 @@ class UpdateScreen extends StatelessWidget { color: Colors.red, labelColor: Colors.white, ); - appConfigProvider.addLog(result['log']); } } @@ -92,8 +90,8 @@ class UpdateScreen extends StatelessWidget { child: Column( children: [ serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? Column( - children: const [ + ? const Column( + children: [ CircularProgressIndicator(), SizedBox(height: 4) ], diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index db3584a..8db5464 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -132,14 +132,8 @@ class _TopItemsScreenState extends State { ), body: RefreshIndicator( onRefresh: () async { - final result = await getServerStatus(serversProvider.selectedServer!); - if (result['result'] == 'success') { - statusProvider.setServerStatusData( - data: result['data'] - ); - } - else { - appConfigProvider.addLog(result['log']); + final result = await statusProvider.getServerStatus(); + if (result == false) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverStatusNotRefreshed, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index b9cda5c..2cf9820 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -23,7 +23,7 @@ import 'package:adguard_home_manager/constants/urls.dart'; Future> apiRequest({ - required Server server, + required Server server, required String method, required String urlPath, dynamic body, @@ -262,81 +262,101 @@ Future loginHA(Server server) async { } } -Future getServerVersion(Server server) async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/status', - type: 'get_server_version' - ); +class ApiClient { + final Server server; - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200 && result['body'] != null) { - return { - 'result': 'success', - 'data': jsonDecode(result['body'])['version'] - }; + ApiClient({ + required this.server + }); + + Future getServerVersion() async { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/status', + type: 'get_server_version' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200 && result['body'] != null) { + return { + 'result': 'success', + 'data': jsonDecode(result['body'])['version'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_version', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_server_version', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } } - else { - return result; - } -} -Future getServerStatus(Server server) async { - final result = await Future.wait([ - apiRequest(server: server, method: 'get', urlPath: '/stats', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/filtering/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/safesearch/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/safebrowsing/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/parental/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'server_status'), - ]); + Future getServerStatus() async { + final result = await Future.wait([ + apiRequest(server: server, method: 'get', urlPath: '/stats', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/filtering/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/safesearch/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/safebrowsing/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/parental/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'server_status'), + ]); - if ( - result[0]['hasResponse'] == true && - result[1]['hasResponse'] == true && - result[2]['hasResponse'] == true && - result[3]['hasResponse'] == true && - result[4]['hasResponse'] == true && - result[5]['hasResponse'] == true && - result[6]['hasResponse'] == true - ) { if ( - result[0]['statusCode'] == 200 && - result[1]['statusCode'] == 200 && - result[2]['statusCode'] == 200 && - result[3]['statusCode'] == 200 && - result[4]['statusCode'] == 200 && - result[5]['statusCode'] == 200 && - result[6]['statusCode'] == 200 + result[0]['hasResponse'] == true && + result[1]['hasResponse'] == true && + result[2]['hasResponse'] == true && + result[3]['hasResponse'] == true && + result[4]['hasResponse'] == true && + result[5]['hasResponse'] == true && + result[6]['hasResponse'] == true ) { - final Map mappedData = { - 'stats': jsonDecode(result[0]['body']), - 'clients': jsonDecode(result[6]['body'])['clients'], - 'status': jsonDecode(result[1]['body']), - 'filtering': jsonDecode(result[2]['body']), - 'safeSearch': jsonDecode(result[3]['body']), - 'safeBrowsingEnabled': jsonDecode(result[4]['body']), - 'parentalControlEnabled': jsonDecode(result[5]['body']), - }; - return { - 'result': 'success', - 'data': ServerStatus.fromJson(mappedData) - }; + if ( + result[0]['statusCode'] == 200 && + result[1]['statusCode'] == 200 && + result[2]['statusCode'] == 200 && + result[3]['statusCode'] == 200 && + result[4]['statusCode'] == 200 && + result[5]['statusCode'] == 200 && + result[6]['statusCode'] == 200 + ) { + final Map mappedData = { + 'stats': jsonDecode(result[0]['body']), + 'clients': jsonDecode(result[6]['body'])['clients'], + 'status': jsonDecode(result[1]['body']), + 'filtering': jsonDecode(result[2]['body']), + 'safeSearch': jsonDecode(result[3]['body']), + 'safeBrowsingEnabled': jsonDecode(result[4]['body']), + 'parentalControlEnabled': jsonDecode(result[5]['body']), + }; + return { + 'result': 'success', + 'data': ServerStatus.fromJson(mappedData) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode']).toString(), + resBody: result.map((res) => res['body']).toString() + ) + }; + } } else { return { @@ -344,259 +364,257 @@ Future getServerStatus(Server server) async { 'log': AppLog( type: 'get_server_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result.map((res) => res['statusCode']).toString(), - resBody: result.map((res) => res['body']).toString() + message: 'no_response', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString() ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_server_status', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString() - ) - }; - } -} -Future updateFiltering({ - required Server server, - required bool enable, -}) async { - final result = await apiRequest( - urlPath: '/filtering/config', - method: 'post', - server: server, - body: { - 'enabled': enable - }, - type: 'update_filtering' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_filtering', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateSafeSearchLegacy(Server server, bool enable) async { - final result = enable == true - ? await apiRequest( - urlPath: '/safesearch/enable', - method: 'post', - server: server, - type: 'enable_safe_search' - ) - : await apiRequest( - urlPath: '/safesearch/disable', - method: 'post', - server: server, - type: 'disable_safe_search' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'safe_search', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateSafeBrowsing(Server server, bool enable) async { - final result = enable == true - ? await apiRequest( - urlPath: '/safebrowsing/enable', - method: 'post', - server: server, - type: 'enable_safe_browsing' - ) - : await apiRequest( - urlPath: '/safebrowsing/disable', - method: 'post', - server: server, - type: 'disable_safe_browsing' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'safe_browsing', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateParentalControl(Server server, bool enable) async { - final result = enable == true - ? await apiRequest( - urlPath: '/parental/enable', - method: 'post', - server: server, - type: 'enable_parental_control' - ) - : await apiRequest( - urlPath: '/parental/disable', - method: 'post', - server: server, - type: 'disable_parental_control' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'parental_control', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateGeneralProtection({ - required Server server, - required bool enable, - int? time -}) async { + Future updateFiltering({ + required bool enable, + }) async { final result = await apiRequest( - urlPath: '/protection', - method: 'post', - server: server, - body: { - 'enabled': enable, - 'duration': time - }, - type: 'general_protection' - ); + urlPath: '/filtering/config', + method: 'post', + server: server, + body: { + 'enabled': enable + }, + type: 'update_filtering' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_filtering', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'general_protection', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } } - else { - return result; - } -} -Future updateGeneralProtectionLegacy(Server server, bool enable) async { - final result = await apiRequest( - urlPath: '/dns_config', - method: 'post', - server: server, - body: { - 'protection_enabled': enable - }, - type: 'general_protection' - ); + Future updateSafeSearchLegacy(bool enable) async { + final result = enable == true + ? await apiRequest( + urlPath: '/safesearch/enable', + method: 'post', + server: server, + type: 'enable_safe_search' + ) + : await apiRequest( + urlPath: '/safesearch/disable', + method: 'post', + server: server, + type: 'disable_safe_search' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'safe_search', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'general_protection', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } } - else { - return result; + + Future updateSafeBrowsing(bool enable) async { + final result = enable == true + ? await apiRequest( + urlPath: '/safebrowsing/enable', + method: 'post', + server: server, + type: 'enable_safe_browsing' + ) + : await apiRequest( + urlPath: '/safebrowsing/disable', + method: 'post', + server: server, + type: 'disable_safe_browsing' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'safe_browsing', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } } -} -Future getClients(Server server) async { - final result = await Future.wait([ - apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'get_clients'), - apiRequest(server: server, method: 'get', urlPath: '/access/list', type: 'get_clients'), - ]); + Future updateParentalControl(bool enable) async { + final result = enable == true + ? await apiRequest( + urlPath: '/parental/enable', + method: 'post', + server: server, + type: 'enable_parental_control' + ) + : await apiRequest( + urlPath: '/parental/disable', + method: 'post', + server: server, + type: 'disable_parental_control' + ); - if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - final clients = Clients.fromJson(jsonDecode(result[0]['body'])); - clients.clientsAllowedBlocked = ClientsAllowedBlocked.fromJson(jsonDecode(result[1]['body'])); - return { - 'result': 'success', - 'data': clients - }; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'parental_control', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future updateGeneralProtection({ + required bool enable, + int? time + }) async { + final result = await apiRequest( + urlPath: '/protection', + method: 'post', + server: server, + body: { + 'enabled': enable, + 'duration': time + }, + type: 'general_protection' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'general_protection', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future updateGeneralProtectionLegacy(bool enable) async { + final result = await apiRequest( + urlPath: '/dns_config', + method: 'post', + server: server, + body: { + 'protection_enabled': enable + }, + type: 'general_protection' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'general_protection', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getClients() async { + final result = await Future.wait([ + apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'get_clients'), + apiRequest(server: server, method: 'get', urlPath: '/access/list', type: 'get_clients'), + ]); + + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { + final clients = Clients.fromJson(jsonDecode(result[0]['body'])); + clients.clientsAllowedBlocked = ClientsAllowedBlocked.fromJson(jsonDecode(result[1]['body'])); + return { + 'result': 'success', + 'data': clients + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_clients', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -604,304 +622,295 @@ Future getClients(Server server) async { 'log': AppLog( type: 'get_clients', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: 'no_response', statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_clients', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } -} -Future requestAllowedBlockedClientsHosts(Server server, Map?> body) async { - final result = await apiRequest( - urlPath: '/access/set', - method: 'post', - server: server, - body: body, - type: 'get_clients' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - if (result['statusCode'] == 400) { - return { - 'result': 'error', - 'message': 'client_another_list' - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_clients', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future getLogs({ - required Server server, - required int count, - int? offset, - DateTime? olderThan, - String? responseStatus, - String? search -}) async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/querylog?limit=$count${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}', - type: 'get_logs' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': LogsData.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_logs', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future getFilteringRules({ - required Server server, -}) async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/filtering/status', - type: 'get_filtering_rules' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': FilteringStatus.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_filtering_rules', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future postFilteringRules({ - required Server server, - required Map> data, -}) async { + Future requestAllowedBlockedClientsHosts(Map?> body) async { final result = await apiRequest( - urlPath: '/filtering/set_rules', - method: 'post', - server: server, - body: data, - type: 'post_filering_rules' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'post_filtering_rules', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future postAddClient({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/clients/add', - method: 'post', - server: server, - body: data, - type: 'add_client' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'add_client', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future postUpdateClient({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/clients/update', - method: 'post', - server: server, - body: data, - type: 'update_client' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_client', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future postDeleteClient({ - required Server server, - required String name, -}) async { - final result = await apiRequest( - urlPath: '/clients/delete', - method: 'post', - server: server, - body: {'name': name}, - type: 'remove_client' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'remove_client', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future getFiltering({ - required Server server, -}) async { - final result = await Future.wait([ - apiRequest( - urlPath: '/filtering/status', - method: 'get', + urlPath: '/access/set', + method: 'post', server: server, - type: 'get_filtering_status' - ), - apiRequest( - urlPath: '/blocked_services/list', - method: 'get', - server: server, - type: 'get_filtering_status' - ), - ]); + body: body, + type: 'get_clients' + ); - if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { - return { - 'result': 'success', - 'data': Filtering.fromJson({ - ...jsonDecode(result[0]['body']), - "blocked_services": result[1]['body'] != null - ? jsonDecode(result[1]['body']) - : [] - }) - }; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + if (result['statusCode'] == 400) { + return { + 'result': 'error', + 'message': 'client_another_list' + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_clients', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getLogs({ + required int count, + int? offset, + DateTime? olderThan, + String? responseStatus, + String? search + }) async { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/querylog?limit=$count${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}', + type: 'get_logs' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': LogsData.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_logs', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getFilteringRules() async { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/filtering/status', + type: 'get_filtering_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': FilteringStatus.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future postFilteringRules({ + required Map> data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/set_rules', + method: 'post', + server: server, + body: data, + type: 'post_filering_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'post_filtering_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future postAddClient({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/clients/add', + method: 'post', + server: server, + body: data, + type: 'add_client' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'add_client', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future postUpdateClient({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/clients/update', + method: 'post', + server: server, + body: data, + type: 'update_client' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_client', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future postDeleteClient({ + required String name, + }) async { + final result = await apiRequest( + urlPath: '/clients/delete', + method: 'post', + server: server, + body: {'name': name}, + type: 'remove_client' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'remove_client', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getFiltering() async { + final result = await Future.wait([ + apiRequest( + urlPath: '/filtering/status', + method: 'get', + server: server, + type: 'get_filtering_status' + ), + apiRequest( + urlPath: '/blocked_services/list', + method: 'get', + server: server, + type: 'get_filtering_status' + ), + ]); + + if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { + return { + 'result': 'success', + 'data': Filtering.fromJson({ + ...jsonDecode(result[0]['body']), + "blocked_services": result[1]['body'] != null + ? jsonDecode(result[1]['body']) + : [] + }) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -909,230 +918,222 @@ Future getFiltering({ 'log': AppLog( type: 'get_filtering_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: 'no_response', statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_filtering_status', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } -} -Future setCustomRules({ - required Server server, - required List rules, -}) async { - final result = await apiRequest( - urlPath: '/filtering/set_rules', - method: 'post', - server: server, - body: {'rules': rules}, - type: 'set_custom_rules' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'set_custom_rules', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } - -} - -Future addFilteringList({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/filtering/add_url', - method: 'post', - server: server, - body: data, - type: 'add_filtering_url' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': result['body'] - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'add_filtering_url', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateFilterList({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/filtering/set_url', - method: 'post', - server: server, - body: data, - type: 'update_filter_list' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_filter_list', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future deleteFilterList({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/filtering/remove_url', - method: 'post', - server: server, - body: data, - type: 'delete_filter_list' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'delete_filter_list', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future getServerInfo({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/status', - method: 'get', - server: server, - type: 'server_info' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': ServerInfoData.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'server_info', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateLists({ - required Server server, -}) async { - final result = await Future.wait([ - apiRequest( - urlPath: '/filtering/refresh', + Future setCustomRules({ + required List rules, + }) async { + final result = await apiRequest( + urlPath: '/filtering/set_rules', method: 'post', server: server, - body: {'whitelist': true}, - type: 'update_lists', - overrideTimeout: true - ), - apiRequest( - urlPath: '/filtering/refresh', + body: {'rules': rules}, + type: 'set_custom_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'set_custom_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + + } + + Future addFilteringList({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/add_url', method: 'post', server: server, - body: {'whitelist': false}, - type: 'update_lists', - overrideTimeout: true - ), - ]); + body: data, + type: 'add_filtering_url' + ); - if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - return { - 'result': 'success', - 'data': {'updated': jsonDecode(result[0]['body'])['updated']+jsonDecode(result[1]['body'])['updated']} - }; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': result['body'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'add_filtering_url', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future updateFilterList({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/set_url', + method: 'post', + server: server, + body: data, + type: 'update_filter_list' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_filter_list', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future deleteFilterList({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/remove_url', + method: 'post', + server: server, + body: data, + type: 'delete_filter_list' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'delete_filter_list', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getServerInfo() async { + final result = await apiRequest( + urlPath: '/status', + method: 'get', + server: server, + type: 'server_info' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': ServerInfoData.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'server_info', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future updateLists() async { + final result = await Future.wait([ + apiRequest( + urlPath: '/filtering/refresh', + method: 'post', + server: server, + body: {'whitelist': true}, + type: 'update_lists', + overrideTimeout: true + ), + apiRequest( + urlPath: '/filtering/refresh', + method: 'post', + server: server, + body: {'whitelist': false}, + type: 'update_lists', + overrideTimeout: true + ), + ]); + + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { + return { + 'result': 'success', + 'data': {'updated': jsonDecode(result[0]['body'])['updated']+jsonDecode(result[1]['body'])['updated']} + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_lists', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -1140,914 +1141,1064 @@ Future updateLists({ 'log': AppLog( type: 'update_lists', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: [result[0]['message'], result[1]['message']].toString(), statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_lists', - dateTime: DateTime.now(), - message: [result[0]['message'], result[1]['message']].toString(), - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } -} -Future checkHostFiltered({ - required Server server, - required String host, -}) async { - final result = await apiRequest( - urlPath: '/filtering/check_host?name=$host', - method: 'get', - server: server, - type: 'check_host_filtered' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': jsonDecode(result['body']) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_lists', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future requestChangeUpdateFrequency({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/filtering/config', - method: 'post', - server: server, - body: data, - type: 'change_update_frequency' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'change_update_frequency', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future setBlockedServices({ - required Server server, - required List data, -}) async { - final result = await apiRequest( - urlPath: '/blocked_services/set', - method: 'post', - server: server, - body: data, - type: 'update_blocked_services' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_blocked_services', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getDhcpData({ - required Server server, -}) async { - final result = await Future.wait([ - apiRequest( - urlPath: '/dhcp/interfaces', + Future checkHostFiltered({ + required String host, + }) async { + final result = await apiRequest( + urlPath: '/filtering/check_host?name=$host', method: 'get', server: server, - type: 'get_dhcp_data' - ), - apiRequest( - urlPath: '/dhcp/status', - method: 'get', + type: 'check_host_filtered' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': jsonDecode(result['body']) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_lists', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future requestChangeUpdateFrequency({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/config', + method: 'post', server: server, - type: 'get_dhcp_data' - ), - ]); + body: data, + type: 'change_update_frequency' + ); - if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - List interfaces = List.from(jsonDecode(result[0]['body']).entries.map((entry) => NetworkInterface.fromJson(entry.value))); + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'change_update_frequency', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } - return { - 'result': 'success', - 'data': DhcpModel( - networkInterfaces: interfaces, - dhcpStatus: DhcpStatus.fromJson(jsonDecode(result[1]['body'])) - ) - }; + Future setBlockedServices({ + required List data, + }) async { + final result = await apiRequest( + urlPath: '/blocked_services/set', + method: 'post', + server: server, + body: data, + type: 'update_blocked_services' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_blocked_services', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getDhcpData() async { + final result = await Future.wait([ + apiRequest( + urlPath: '/dhcp/interfaces', + method: 'get', + server: server, + type: 'get_dhcp_data' + ), + apiRequest( + urlPath: '/dhcp/status', + method: 'get', + server: server, + type: 'get_dhcp_data' + ), + ]); + + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { + List interfaces = List.from(jsonDecode(result[0]['body']).entries.map((entry) => NetworkInterface.fromJson(entry.value))); + + return { + 'result': 'success', + 'data': DhcpModel( + networkInterfaces: interfaces, + dhcpStatus: DhcpStatus.fromJson(jsonDecode(result[1]['body'])) + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_dhcp_data', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { 'result': 'error', 'log': AppLog( - type: 'get_dhcp_data', + type: 'get_dhpc_data', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: [result[0]['log'].message, result[1]['log'].message].toString(), statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_dhpc_data', - dateTime: DateTime.now(), - message: [result[0]['log'].message, result[1]['log'].message].toString(), - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; + + Future saveDhcpConfig({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/dhcp/set_config', + method: 'post', + server: server, + body: data, + type: 'save_dhcp_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'save_dhcp_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } } -} -Future saveDhcpConfig({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/dhcp/set_config', - method: 'post', - server: server, - body: data, - type: 'save_dhcp_config' - ); + Future resetDhcpConfig() async { + final result = await apiRequest( + urlPath: '/dhcp/reset', + method: 'post', + server: server, + body: {}, + type: 'reset_dhcp_config' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'reset_dhcp_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future deleteStaticLease({ + required Map data + }) async { + final result = await apiRequest( + urlPath: '/dhcp/remove_static_lease', + method: 'post', + server: server, + body: data, + type: 'remove_static_lease' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'remove_static_lease', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future createStaticLease({ + required Map data + }) async { + final result = await apiRequest( + urlPath: '/dhcp/add_static_lease', + method: 'post', + server: server, + body: data, + type: 'add_static_lease' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else if (result['statusCode'] == 400 && result['body'].contains('static lease already exists')) { + return { + 'result': 'error', + 'message': 'already_exists', + 'log': AppLog( + type: 'add_static_lease', + dateTime: DateTime.now(), + message: 'already_exists', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + else if (result['statusCode'] == 400 && result['body'].contains('server is unconfigured')) { + return { + 'result': 'error', + 'message': 'server_not_configured', + 'log': AppLog( + type: 'add_static_lease', + dateTime: DateTime.now(), + message: 'server_not_configured', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'add_static_lease', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future restoreAllLeases() async { + final result = await apiRequest( + urlPath: '/dhcp/reset_leases', + method: 'post', + server: server, + body: {}, + type: 'restore_all_leases' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'restore_all_leases', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getDnsRewriteRules() async { + final result = await apiRequest( + urlPath: '/rewrite/list', + method: 'get', + server: server, + type: 'get_dns_rewrite_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + final List data = List.from( + jsonDecode(result['body']).map((item) => RewriteRules.fromJson(item)) + ); + + return { + 'result': 'success', + 'data': data + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_dns_rewrite_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future deleteDnsRewriteRule({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/rewrite/delete', + method: 'post', + server: server, + body: data, + type: 'delete_dns_rewrite_rule' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'delete_dns_rewrite_rule', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future addDnsRewriteRule({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/rewrite/add', + method: 'post', + server: server, + body: data, + type: 'add_dns_rewrite_rule' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'add_dns_rewrite_rule', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getQueryLogInfo() async { + final result = await apiRequest( + urlPath: '/querylog/config', + method: 'get', + server: server, + type: 'get_query_log_info' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': jsonDecode(result['body']) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_query_log_info', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getQueryLogInfoLegacy() async { + final result = await apiRequest( + urlPath: '/querylog_info', + method: 'get', + server: server, + type: 'get_query_log_info' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': jsonDecode(result['body']) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_query_log_info', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future updateQueryLogParameters({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/querylog/config/update', + method: 'put', + server: server, + body: data, + type: 'update_query_log_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_query_log_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future updateQueryLogParametersLegacy({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/querylog_config', + method: 'post', + server: server, + body: data, + type: 'update_query_log_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_query_log_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future clearLogs() async { + final result = await apiRequest( + urlPath: '/querylog_clear', + method: 'post', + server: server, + body: {}, + type: 'clear_query_logs' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'clear_query_logs', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getDnsInfo() async { + final result = await apiRequest( + urlPath: '/dns_info', + method: 'get', + server: server, + type: 'get_dns_info' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success' , + 'data': DnsInfo.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_dns_info', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future setDnsConfig({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/dns_config', + method: 'post', + server: server, + body: data, + type: 'set_dns_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + if (result['statusCode'] == 400) { + return { + 'result': 'error', + 'log': AppLog( + type: 'set_dns_config', + dateTime: DateTime.now(), + message: 'data_not_valid', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'set_dns_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getEncryptionSettings() async { + final result = await apiRequest( + urlPath: '/tls/status', + method: 'get', + server: server, + type: 'get_encryption_settings' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': EncryptionData.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getBlockedServices() async { + final result = await apiRequest( + urlPath: '/blocked_services/all', + method: 'get', + server: server, + type: 'get_blocked_services' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': List.from( + BlockedServicesFromApi.fromJson(jsonDecode(result['body'])).blockedServices + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future checkEncryptionSettings({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/tls/validate', + method: 'post', + server: server, + body: data, + type: 'check_encryption_settings' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': jsonDecode(result['body']) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'check_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future saveEncryptionSettings({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/tls/configure', + method: 'post', + server: server, + body: data, + type: 'update_encryption_settings' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future resetDnsCache() async { + final result = await apiRequest( + urlPath: '/cache_clear', + method: 'post', + server: server, + type: 'clear_dns_cache' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'clear_dns_cache', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future checkServerUpdates() async { + final result = await Future.wait([ + apiRequest( + urlPath: '/version.json', + method: 'get', + server: server, + type: 'check_server_updates', + body: json.encode({ + "recheck_now": true + }) + ), + apiRequest( + urlPath: '/status', + method: 'get', + server: server, + type: 'check_server_updates', + body: json.encode({ + "recheck_now": true + }) + ), + ]); + + if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { + final Map obj = { + ...jsonDecode(result[0]['body']), + 'current_version': jsonDecode(result[1]['body'])['version'] + }; + return { + 'result': 'success', + 'data': obj + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { 'result': 'error', 'log': AppLog( - type: 'save_dhcp_config', + type: 'get_filtering_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], + message: 'no_response', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return result; + + Future getUpdateChangelog({ + required String releaseTag + }) async { + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.getUrl(Uri.parse("${Urls.adGuardHomeReleasesTags}/$releaseTag")); + HttpClientResponse response = await request.close(); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + if (response.statusCode == 200) { + return { + 'result': 'success', + 'hasResponse': true, + 'error': false, + 'statusCode': response.statusCode, + 'body': jsonDecode(reply)['body'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: response.statusCode.toString(), + resBody: reply, + ) + }; + } + } on SocketException { + return { + 'result': 'no_connection', + 'message': 'SocketException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'SocketException' + ) + }; + } on TimeoutException { + return { + 'result': 'no_connection', + 'message': 'TimeoutException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'TimeoutException' + ) + }; + } on HandshakeException { + return { + 'result': 'ssl_error', + 'message': 'HandshakeException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'HandshakeException' + ) + }; + } catch (e) { + return { + 'result': 'error', + 'message': e.toString(), + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: e.toString() + ) + }; + } } -} -Future resetDhcpConfig({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/dhcp/reset', - method: 'post', - server: server, - body: {}, - type: 'reset_dhcp_config' - ); + Future requestUpdateServer() async { + final result = await apiRequest( + urlPath: '/update', + method: 'post', + server: server, + type: 'update_server' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_server', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'reset_dhcp_config', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; + return result; } } - else { - return result; - } -} -Future deleteStaticLease({ - required Server server, - required Map data -}) async { - final result = await apiRequest( - urlPath: '/dhcp/remove_static_lease', - method: 'post', - server: server, - body: data, - type: 'remove_static_lease' - ); + Future updateSafeSearchSettings({ - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + required Map body + }) async { + final result = await apiRequest( + urlPath: '/safesearch/settings', + method: 'put', + server: server, + type: 'safesearch_settings', + body: body + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'safesearch_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'remove_static_lease', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; + return result; } } - else { - return result; - } -} - -Future createStaticLease({ - required Server server, - required Map data -}) async { - final result = await apiRequest( - urlPath: '/dhcp/add_static_lease', - method: 'post', - server: server, - body: data, - type: 'add_static_lease' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else if (result['statusCode'] == 400 && result['body'].contains('static lease already exists')) { - return { - 'result': 'error', - 'message': 'already_exists', - 'log': AppLog( - type: 'add_static_lease', - dateTime: DateTime.now(), - message: 'already_exists', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - else if (result['statusCode'] == 400 && result['body'].contains('server is unconfigured')) { - return { - 'result': 'error', - 'message': 'server_not_configured', - 'log': AppLog( - type: 'add_static_lease', - dateTime: DateTime.now(), - message: 'server_not_configured', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'add_static_lease', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future restoreAllLeases({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/dhcp/reset_leases', - method: 'post', - server: server, - body: {}, - type: 'restore_all_leases' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'restore_all_leases', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getDnsRewriteRules({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/rewrite/list', - method: 'get', - server: server, - type: 'get_dns_rewrite_rules' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - final List data = List.from( - jsonDecode(result['body']).map((item) => RewriteRules.fromJson(item)) - ); - - return { - 'result': 'success', - 'data': data - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_dns_rewrite_rules', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future deleteDnsRewriteRule({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/rewrite/delete', - method: 'post', - server: server, - body: data, - type: 'delete_dns_rewrite_rule' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'delete_dns_rewrite_rule', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future addDnsRewriteRule({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/rewrite/add', - method: 'post', - server: server, - body: data, - type: 'add_dns_rewrite_rule' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'add_dns_rewrite_rule', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getQueryLogInfo({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/querylog/config', - method: 'get', - server: server, - type: 'get_query_log_info' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': jsonDecode(result['body']) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_query_log_info', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getQueryLogInfoLegacy({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/querylog_info', - method: 'get', - server: server, - type: 'get_query_log_info' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': jsonDecode(result['body']) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_query_log_info', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future updateQueryLogParameters({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/querylog/config/update', - method: 'put', - server: server, - body: data, - type: 'update_query_log_config' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_query_log_config', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future updateQueryLogParametersLegacy({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/querylog_config', - method: 'post', - server: server, - body: data, - type: 'update_query_log_config' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_query_log_config', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future clearLogs({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/querylog_clear', - method: 'post', - server: server, - body: {}, - type: 'clear_query_logs' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'clear_query_logs', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getDnsInfo({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/dns_info', - method: 'get', - server: server, - type: 'get_dns_info' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success' , - 'data': DnsInfo.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_dns_info', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future setDnsConfig({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/dns_config', - method: 'post', - server: server, - body: data, - type: 'set_dns_config' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - if (result['statusCode'] == 400) { - return { - 'result': 'error', - 'log': AppLog( - type: 'set_dns_config', - dateTime: DateTime.now(), - message: 'data_not_valid', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'set_dns_config', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getEncryptionSettings({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/tls/status', - method: 'get', - server: server, - type: 'get_encryption_settings' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': EncryptionData.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getBlockedServices({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/blocked_services/all', - method: 'get', - server: server, - type: 'get_blocked_services' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': List.from( - BlockedServicesFromApi.fromJson(jsonDecode(result['body'])).blockedServices - ) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future checkEncryptionSettings({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/tls/validate', - method: 'post', - server: server, - body: data, - type: 'check_encryption_settings' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': jsonDecode(result['body']) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'check_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future saveEncryptionSettings({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/tls/configure', - method: 'post', - server: server, - body: data, - type: 'update_encryption_settings' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future resetDnsCache({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/cache_clear', - method: 'post', - server: server, - type: 'clear_dns_cache' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'clear_dns_cache', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } } Future checkAppUpdatesGitHub() async { @@ -2119,206 +2270,4 @@ Future checkAppUpdatesGitHub() async { ) }; } -} - -Future checkServerUpdates({ - required Server server, -}) async { - final result = await Future.wait([ - apiRequest( - urlPath: '/version.json', - method: 'get', - server: server, - type: 'check_server_updates', - body: json.encode({ - "recheck_now": true - }) - ), - apiRequest( - urlPath: '/status', - method: 'get', - server: server, - type: 'check_server_updates', - body: json.encode({ - "recheck_now": true - }) - ), - ]); - - if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { - final Map obj = { - ...jsonDecode(result[0]['body']), - 'current_version': jsonDecode(result[1]['body'])['version'] - }; - return { - 'result': 'success', - 'data': obj - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_filtering_status', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_filtering_status', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } -} - -Future getUpdateChangelog({ - required Server server, - required String releaseTag -}) async { - try { - HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse("${Urls.adGuardHomeReleasesTags}/$releaseTag")); - HttpClientResponse response = await request.close(); - String reply = await response.transform(utf8.decoder).join(); - httpClient.close(); - if (response.statusCode == 200) { - return { - 'result': 'success', - 'hasResponse': true, - 'error': false, - 'statusCode': response.statusCode, - 'body': jsonDecode(reply)['body'] - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: response.statusCode.toString(), - resBody: reply, - ) - }; - } - } on SocketException { - return { - 'result': 'no_connection', - 'message': 'SocketException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'SocketException' - ) - }; - } on TimeoutException { - return { - 'result': 'no_connection', - 'message': 'TimeoutException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'TimeoutException' - ) - }; - } on HandshakeException { - return { - 'result': 'ssl_error', - 'message': 'HandshakeException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'HandshakeException' - ) - }; - } catch (e) { - return { - 'result': 'error', - 'message': e.toString(), - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: e.toString() - ) - }; - } -} - -Future requestUpdateServer({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/update', - method: 'post', - server: server, - type: 'update_server' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_server', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future updateSafeSearchSettings({ - required Server server, - required Map body -}) async { - final result = await apiRequest( - urlPath: '/safesearch/settings', - method: 'put', - server: server, - type: 'safesearch_settings', - body: body - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'safesearch_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } } \ No newline at end of file diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index d299cf4..51d8b22 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -261,13 +261,16 @@ class _AddServerModalState extends State { final serverCreated = await serversProvider.createServer(serverObj); if (serverCreated == null) { statusProvider.setServerStatusLoad(LoadStatus.loading); + + final ApiClient apiClient = ApiClient(server: serverObj); - final serverStatus = await getServerStatus(serverObj); + final serverStatus = await apiClient.getServerStatus(); if (serverStatus['result'] == 'success') { statusProvider.setServerStatusData( data: serverStatus['data'] ); + serversProvider.setApiClient(apiClient); statusProvider.setServerStatusLoad(LoadStatus.loaded); if (serverStatus['data'].serverVersion.contains('a') || serverStatus['data'].serverVersion.contains('b')) { Navigator.pop(context); @@ -382,7 +385,8 @@ class _AddServerModalState extends State { final serverSaved = await serversProvider.editServer(serverObj); if (serverSaved == null) { - final version = await getServerVersion(serverObj); + final ApiClient apiClient = ApiClient(server: serverObj); + final version = await apiClient.getServerVersion(); if ( version['result'] == 'success' && (version['data'].contains('a') || version['data'].contains('b')) // alpha or beta diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index 36abbbe..8465844 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -17,11 +17,10 @@ class BottomNavBar extends StatelessWidget { final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); - List screens = serversProvider.selectedServer != null + List screens = serversProvider.selectedServer != null && serversProvider.apiClient != null ? screensServerConnected : screensSelectServer; - String translatedName(String key) { switch (key) { case 'home': @@ -47,8 +46,14 @@ class BottomNavBar extends StatelessWidget { } } + if ((serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1) { + appConfigProvider.setSelectedScreen(0); + } + return NavigationBar( - selectedIndex: appConfigProvider.selectedScreen, + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 + ? 0 + : appConfigProvider.selectedScreen, destinations: screens.map((screen) => NavigationDestination( icon: Stack( children: [ diff --git a/lib/widgets/domain_options.dart b/lib/widgets/domain_options.dart index 415a8c3..58409d9 100644 --- a/lib/widgets/domain_options.dart +++ b/lib/widgets/domain_options.dart @@ -9,12 +9,10 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; class DomainOptions extends StatelessWidget { @@ -37,7 +35,6 @@ class DomainOptions extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -45,52 +42,26 @@ class DomainOptions extends StatelessWidget { final ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingUserFilters); - final rules = await getFilteringRules(server: serversProvider.selectedServer!); + final rules = await statusProvider.blockUnblockDomain( + domain: domain, + newStatus: newStatus + ); - if (rules['result'] == 'success') { - FilteringStatus oldStatus = statusProvider.serverStatus!.filteringStatus; + processModal.close(); - List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); - if (newStatus == 'block') { - newRules.add("||$domain^"); - } - else if (newStatus == 'unblock') { - newRules.add("@@||$domain^"); - } - FilteringStatus newObj = statusProvider.serverStatus!.filteringStatus; - newObj.userRules = newRules; - statusProvider.setFilteringStatus(newObj); - - final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); - - processModal.close(); - - if (result['result'] == 'success') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesUpdated), - backgroundColor: Colors.green, - ) - ); - } - else { - appConfigProvider.addLog(result['log']); - statusProvider.setFilteringStatus(oldStatus); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) - ); - } + if (rules == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesUpdated, + color: Colors.green + ); } else { - appConfigProvider.addLog(rules['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, + color: Colors.red + ); } } diff --git a/lib/widgets/navigation_rail.dart b/lib/widgets/navigation_rail.dart index 6dc028f..063993c 100644 --- a/lib/widgets/navigation_rail.dart +++ b/lib/widgets/navigation_rail.dart @@ -46,8 +46,14 @@ class SideNavigationRail extends StatelessWidget { } } + if ((serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1) { + appConfigProvider.setSelectedScreen(0); + } + return NavigationRail( - selectedIndex: appConfigProvider.selectedScreen, + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 + ? 0 + : appConfigProvider.selectedScreen, destinations: screens.map((screen) => NavigationRailDestination( icon: Icon( screen.icon, diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 1a9c482..fb3364e 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -135,10 +135,12 @@ class _ServersListItemState extends State with SingleTickerProv : await login(server); if (result['result'] == 'success') { + final ApiClient apiClient = ApiClient(server: server); + serversProvider.setApiClient(apiClient); serversProvider.setSelectedServer(server); statusProvider.setServerStatusLoad(LoadStatus.loading); - final serverStatus = await getServerStatus(server); + final serverStatus = await apiClient.getServerStatus(); if (serverStatus['result'] == 'success') { statusProvider.setServerStatusData( data: serverStatus['data'] diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index 32c3772..fd274d6 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -102,10 +102,12 @@ class _ServersTileItemState extends State with SingleTickerProv : await login(server); if (result['result'] == 'success') { + final ApiClient apiClient = ApiClient(server: server); + serversProvider.setApiClient(apiClient); serversProvider.setSelectedServer(server); statusProvider.setServerStatusLoad(LoadStatus.loading); - final serverStatus = await getServerStatus(server); + final serverStatus = await apiClient.getServerStatus(); if (serverStatus['result'] == 'success') { statusProvider.setServerStatusData( data: serverStatus['data'] From 3470270df0f8eaab81447354160b7d53d555ea19 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 15:11:24 +0200 Subject: [PATCH 154/676] Removed unused imports --- lib/main.dart | 1 - lib/providers/servers_provider.dart | 5 +--- lib/screens/filters/add_button.dart | 3 -- .../access_settings/access_settings.dart | 3 -- lib/screens/settings/advanced_setings.dart | 29 ------------------- lib/screens/settings/dns/cache_config.dart | 2 -- .../settings/dns/dns_server_settings.dart | 3 -- lib/screens/settings/dns/upstream_dns.dart | 2 -- lib/screens/top_items/top_items.dart | 3 -- 9 files changed, 1 insertion(+), 50 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 4ab8db5..6fa26e1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -27,7 +27,6 @@ import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/colors.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/config/globals.dart'; import 'package:adguard_home_manager/config/theme.dart'; import 'package:adguard_home_manager/classes/http_override.dart'; diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 2ed27be..4b45394 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -193,7 +193,7 @@ class ServersProvider with ChangeNotifier { } } - Future?> saveFromDb(List>? data) async { + Future saveFromDb(List>? data) async { if (data != null) { Server? defaultServer; for (var server in data) { @@ -223,9 +223,6 @@ class ServersProvider with ChangeNotifier { _apiClient = ApiClient(server: defaultServer); initializateServer(defaultServer); } - else { - return null; - } } else { notifyListeners(); diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 0292d3a..722ff60 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -11,11 +11,8 @@ import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class AddFiltersButton extends StatelessWidget { diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index 46ea0f3..beb34fd 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -8,9 +8,6 @@ import 'package:adguard_home_manager/screens/settings/access_settings/clients_li import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class AccessSettings extends StatefulWidget { const AccessSettings({Key? key}) : super(key: key); diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 402b69a..66ff49b 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -1,14 +1,10 @@ // ignore_for_file: use_build_context_synchronously -import 'dart:io'; - import 'package:flutter/material.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/screens/settings/app_logs/app_logs.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -20,8 +16,6 @@ class AdvancedSettings extends StatelessWidget { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - final width = MediaQuery.of(context).size.width; - Future updateSettings({ required bool newStatus, required Future Function(bool) function @@ -71,29 +65,6 @@ class AdvancedSettings extends StatelessWidget { right: 10 ) ), - // CustomListTile( - // icon: Icons.list_rounded, - // title: AppLocalizations.of(context)!.logs, - // subtitle: AppLocalizations.of(context)!.checkAppLogs, - // onTap: () => { - // if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - // SplitView.of(context).push(const AppLogs()) - // } - // else { - // Navigator.of(context).push( - // MaterialPageRoute( - // builder: (context) => const AppLogs() - // ) - // ) - // } - // }, - // padding: const EdgeInsets.only( - // top: 10, - // bottom: 10, - // left: 20, - // right: 10 - // ) - // ), ], ) ); diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index bbd78c3..cd2968b 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -12,9 +12,7 @@ import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/clear_dns_cache.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class CacheConfigDnsScreen extends StatefulWidget { const CacheConfigDnsScreen({Key? key}) : super(key: key); diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index fffd43a..9169408 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -8,13 +8,10 @@ import 'package:adguard_home_manager/widgets/custom_radio_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class DnsServerSettingsScreen extends StatefulWidget { const DnsServerSettingsScreen({Key? key}) : super(key: key); diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 1d2e596..3041da4 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -14,7 +14,6 @@ import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class UpstreamDnsScreen extends StatefulWidget { const UpstreamDnsScreen({Key? key}) : super(key: key); @@ -67,7 +66,6 @@ class _UpstreamDnsScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 8db5464..6e9af74 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -16,8 +16,6 @@ import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class TopItemsScreen extends StatefulWidget { final String type; @@ -58,7 +56,6 @@ class _TopItemsScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); From 44e0f274ec6ace59e457fc4d8b79bf52082f17c8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 15:11:53 +0200 Subject: [PATCH 155/676] Removed unused imports --- lib/screens/filters/add_button.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 722ff60..3cbedc9 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -13,7 +13,6 @@ import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class AddFiltersButton extends StatelessWidget { final String type; @@ -27,7 +26,6 @@ class AddFiltersButton extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); From 7f0c5fcefd376257e4c1699e650e319009ab502e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 18:19:58 +0200 Subject: [PATCH 156/676] Fixed countdown --- lib/functions/format_time.dart | 13 ++++++ lib/providers/status_provider.dart | 57 +++++++++++++++++++++++++- lib/screens/home/management_modal.dart | 56 ++----------------------- 3 files changed, 72 insertions(+), 54 deletions(-) diff --git a/lib/functions/format_time.dart b/lib/functions/format_time.dart index e5baff0..41f0dd4 100644 --- a/lib/functions/format_time.dart +++ b/lib/functions/format_time.dart @@ -13,4 +13,17 @@ String convertTimestampLocalTimezone(DateTime timestamp, String format) { String formatTimeOfDay(TimeOfDay timestamp, String format) { DateFormat f = DateFormat(format); return f.format(DateTime(0, 0, 0, timestamp.hour, timestamp.minute)); +} + +String formatRemainingSeconds(int seconds) { + int h, m, s; + h = seconds ~/ 3600; + m = ((seconds - h * 3600)) ~/ 60; + s = seconds - (h * 3600) - (m * 60); + + String hourLeft = h.toString().length < 2 ? "0$h" : h.toString(); + String minuteLeft = m.toString().length < 2 ? "0$m" : m.toString(); + String secondsLeft = s.toString().length < 2 ? "0$s" : s.toString(); + + return "$hourLeft:$minuteLeft:$secondsLeft"; } \ No newline at end of file diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 006a753..7fa1682 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:adguard_home_manager/models/server_status.dart'; @@ -19,6 +21,11 @@ class StatusProvider with ChangeNotifier { List _protectionsManagementProcess = []; // protections that are currenty being enabled or disabled FilteringStatus? _filteringStatus; + // Countdown + DateTime? _currentDeadline; + Timer? _countdown; + int _remaining = 0; + LoadStatus get loadStatus { return _loadStatus; } @@ -35,10 +42,24 @@ class StatusProvider with ChangeNotifier { return _filteringStatus; } + int get remainingTime { + return _remaining; + } + + DateTime? get currentDeadline { + return _currentDeadline; + } + void setServerStatusData({ required ServerStatus data, }) { _serverStatus = data; + if ( + (_countdown == null ||( _countdown != null && _countdown!.isActive == false)) && + data.disabledUntil != null + ) { + startCountdown(data.disabledUntil!); + } notifyListeners(); } @@ -52,6 +73,37 @@ class StatusProvider with ChangeNotifier { notifyListeners(); } + void startCountdown(DateTime deadline) { + stopCountdown(); + + _currentDeadline = deadline; + _remaining = deadline.difference(DateTime.now()).inSeconds+1; + + _countdown = Timer.periodic( + const Duration(seconds: 1), + (Timer timer) async { + if (_remaining == 0) { + timer.cancel(); + notifyListeners(); + getServerStatus(); + } + else { + _remaining = _remaining - 1; + notifyListeners(); + } + }, + ); + } + + void stopCountdown() { + if (_countdown != null && _countdown!.isActive) { + _countdown!.cancel(); + _countdown = null; + _remaining = 0; + _currentDeadline = null; + } + } + Future updateBlocking({ required String block, required bool newStatus, @@ -72,12 +124,15 @@ class StatusProvider with ChangeNotifier { if (result['result'] == 'success') { _serverStatus!.generalEnabled = newStatus; if (time != null) { + final deadline = generateTimeDeadline(time); _serverStatus!.timeGeneralDisabled = time; - _serverStatus!.disabledUntil = generateTimeDeadline(time); + _serverStatus!.disabledUntil = deadline; + startCountdown(deadline); } else { _serverStatus!.timeGeneralDisabled = 0; _serverStatus!.disabledUntil = null; + stopCountdown(); } notifyListeners(); return null; diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index f35820c..562fbc4 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -11,7 +11,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/functions/time_server_disabled.dart'; +import 'package:adguard_home_manager/functions/format_time.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class ManagementModal extends StatefulWidget { @@ -31,10 +31,6 @@ class _ManagementModalState extends State with SingleTickerProv late Animation animation; final ExpandableController expandableController = ExpandableController(); - DateTime? currentDeadline; - Timer? countdown; - int start = 0; - @override void initState() { expandableController.addListener(() async { @@ -65,7 +61,6 @@ class _ManagementModalState extends State with SingleTickerProv @override void dispose() { - if (countdown != null) countdown!.cancel(); animationController.dispose(); super.dispose(); } @@ -75,51 +70,6 @@ class _ManagementModalState extends State with SingleTickerProv final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - void startTimer(DateTime deadline) { - setState(() { - currentDeadline = deadline; - start = deadline.difference(DateTime.now()).inSeconds+1; - }); - - const oneSec = Duration(seconds: 1); - countdown = Timer.periodic( - oneSec, - (Timer timer) async { - if (start == 0) { - setState(() { - timer.cancel(); - }); - final result = await statusProvider.getServerStatus(); - if (result == false) { - setState(() { - start = start - 1; - }); - } - } - }, - ); - } - - if ( - statusProvider.serverStatus != null && - statusProvider.serverStatus!.disabledUntil != null && - statusProvider.serverStatus!.disabledUntil != currentDeadline - ) { - startTimer(statusProvider.serverStatus!.disabledUntil!); - } - - if ( - statusProvider.serverStatus != null && - statusProvider.serverStatus!.generalEnabled == true - ) { - setState(() { - start = 0; - currentDeadline = null; - if (countdown != null) countdown!.cancel(); - countdown = null; - }); - } - void updateBlocking({ required bool value, required String filter, @@ -178,8 +128,8 @@ class _ManagementModalState extends State with SingleTickerProv ), if (statusProvider.serverStatus!.timeGeneralDisabled > 0) ...[ const SizedBox(height: 2), - if (currentDeadline != null) Text( - "${AppLocalizations.of(context)!.remainingTime}: ${generateRemainingTimeString(currentDeadline!.difference(DateTime.now()))}" + if (statusProvider.currentDeadline != null) Text( + "${AppLocalizations.of(context)!.remainingTime}: ${formatRemainingSeconds(statusProvider.remainingTime)}" ) ] ], From de651118f249a09500b98369629ac0b1722d6c6a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 18:30:44 +0200 Subject: [PATCH 157/676] Added timer icon home header --- lib/screens/home/appbar.dart | 58 ++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 1ae88e1..675dafd 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -40,22 +40,48 @@ class HomeAppBar extends StatelessWidget { floating: true, centerTitle: false, forceElevated: innerBoxScrolled, - leading: Icon( - serversProvider.selectedServer != null && statusProvider.serverStatus != null - ? statusProvider.serverStatus!.generalEnabled == true - ? Icons.gpp_good_rounded - : Icons.gpp_bad_rounded - : Icons.shield, - size: 30, - color: serversProvider.selectedServer != null && statusProvider.serverStatus != null - ? statusProvider.serverStatus!.generalEnabled == true - ? appConfigProvider.useThemeColorForStatus - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - : Colors.red - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + leading: Stack( + children: [ + Center( + child: Icon( + serversProvider.selectedServer != null && statusProvider.serverStatus != null + ? statusProvider.serverStatus!.generalEnabled == true + ? Icons.gpp_good_rounded + : Icons.gpp_bad_rounded + : Icons.shield, + size: 30, + color: serversProvider.selectedServer != null && statusProvider.serverStatus != null + ? statusProvider.serverStatus!.generalEnabled == true + ? appConfigProvider.useThemeColorForStatus + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + : Colors.red + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + ), + ), + if (statusProvider.remainingTime > 0) Positioned( + bottom: 15, + right: 15, + child: Stack( + children: [ + Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Theme.of(context).colorScheme.surface + ), + child: Icon( + Icons.timer_rounded, + size: 12, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ], + ), + ) + ], ), title: Column( mainAxisSize: MainAxisSize.min, From 3a2b2533b06432ec5be96c27ffced6ba0293790d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 18:33:39 +0200 Subject: [PATCH 158/676] Fixed background color top row management modal --- lib/screens/home/management_modal.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 562fbc4..aaeaab7 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -223,7 +223,7 @@ class _ManagementModalState extends State with SingleTickerProv ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(28), - color: Theme.of(context).primaryColor.withOpacity(0.1) + color: Theme.of(context).colorScheme.primary.withOpacity(0.1) ), child: Expandable( theme: const ExpandableThemeData( From 38b6f428f20de4aadc1a2a1d208af7fa0fab1a8f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 18:42:11 +0200 Subject: [PATCH 159/676] Disabled update checker on beta --- lib/base.dart | 21 ++++++++++++--------- lib/screens/settings/general_settings.dart | 3 ++- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/base.dart b/lib/base.dart index 5c6289b..6b9f3b0 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -77,16 +77,19 @@ class _BaseState extends State with WidgetsBindingObserver { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { - final result = await checkInstallationSource(); + final version = Provider.of(context, listen: false).getAppInfo!.version; + if (!version.contains('beta')) { + final result = await checkInstallationSource(); - if (result != null && widget.appConfigProvider.doNotRememberVersion != result.tagName) { - await showDialog( - context: context, - builder: (context) => UpdateModal( - gitHubRelease: result, - onDownload: (link, version) => openUrl(link), - ), - ); + if (result != null && widget.appConfigProvider.doNotRememberVersion != result.tagName) { + await showDialog( + context: context, + builder: (context) => UpdateModal( + gitHubRelease: result, + onDownload: (link, version) => openUrl(link), + ), + ); + } } }); } diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index d237d3c..792d463 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -210,7 +210,8 @@ class _GeneralSettingsState extends State { appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || appConfigProvider.installationSource == Source.UNKNOWN - )) + )) && + !appConfigProvider.getAppInfo!.version.contains('beta') ) ...[ SectionLabel(label: AppLocalizations.of(context)!.application), CustomListTile( From 33840c2c908c9165335a1895f32ed66c6f1dbd74 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 18:45:56 +0200 Subject: [PATCH 160/676] Updated Android version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 5f2b61d..ccebd1f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.3.2+61 +version: 2.4.0-beta.1+62 environment: sdk: '>=2.18.1 <3.0.0' From 71853d678aa9bef3b4d91a860cad57779bfa8843 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 21:14:26 +0200 Subject: [PATCH 161/676] Fixed updater --- lib/base.dart | 70 +++++----------------- lib/constants/urls.dart | 2 +- lib/functions/check_app_updates.dart | 51 ++++++++++++++++ lib/functions/compare_versions.dart | 58 ++++++++++++++---- lib/main.dart | 2 +- lib/providers/app_config_provider.dart | 2 +- lib/screens/settings/general_settings.dart | 29 ++++----- lib/services/http_requests.dart | 4 +- 8 files changed, 131 insertions(+), 87 deletions(-) create mode 100644 lib/functions/check_app_updates.dart diff --git a/lib/base.dart b/lib/base.dart index 6b9f3b0..5869774 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -1,15 +1,11 @@ // ignore_for_file: use_build_context_synchronously, depend_on_referenced_packages -import 'dart:async'; -import 'dart:io'; - import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:provider/provider.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:store_checker/store_checker.dart'; import 'package:flutter/services.dart'; import 'package:adguard_home_manager/widgets/bottom_nav_bar.dart'; @@ -18,21 +14,14 @@ import 'package:adguard_home_manager/widgets/update_modal.dart'; import 'package:adguard_home_manager/widgets/navigation_rail.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; -import 'package:adguard_home_manager/models/github_release.dart'; +import 'package:adguard_home_manager/functions/check_app_updates.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/app_screen.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class Base extends StatefulWidget { - final AppConfigProvider appConfigProvider; - - const Base({ - Key? key, - required this.appConfigProvider, - }) : super(key: key); + const Base({Key? key}) : super(key: key); @override State createState() => _BaseState(); @@ -41,35 +30,6 @@ class Base extends StatefulWidget { class _BaseState extends State with WidgetsBindingObserver { int selectedScreen = 0; - Future checkInstallationSource() async { - final result = await checkAppUpdatesGitHub(); - if (result['result'] == 'success') { - final update = gitHubUpdateExists(widget.appConfigProvider.getAppInfo!.version, result['body'].tagName); - if (update == true) { - widget.appConfigProvider.setAppUpdatesAvailable(result['body']); - if (Platform.isAndroid) { - if ( - widget.appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || - widget.appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || - widget.appConfigProvider.installationSource == Source.UNKNOWN - ) { - return result['body']; - } - else { - return null; - } - } - else if (Platform.isIOS) { - return null; - } - else { - return result['body']; - } - } - } - return null; - } - @override void initState() { WidgetsBinding.instance.addObserver(this); @@ -77,19 +37,21 @@ class _BaseState extends State with WidgetsBindingObserver { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { - final version = Provider.of(context, listen: false).getAppInfo!.version; - if (!version.contains('beta')) { - final result = await checkInstallationSource(); + final appConfigProvider = Provider.of(context, listen: false); + final result = await checkAppUpdates( + appVersion: appConfigProvider.getAppInfo!.version, + installationSource: appConfigProvider.installationSource, + setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable + ); - if (result != null && widget.appConfigProvider.doNotRememberVersion != result.tagName) { - await showDialog( - context: context, - builder: (context) => UpdateModal( - gitHubRelease: result, - onDownload: (link, version) => openUrl(link), - ), - ); - } + if (result != null && appConfigProvider.doNotRememberVersion != result.tagName) { + await showDialog( + context: context, + builder: (context) => UpdateModal( + gitHubRelease: result, + onDownload: (link, version) => openUrl(link), + ), + ); } }); } diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart index c8b1afa..cd92b8c 100644 --- a/lib/constants/urls.dart +++ b/lib/constants/urls.dart @@ -2,6 +2,6 @@ class Urls { static const String playStore = "https://play.google.com/store/apps/details?id=com.jgeek00.adguard_home_manager"; static const String gitHub = "https://github.com/JGeek00/adguard-home-manager"; static const String customRuleDocs = "https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters"; - static const String checkLatestReleaseUrl = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases/latest"; + static const String getReleasesGitHub = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases"; static const String adGuardHomeReleasesTags = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/tags"; } \ No newline at end of file diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart new file mode 100644 index 0000000..e5244fe --- /dev/null +++ b/lib/functions/check_app_updates.dart @@ -0,0 +1,51 @@ +import 'dart:io'; +import 'dart:math'; + +import 'package:store_checker/store_checker.dart'; + +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/models/github_release.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; + +Future checkAppUpdates({ + required String appVersion, + required void Function(GitHubRelease?) setUpdateAvailable, + required Source installationSource +}) async { + final result = await checkAppUpdatesGitHub(); + + if (result['result'] == 'success') { + final update = gitHubUpdateExists(appVersion, result['body']); + + if (update == true) { + final release = appVersion.contains('beta') + ? result['body'].firstWhere((release) => release.prerelease == true) + : result['body'].firstWhere((release) => release.prerelease == false); + + setUpdateAvailable(release); + + if (Platform.isAndroid) { + if ( + installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || + installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || + installationSource == Source.UNKNOWN + ) { + return release; + } + else { + return null; + } + } + else if (Platform.isIOS) { + return null; + } + else { + return release; + } + } + else { + setUpdateAvailable(null); + } + } + return null; +} \ No newline at end of file diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index b28bf65..e10662a 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -1,5 +1,7 @@ import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:adguard_home_manager/models/github_release.dart'; + bool compareVersions({ required String currentVersion, required String newVersion @@ -147,20 +149,52 @@ bool serverVersionIsAhead({ } } -bool gitHubUpdateExists(String appVersion, String gitHubVersion) { - final List appVersionSplit = List.from(appVersion.split('.').map((e) => int.parse(e))); - final List gitHubVersionSplit = List.from(gitHubVersion.split('.').map((e) => int.parse(e))); +bool gitHubUpdateExists(String appVersion, List gitHubReleases) { + if (appVersion.contains('beta')) { + final gitHubVersion = gitHubReleases.firstWhere((release) => release.prerelease == true).tagName; - if (gitHubVersionSplit[0] > appVersionSplit[0]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] > appVersionSplit[1]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] > appVersionSplit[2]) { - return true; + final appBetaSplit = appVersion.split('-'); + final gitHubBetaSplit = gitHubVersion.split('-'); + + final List appVersionSplit = List.from(appBetaSplit[0].split('.').map((e) => int.parse(e))); + final int appBetaNumber = int.parse(appBetaSplit[1].split('.')[1]); + + final List gitHubVersionSplit = List.from(gitHubBetaSplit[0].split('.').map((e) => int.parse(e))); + final int gitHubBetaNumber = int.parse(gitHubBetaSplit[1].split('.')[1]); + + if (gitHubVersionSplit[0] > appVersionSplit[0]) { + return true; + } + else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] > appVersionSplit[1]) { + return true; + } + else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] > appVersionSplit[2]) { + return true; + } + else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] == appVersionSplit[2] && gitHubBetaNumber > appBetaNumber) { + return true; + } + else { + return false; + } } else { - return false; + final gitHubVersion = gitHubReleases.firstWhere((release) => release.prerelease == false).tagName; + + final List appVersionSplit = List.from(appVersion.split('.').map((e) => int.parse(e))); + final List gitHubVersionSplit = List.from(gitHubVersion.split('.').map((e) => int.parse(e))); + + if (gitHubVersionSplit[0] > appVersionSplit[0]) { + return true; + } + else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] > appVersionSplit[1]) { + return true; + } + else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] > appVersionSplit[2]) { + return true; + } + else { + return false; + } } } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 6fa26e1..4dcd872 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -239,7 +239,7 @@ class _MainState extends State
{ child: child!, ); }, - home: Base(appConfigProvider: appConfigProvider), + home: const Base(), ), ); } diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 0f8096d..7aeb917 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -199,7 +199,7 @@ class AppConfigProvider with ChangeNotifier { } } - void setAppUpdatesAvailable(GitHubRelease value) { + void setAppUpdatesAvailable(GitHubRelease? value) { _appUpdatesAvailable = value; notifyListeners(); } diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index 792d463..718bda7 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -2,20 +2,19 @@ import 'dart:io'; -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:store_checker/store_checker.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.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/check_app_updates.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/functions/app_update_download_link.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; class GeneralSettings extends StatefulWidget { const GeneralSettings({Key? key}) : super(key: key); @@ -56,16 +55,15 @@ class _GeneralSettingsState extends State { Future checkUpdatesAvailable() async { setState(() => appUpdatesStatus = AppUpdatesStatus.checking); - final result = await checkAppUpdatesGitHub(); - if (result['result'] == 'success') { - final update = gitHubUpdateExists(appConfigProvider.getAppInfo!.version, result['body'].tagName); - if (update == true) { - appConfigProvider.setAppUpdatesAvailable(result['body']); - setState(() => appUpdatesStatus = AppUpdatesStatus.available); - } - else { - setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); - } + + final res = await checkAppUpdates( + appVersion: appConfigProvider.getAppInfo!.version, + setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, + installationSource: appConfigProvider.installationSource + ); + + if (res != null) { + setState(() => appUpdatesStatus = AppUpdatesStatus.available); } else { setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); @@ -210,8 +208,7 @@ class _GeneralSettingsState extends State { appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || appConfigProvider.installationSource == Source.UNKNOWN - )) && - !appConfigProvider.getAppInfo!.version.contains('beta') + )) ) ...[ SectionLabel(label: AppLocalizations.of(context)!.application), CustomListTile( diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 2cf9820..4d129ae 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -2204,7 +2204,7 @@ class ApiClient { Future checkAppUpdatesGitHub() async { try { HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.checkLatestReleaseUrl)); + HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getReleasesGitHub)); HttpClientResponse response = await request.close(); String reply = await response.transform(utf8.decoder).join(); httpClient.close(); @@ -2214,7 +2214,7 @@ Future checkAppUpdatesGitHub() async { 'hasResponse': true, 'error': false, 'statusCode': response.statusCode, - 'body': GitHubRelease.fromJson(jsonDecode(reply)) + 'body': List.from(jsonDecode(reply).map((entry) => GitHubRelease.fromJson(entry))) }; } else { From bb5c4c242f4dfd0e51b9a944e8b6fb247e836b53 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 21:14:43 +0200 Subject: [PATCH 162/676] Removed import --- lib/functions/check_app_updates.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart index e5244fe..2063f20 100644 --- a/lib/functions/check_app_updates.dart +++ b/lib/functions/check_app_updates.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'dart:math'; import 'package:store_checker/store_checker.dart'; From 6f05f8eb40372fb2019c740d99fbf9c62f752d73 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 May 2023 22:37:47 +0200 Subject: [PATCH 163/676] Updated android and macos version --- macos/Runner.xcodeproj/project.pbxproj | 12 ++++++------ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 5bf52bf..03d00fd 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 61; + CURRENT_PROJECT_VERSION = 63; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.4.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 61; + CURRENT_PROJECT_VERSION = 63; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.4.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 61; + CURRENT_PROJECT_VERSION = 63; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.4.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; diff --git a/pubspec.yaml b/pubspec.yaml index ccebd1f..09715b6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.4.0-beta.1+62 +version: 2.4.0-beta.2+63 environment: sdk: '>=2.18.1 <3.0.0' From f01e219ebef55cb23fc2d99fcee920da8df09ef4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 02:28:11 +0200 Subject: [PATCH 164/676] Created GitHub actions workflow --- .github/workflows/release.yaml | 43 ++++++++++++++++++++++++++++++++++ android/app/build.gradle | 19 ++++++++++++--- pubspec.yaml | 2 +- 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..d773e0e --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,43 @@ +name: Release build + +on: + workflow_dispatch: + inputs: + version: + description: "Version number" + default: "1.0.0+1" +jobs: + build: + name: Build APK and Create release + needs: [version] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Update version in YAML + run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}/g' pubspec.yaml + - name: Update KeyStore password in gradle properties + run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties + - name: Update KeyStore key password in gradle properties + run: sed -i 's/#{KEYSTORE_KEY_PASS}#/${{ secrets.KEYSTORE_KEY_PASS }}/g' android/key.properties + - uses: actions/setup-java@v1 + with: + java-version: "18.x" + - uses: subosito/flutter-action@v1 + with: + channel: "stable" + - run: flutter clean + - run: flutter pub get + - run: flutter build apk --release + - run: flutter build appbundle --release + - name: Create a Release in GitHub + uses: ncipollo/release-action@v1 + with: + artifacts: "build/app/outputs/apk/release/*.apk,build/app/outputs/bundle/release/app-release.aab" + token: ${{ secrets.GH_TOKEN }} + tag: ${{ steps.version.outputs.content }} + commit: ${{ github.sha }} + - name: Upload app bundle + uses: actions/upload-artifact@v2 + with: + name: appbundle + path: build/app/outputs/bundle/release/app-release.aab \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index d93673c..099c059 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -25,6 +25,12 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + android { compileSdkVersion 33 ndkVersion flutter.ndkVersion @@ -53,11 +59,18 @@ android { versionName flutterVersionName } + signingConfigs { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } + buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + signingConfig signingConfigs.release } } } diff --git a/pubspec.yaml b/pubspec.yaml index 5f2b61d..6f3b2dc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.3.2+61 +version: 99.99.99+99 environment: sdk: '>=2.18.1 <3.0.0' From dbe43e05740a7393673ca2dec7cba40757f1f758 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 02:31:47 +0200 Subject: [PATCH 165/676] Removed version dependency --- .github/workflows/release.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d773e0e..9e4bcce 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,7 +9,6 @@ on: jobs: build: name: Build APK and Create release - needs: [version] runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 From 95386cca7f6ea14f40a8d1b5f7a8dfe773e43d09 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 03:14:54 +0200 Subject: [PATCH 166/676] Keystore annd properties on base64 --- .github/workflows/release.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9e4bcce..c71180c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -12,6 +12,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 + - name: Decode android/keystore.jks + run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/keystore.jks + - name: Decode android/key.properties + run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - name: Update version in YAML run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}/g' pubspec.yaml - name: Update KeyStore password in gradle properties From 81116f390d18823cb89759edf88f42c237beee3b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 03:25:15 +0200 Subject: [PATCH 167/676] Added env --- .github/workflows/release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c71180c..919192d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,6 +16,8 @@ jobs: run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/keystore.jks - name: Decode android/key.properties run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties + - name: Decode .env + run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Update version in YAML run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}/g' pubspec.yaml - name: Update KeyStore password in gradle properties From 7c3b9f17289de6795d285097ce7902c7325faa1f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 03:36:03 +0200 Subject: [PATCH 168/676] Changed keystore path --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 919192d..57207e2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Decode android/keystore.jks - run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/keystore.jks + run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/app/keystore.jks - name: Decode android/key.properties run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - name: Decode .env From b9d97f392893e0b141d6f33916738d9fd606ac84 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 03:46:09 +0200 Subject: [PATCH 169/676] Changed keystore name --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 57207e2..c4f7054 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - name: Decode android/keystore.jks + - name: Decode android/app/keystore.jks run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/app/keystore.jks - name: Decode android/key.properties run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties From 6e892284939a16168f63d8a9feaf31cec3fc74aa Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 09:31:21 +0200 Subject: [PATCH 170/676] Separated build number field --- .github/workflows/release.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c4f7054..18c4792 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -4,8 +4,11 @@ on: workflow_dispatch: inputs: version: - description: "Version number" - default: "1.0.0+1" + description: "Version" + default: "1.0.0" + number: + description: "Build number" + default: "1" jobs: build: name: Build APK and Create release @@ -19,7 +22,7 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Update version in YAML - run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}/g' pubspec.yaml + run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties @@ -39,7 +42,7 @@ jobs: with: artifacts: "build/app/outputs/apk/release/*.apk,build/app/outputs/bundle/release/app-release.aab" token: ${{ secrets.GH_TOKEN }} - tag: ${{ steps.version.outputs.content }} + tag: ${{ github.event.inputs.version }} commit: ${{ github.sha }} - name: Upload app bundle uses: actions/upload-artifact@v2 From 620a6472fff57da74431999970a8a995ed62ddbd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 09:55:29 +0200 Subject: [PATCH 171/676] Rename resulting files --- .github/workflows/release.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 18c4792..d6a2160 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,7 +14,7 @@ jobs: name: Build APK and Create release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - name: Decode android/app/keystore.jks run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/app/keystore.jks - name: Decode android/key.properties @@ -37,10 +37,14 @@ jobs: - run: flutter pub get - run: flutter build apk --release - run: flutter build appbundle --release + - name: Rename apk + run: mv build/app/outputs/apk/release/app-release.apk build/app/outputs/apk/release/AdGuardHomeManager_{{ github.event.inputs.version }}_Android.apk + - name: Rename aab + run: mv build/app/outputs/apk/release/app-release.aab build/app/outputs/apk/release/AdGuardHomeManager_{{ github.event.inputs.version }}_Android.aab - name: Create a Release in GitHub uses: ncipollo/release-action@v1 with: - artifacts: "build/app/outputs/apk/release/*.apk,build/app/outputs/bundle/release/app-release.aab" + artifacts: "build/app/outputs/apk/release/AdGuardHomeManager_{{ github.event.inputs.version }}_Android.apk,build/app/outputs/bundle/release/AdGuardHomeManager_{{ github.event.inputs.version }}_Android.aab" token: ${{ secrets.GH_TOKEN }} tag: ${{ github.event.inputs.version }} commit: ${{ github.sha }} From 1eb5d5c5e6492941dcece1d3e03a61a7190faed2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 10:16:51 +0200 Subject: [PATCH 172/676] Fixes --- .github/workflows/release.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d6a2160..e20c9b0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -38,13 +38,13 @@ jobs: - run: flutter build apk --release - run: flutter build appbundle --release - name: Rename apk - run: mv build/app/outputs/apk/release/app-release.apk build/app/outputs/apk/release/AdGuardHomeManager_{{ github.event.inputs.version }}_Android.apk + run: mv build/app/outputs/apk/release/app-release.apk build/app/outputs/apk/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - name: Rename aab - run: mv build/app/outputs/apk/release/app-release.aab build/app/outputs/apk/release/AdGuardHomeManager_{{ github.event.inputs.version }}_Android.aab + run: mv build/app/outputs/apk/release/app-release.aab build/app/outputs/apk/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - name: Create a Release in GitHub uses: ncipollo/release-action@v1 with: - artifacts: "build/app/outputs/apk/release/AdGuardHomeManager_{{ github.event.inputs.version }}_Android.apk,build/app/outputs/bundle/release/AdGuardHomeManager_{{ github.event.inputs.version }}_Android.aab" + artifacts: "build/app/outputs/apk/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk,build/app/outputs/bundle/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab" token: ${{ secrets.GH_TOKEN }} tag: ${{ github.event.inputs.version }} commit: ${{ github.sha }} From 88857945c3c04b4482df11552bf25a0cb77eb667 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 10:27:15 +0200 Subject: [PATCH 173/676] Fixed route --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e20c9b0..1f412ef 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -40,7 +40,7 @@ jobs: - name: Rename apk run: mv build/app/outputs/apk/release/app-release.apk build/app/outputs/apk/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - name: Rename aab - run: mv build/app/outputs/apk/release/app-release.aab build/app/outputs/apk/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + run: mv build/app/outputs/bundle/release/app-release.aab build/app/outputs/bundle/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - name: Create a Release in GitHub uses: ncipollo/release-action@v1 with: From 3cf72ec436e704f200777a481de8b94e4b341752 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 May 2023 15:15:34 +0200 Subject: [PATCH 174/676] Added conditions --- .github/workflows/release.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1f412ef..ab1bca3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -5,13 +5,20 @@ on: inputs: version: description: "Version" + required: true default: "1.0.0" number: description: "Build number" + required: true default: "1" + android: + description: "Build Android" + type: boolean + default: true jobs: build: - name: Build APK and Create release + name: Build APK and AAB + if: github.event.inputs.android == true runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 From 22ae994370c57ae30206e6c0fcb300fbc6fd8506 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 00:54:14 +0200 Subject: [PATCH 175/676] Added macos build --- .github/workflows/release.yaml | 35 +++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ab1bca3..1b69554 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,6 +15,10 @@ on: description: "Build Android" type: boolean default: true + macos: + description: "Build macOS" + type: boolean + default: true jobs: build: name: Build APK and AAB @@ -59,4 +63,33 @@ jobs: uses: actions/upload-artifact@v2 with: name: appbundle - path: build/app/outputs/bundle/release/app-release.aab \ No newline at end of file + path: build/app/outputs/bundle/release/app-release.aab + build: + name: Build macOS + if: github.event.inputs.macos == true + runs-on: macos-latest + steps: + - uses: actions/checkout@v3 + - uses: subosito/flutter-action@v1 + with: + channel: "stable" + - run: flutter clean + - run: flutter pub get + - run: flutter build macos --release + - name: Get into build dir + run: cd build/macos/Build/Products/Release + - name: Geneate build folder + run: mkdir AdGuard\ Home\ Manager + - name: Copy app into folder + run: cp AdGuard\ Home\ Manager.app AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app + - name: Generate symbolic link to Applications dir + run: ln -s /Applications AdGuard\ Home\ Manager + - name: Generate dmg + run: hdiutil create -srcfolder AdGuard\ Home\ Manager AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + - name: Create a Release in GitHub + uses: ncipollo/release-action@v1 + with: + artifacts: "AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" + token: ${{ secrets.GH_TOKEN }} + tag: ${{ github.event.inputs.version }} + commit: ${{ github.sha }} \ No newline at end of file From e09c929f17a29fd7ad17fbc16ed85a818cbb42bc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 00:55:32 +0200 Subject: [PATCH 176/676] Changed job name --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1b69554..73da265 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -20,7 +20,7 @@ on: type: boolean default: true jobs: - build: + build-and-release-android: name: Build APK and AAB if: github.event.inputs.android == true runs-on: ubuntu-latest @@ -64,7 +64,7 @@ jobs: with: name: appbundle path: build/app/outputs/bundle/release/app-release.aab - build: + build-and-release-macos: name: Build macOS if: github.event.inputs.macos == true runs-on: macos-latest From 82772246ecdb5d215f018ff7769008036c05ea08 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 01:02:50 +0200 Subject: [PATCH 177/676] Removed conditions --- .github/workflows/release.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 73da265..4cc988f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -22,7 +22,6 @@ on: jobs: build-and-release-android: name: Build APK and AAB - if: github.event.inputs.android == true runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -66,7 +65,6 @@ jobs: path: build/app/outputs/bundle/release/app-release.aab build-and-release-macos: name: Build macOS - if: github.event.inputs.macos == true runs-on: macos-latest steps: - uses: actions/checkout@v3 From cf5d92f3974778b4ca493a72628e32d6f613893a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 01:07:07 +0200 Subject: [PATCH 178/676] Removed checkboxes --- .github/workflows/release.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4cc988f..3ba1156 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -11,14 +11,6 @@ on: description: "Build number" required: true default: "1" - android: - description: "Build Android" - type: boolean - default: true - macos: - description: "Build macOS" - type: boolean - default: true jobs: build-and-release-android: name: Build APK and AAB From b5ffec64c3a65e7f251ff509f011d321c311b786 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 01:17:38 +0200 Subject: [PATCH 179/676] Add .env file --- .github/workflows/release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3ba1156..7c7db67 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -60,6 +60,8 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v3 + - name: Decode .env + run: echo "${{ secrets.ENV }}" | base64 --decode > .env - uses: subosito/flutter-action@v1 with: channel: "stable" From b4477bd79845b29db0bf025fccfa692c82c3c617 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 01:37:15 +0200 Subject: [PATCH 180/676] Update pubspec version and changed route --- .github/workflows/release.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7c7db67..aa021e4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -62,18 +62,20 @@ jobs: - uses: actions/checkout@v3 - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env + - name: Update version in YAML + run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml - uses: subosito/flutter-action@v1 with: channel: "stable" - run: flutter clean - run: flutter pub get - run: flutter build macos --release - - name: Get into build dir + - name: Get into Release directory run: cd build/macos/Build/Products/Release - - name: Geneate build folder + - name: Create folder to build dmg run: mkdir AdGuard\ Home\ Manager - name: Copy app into folder - run: cp AdGuard\ Home\ Manager.app AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app + run: cp -r ./AdGuard\ Home\ Manager.app ./AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app - name: Generate symbolic link to Applications dir run: ln -s /Applications AdGuard\ Home\ Manager - name: Generate dmg From 2294638185aae9f410bcb7291729d1261e5b1173 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 01:50:29 +0200 Subject: [PATCH 181/676] Fixed sed and changed dmg --- .github/workflows/release.yaml | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index aa021e4..0de3945 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -58,32 +58,41 @@ jobs: build-and-release-macos: name: Build macOS runs-on: macos-latest + env: + MACOS_APP_RELEASE_PATH: build/macos/Build/Products/Release steps: - uses: actions/checkout@v3 - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Update version in YAML - run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml + run: sed -i '' 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml - uses: subosito/flutter-action@v1 with: channel: "stable" - run: flutter clean - run: flutter pub get - run: flutter build macos --release - - name: Get into Release directory - run: cd build/macos/Build/Products/Release - - name: Create folder to build dmg - run: mkdir AdGuard\ Home\ Manager - - name: Copy app into folder - run: cp -r ./AdGuard\ Home\ Manager.app ./AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app - - name: Generate symbolic link to Applications dir - run: ln -s /Applications AdGuard\ Home\ Manager - - name: Generate dmg - run: hdiutil create -srcfolder AdGuard\ Home\ Manager AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + - name: Create a dmg + run: | + echo "Install create-dmg" + brew install create-dmg + cd $MACOS_APP_RELEASE_PATH + create-dmg \ + --volname "AdGuard Home Manager" \ + --window-pos 200 120 \ + --window-size 800 529 \ + --icon-size 130 \ + --text-size 14 \ + --icon "AdGuard Home Manager.app" 260 250 \ + --hide-extension "AdGuard Home Manager.app" \ + --app-drop-link 540 250 \ + --hdiutil-quiet \ + "AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" \ + AdGuard Home Manager.app" - name: Create a Release in GitHub uses: ncipollo/release-action@v1 with: - artifacts: "AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" + artifacts: "$MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" token: ${{ secrets.GH_TOKEN }} tag: ${{ github.event.inputs.version }} commit: ${{ github.sha }} \ No newline at end of file From f625f529cd2f706cbcf09745f3249236b072bbf6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 02:09:33 +0200 Subject: [PATCH 182/676] Changed build dmg --- .github/workflows/release.yaml | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0de3945..3962b18 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -72,27 +72,20 @@ jobs: - run: flutter clean - run: flutter pub get - run: flutter build macos --release - - name: Create a dmg - run: | - echo "Install create-dmg" - brew install create-dmg - cd $MACOS_APP_RELEASE_PATH - create-dmg \ - --volname "AdGuard Home Manager" \ - --window-pos 200 120 \ - --window-size 800 529 \ - --icon-size 130 \ - --text-size 14 \ - --icon "AdGuard Home Manager.app" 260 250 \ - --hide-extension "AdGuard Home Manager.app" \ - --app-drop-link 540 250 \ - --hdiutil-quiet \ - "AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" \ - AdGuard Home Manager.app" + - name: Get into Release directory + run: cd $MACOS_APP_RELEASE_PATH + - name: Create folder to build dmg + run: mkdir AdGuard\ Home\ Manager + - name: Copy app into folder + run: cp -r ./AdGuard\ Home\ Manager.app ./AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app + - name: Generate symbolic link to Applications dir + run: ln -s /Applications AdGuard\ Home\ Manager + - name: Generate dmg + run: hdiutil create -srcfolder AdGuard\ Home\ Manager AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - name: Create a Release in GitHub uses: ncipollo/release-action@v1 with: - artifacts: "$MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" + artifacts: "AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" token: ${{ secrets.GH_TOKEN }} tag: ${{ github.event.inputs.version }} commit: ${{ github.sha }} \ No newline at end of file From c91575038c6a6c83c97171357bc9251a18fb8341 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 02:22:52 +0200 Subject: [PATCH 183/676] Test --- .github/workflows/release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3962b18..aecad06 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -76,6 +76,8 @@ jobs: run: cd $MACOS_APP_RELEASE_PATH - name: Create folder to build dmg run: mkdir AdGuard\ Home\ Manager + - name: dir + run: pwd & ls - name: Copy app into folder run: cp -r ./AdGuard\ Home\ Manager.app ./AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app - name: Generate symbolic link to Applications dir From 38bff906f623abf2bcf2f6b9a3113591ee606e43 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 02:34:49 +0200 Subject: [PATCH 184/676] Fixed routes --- .github/workflows/release.yaml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index aecad06..8edf8f0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -72,22 +72,18 @@ jobs: - run: flutter clean - run: flutter pub get - run: flutter build macos --release - - name: Get into Release directory - run: cd $MACOS_APP_RELEASE_PATH - name: Create folder to build dmg - run: mkdir AdGuard\ Home\ Manager - - name: dir - run: pwd & ls + run: mkdir $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager - name: Copy app into folder - run: cp -r ./AdGuard\ Home\ Manager.app ./AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app + run: cp -r $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager.app $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app - name: Generate symbolic link to Applications dir - run: ln -s /Applications AdGuard\ Home\ Manager + run: ln -s /Applications $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager - name: Generate dmg - run: hdiutil create -srcfolder AdGuard\ Home\ Manager AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - name: Create a Release in GitHub uses: ncipollo/release-action@v1 with: - artifacts: "AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" + artifacts: "$MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" token: ${{ secrets.GH_TOKEN }} tag: ${{ github.event.inputs.version }} commit: ${{ github.sha }} \ No newline at end of file From ce3d664e5c9ef3f88a53d1de57d4b99f8486b9ec Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 02:50:48 +0200 Subject: [PATCH 185/676] Upload release --- .github/workflows/release.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8edf8f0..7d180aa 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -86,4 +86,9 @@ jobs: artifacts: "$MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" token: ${{ secrets.GH_TOKEN }} tag: ${{ github.event.inputs.version }} - commit: ${{ github.sha }} \ No newline at end of file + commit: ${{ github.sha }} + - name: Upload release + uses: actions/upload-artifact@v2 + with: + name: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + path: $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg \ No newline at end of file From cc346b7dc8a86cf290696127a54f8055b98be9c5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 03:08:16 +0200 Subject: [PATCH 186/676] Changed push build --- .github/workflows/release.yaml | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7d180aa..aedec6d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -80,15 +80,25 @@ jobs: run: ln -s /Applications $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager - name: Generate dmg run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - - name: Create a Release in GitHub - uses: ncipollo/release-action@v1 + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} with: - artifacts: "$MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg" - token: ${{ secrets.GH_TOKEN }} - tag: ${{ github.event.inputs.version }} - commit: ${{ github.sha }} - - name: Upload release - uses: actions/upload-artifact@v2 + tag_name: ${{ github.event.inputs.version }} + release_name: v${{ steps.versions.outputs.version }} + body: | + Release Notes + draft: false + prerelease: false + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} with: - name: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - path: $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg \ No newline at end of file + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + asset_name: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + asset_content_type: application/octet-stream \ No newline at end of file From 07c205fdd7ad6efd009a1eabeecf30958eee207a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 03:26:27 +0200 Subject: [PATCH 187/676] Changes --- .github/workflows/release.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index aedec6d..c5076c8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -87,11 +87,13 @@ jobs: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} with: tag_name: ${{ github.event.inputs.version }} - release_name: v${{ steps.versions.outputs.version }} + release_name: v${{ github.event.inputs.version }} body: | Release Notes draft: false prerelease: false + - name: file + run: ls $MACOS_APP_RELEASE_PATH - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 From 3a33f6ddbe07ec319c791c0c5e55708e9c799374 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 03:43:27 +0200 Subject: [PATCH 188/676] Change path --- .github/workflows/release.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c5076c8..f56e288 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -80,6 +80,8 @@ jobs: run: ln -s /Applications $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager - name: Generate dmg run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + - name: Copy dmg to project root + run: cp $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - name: Create Release id: create_release uses: actions/create-release@v1 @@ -94,6 +96,8 @@ jobs: prerelease: false - name: file run: ls $MACOS_APP_RELEASE_PATH + - name: file root + run: ls - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 @@ -101,6 +105,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + asset_path: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg asset_name: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg asset_content_type: application/octet-stream \ No newline at end of file From 46f1ac3513448e3021a69df8dc0f65caad7f7a55 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 04:03:36 +0200 Subject: [PATCH 189/676] Changed android routes --- .github/workflows/release.yaml | 56 +++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f56e288..7837870 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -13,8 +13,10 @@ on: default: "1" jobs: build-and-release-android: - name: Build APK and AAB + name: Build Android APK and AAB runs-on: ubuntu-latest + env: + ANDROID_APP_RELEASE_PATH: build/app/outputs/apk/release steps: - uses: actions/checkout@v3 - name: Decode android/app/keystore.jks @@ -40,21 +42,45 @@ jobs: - run: flutter build apk --release - run: flutter build appbundle --release - name: Rename apk - run: mv build/app/outputs/apk/release/app-release.apk build/app/outputs/apk/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + run: mv $ANDROID_APP_RELEASE_PATH/app-release.apk $ANDROID_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - name: Rename aab - run: mv build/app/outputs/bundle/release/app-release.aab build/app/outputs/bundle/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - - name: Create a Release in GitHub - uses: ncipollo/release-action@v1 + run: mv $ANDROID_APP_RELEASE_PATH/app-release.aab $ANDROID_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + - name: Copy apk to project root + run: cp $ANDROID_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + - name: Copy aab to project root + run: cp $ANDROID_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} with: - artifacts: "build/app/outputs/apk/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk,build/app/outputs/bundle/release/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab" - token: ${{ secrets.GH_TOKEN }} - tag: ${{ github.event.inputs.version }} - commit: ${{ github.sha }} - - name: Upload app bundle - uses: actions/upload-artifact@v2 + tag_name: ${{ github.event.inputs.version }} + release_name: v${{ github.event.inputs.version }} + body: | + Release Notes + draft: false + prerelease: false + - name: Upload aab + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} with: - name: appbundle - path: build/app/outputs/bundle/release/app-release.aab + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + asset_name: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + asset_content_type: application/octet-stream + - name: Upload apk + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + asset_name: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + asset_content_type: application/octet-stream build-and-release-macos: name: Build macOS runs-on: macos-latest @@ -94,10 +120,6 @@ jobs: Release Notes draft: false prerelease: false - - name: file - run: ls $MACOS_APP_RELEASE_PATH - - name: file root - run: ls - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 From 27b2f9b6abac63d783994ec6ece942d6fe311e77 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 04:05:05 +0200 Subject: [PATCH 190/676] Fixed issues --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7837870..a2bbdc5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -62,7 +62,7 @@ jobs: draft: false prerelease: false - name: Upload aab - id: upload-release-asset + id: upload-aab uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} @@ -72,7 +72,7 @@ jobs: asset_name: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab asset_content_type: application/octet-stream - name: Upload apk - id: upload-release-asset + id: upload-apk uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} From 54eecfcebca3417461bd3e51c466c0531097f6e4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 04:19:32 +0200 Subject: [PATCH 191/676] Fixed android routes --- .github/workflows/release.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a2bbdc5..a5133f8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,7 +16,8 @@ jobs: name: Build Android APK and AAB runs-on: ubuntu-latest env: - ANDROID_APP_RELEASE_PATH: build/app/outputs/apk/release + ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release + ANDROID_APK_RELEASE_PATH: build/app/outputs/apk/release steps: - uses: actions/checkout@v3 - name: Decode android/app/keystore.jks @@ -42,13 +43,13 @@ jobs: - run: flutter build apk --release - run: flutter build appbundle --release - name: Rename apk - run: mv $ANDROID_APP_RELEASE_PATH/app-release.apk $ANDROID_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - name: Rename aab - run: mv $ANDROID_APP_RELEASE_PATH/app-release.aab $ANDROID_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - name: Copy apk to project root - run: cp $ANDROID_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - name: Copy aab to project root - run: cp $ANDROID_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - name: Create Release id: create_release uses: actions/create-release@v1 From 8ef4a935f8baf87db3bf51796ce486da1f1f4eaa Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 13:35:24 +0200 Subject: [PATCH 192/676] Added check if tag exists --- .github/workflows/release.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a5133f8..ddfb42b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -50,7 +50,14 @@ jobs: run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - name: Copy aab to project root run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + - name: Check if tag exists + uses: mukunku/tag-exists-action@v1.2.0 + id: checkTag + with: + github_token: ${{ secrets.GH_TOKEN }} + tag: ${{ github.event.inputs.version }} - name: Create Release + if: steps.checkTag.outputs.exists == false id: create_release uses: actions/create-release@v1 env: @@ -109,7 +116,14 @@ jobs: run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - name: Copy dmg to project root run: cp $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + - name: Check if tag exists + uses: mukunku/tag-exists-action@v1.2.0 + id: checkTag + with: + github_token: ${{ secrets.GH_TOKEN }} + tag: ${{ github.event.inputs.version }} - name: Create Release + if: steps.checkTag.outputs.exists == false id: create_release uses: actions/create-release@v1 env: From c3207724fd93fb58fcf35a1b4197e40f14740ae2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 13:52:58 +0200 Subject: [PATCH 193/676] Changed release --- .github/workflows/release.yaml | 80 ++++++++-------------------------- 1 file changed, 18 insertions(+), 62 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ddfb42b..6f345df 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -50,45 +50,19 @@ jobs: run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - name: Copy aab to project root run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - - name: Check if tag exists - uses: mukunku/tag-exists-action@v1.2.0 - id: checkTag - with: - github_token: ${{ secrets.GH_TOKEN }} - tag: ${{ github.event.inputs.version }} - - name: Create Release - if: steps.checkTag.outputs.exists == false - id: create_release - uses: actions/create-release@v1 + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + draft: false + prerelease: false + name: v${{ github.event.inputs.version }} + tag_name: ${{ github.event.inputs.version }} with: - tag_name: ${{ github.event.inputs.version }} - release_name: v${{ github.event.inputs.version }} - body: | - Release Notes - draft: false - prerelease: false - - name: Upload aab - id: upload-aab - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - asset_name: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - asset_content_type: application/octet-stream - - name: Upload apk - id: upload-apk - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - asset_name: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - asset_content_type: application/octet-stream + files: | + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk build-and-release-macos: name: Build macOS runs-on: macos-latest @@ -116,32 +90,14 @@ jobs: run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - name: Copy dmg to project root run: cp $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - - name: Check if tag exists - uses: mukunku/tag-exists-action@v1.2.0 - id: checkTag - with: - github_token: ${{ secrets.GH_TOKEN }} - tag: ${{ github.event.inputs.version }} - - name: Create Release - if: steps.checkTag.outputs.exists == false - id: create_release - uses: actions/create-release@v1 + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + draft: false + prerelease: false + name: v${{ github.event.inputs.version }} + tag_name: ${{ github.event.inputs.version }} with: - tag_name: ${{ github.event.inputs.version }} - release_name: v${{ github.event.inputs.version }} - body: | - Release Notes - draft: false - prerelease: false - - name: Upload Release Asset - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - asset_name: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - asset_content_type: application/octet-stream \ No newline at end of file + files: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg \ No newline at end of file From 36667469247f41ec7fd5e1838840cc3c5f3ee5e9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 13:55:18 +0200 Subject: [PATCH 194/676] Fixes --- .github/workflows/release.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6f345df..ad5179d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -55,11 +55,11 @@ jobs: if: startsWith(github.ref, 'refs/tags/') env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - draft: false - prerelease: false - name: v${{ github.event.inputs.version }} - tag_name: ${{ github.event.inputs.version }} with: + draft: false + prerelease: false + name: v${{ github.event.inputs.version }} + tag_name: ${{ github.event.inputs.version }} files: | AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk @@ -95,9 +95,9 @@ jobs: if: startsWith(github.ref, 'refs/tags/') env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - draft: false - prerelease: false - name: v${{ github.event.inputs.version }} - tag_name: ${{ github.event.inputs.version }} with: + draft: false + prerelease: false + name: v${{ github.event.inputs.version }} + tag_name: ${{ github.event.inputs.version }} files: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg \ No newline at end of file From 602acd2189ee55ebfd3818e05a17f76ed5c28d1e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 14:18:48 +0200 Subject: [PATCH 195/676] Updated versions --- .github/workflows/release.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ad5179d..b0bd3bf 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -32,10 +32,10 @@ jobs: run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties run: sed -i 's/#{KEYSTORE_KEY_PASS}#/${{ secrets.KEYSTORE_KEY_PASS }}/g' android/key.properties - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: java-version: "18.x" - - uses: subosito/flutter-action@v1 + - uses: subosito/flutter-action@v2 with: channel: "stable" - run: flutter clean @@ -74,7 +74,7 @@ jobs: run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Update version in YAML run: sed -i '' 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml - - uses: subosito/flutter-action@v1 + - uses: subosito/flutter-action@v2 with: channel: "stable" - run: flutter clean From 76f4b2825649ac856e45bb1956f4a14641edb9e6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 14:21:34 +0200 Subject: [PATCH 196/676] Changed some titles and fixed java action --- .github/workflows/release.yaml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b0bd3bf..49ebef6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,4 +1,4 @@ -name: Release build +name: Compile and release production build on: workflow_dispatch: @@ -13,7 +13,7 @@ on: default: "1" jobs: build-and-release-android: - name: Build Android APK and AAB + name: Build Android .apk and .aab runs-on: ubuntu-latest env: ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release @@ -34,7 +34,8 @@ jobs: run: sed -i 's/#{KEYSTORE_KEY_PASS}#/${{ secrets.KEYSTORE_KEY_PASS }}/g' android/key.properties - uses: actions/setup-java@v2 with: - java-version: "18.x" + distribution: 'zulu' + java-version: '18.x' - uses: subosito/flutter-action@v2 with: channel: "stable" @@ -64,7 +65,7 @@ jobs: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk build-and-release-macos: - name: Build macOS + name: Build macOS .dmg runs-on: macos-latest env: MACOS_APP_RELEASE_PATH: build/macos/Build/Products/Release From 1c0e4629a20c2a9555d3a259742a7746503867dd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 14:35:29 +0200 Subject: [PATCH 197/676] Separate release --- .github/workflows/release.yaml | 56 +++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 49ebef6..e669a67 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -12,7 +12,7 @@ on: required: true default: "1" jobs: - build-and-release-android: + build-android: name: Build Android .apk and .aab runs-on: ubuntu-latest env: @@ -51,20 +51,14 @@ jobs: run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - name: Copy aab to project root run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - - name: Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + - name: Upload artifact + uses: actions/upload-artifact@v3 with: - draft: false - prerelease: false - name: v${{ github.event.inputs.version }} - tag_name: ${{ github.event.inputs.version }} - files: | + name: android + path: | AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - build-and-release-macos: + build-macos: name: Build macOS .dmg runs-on: macos-latest env: @@ -91,14 +85,32 @@ jobs: run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - name: Copy dmg to project root run: cp $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - - name: Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + - name: Upload artifact + uses: actions/upload-artifact@v3 with: - draft: false - prerelease: false - name: v${{ github.event.inputs.version }} - tag_name: ${{ github.event.inputs.version }} - files: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg \ No newline at end of file + name: macos + path: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + release-builds: + needs: [build-android, build-macos] + - uses: actions/checkout@v3 + - uses: actions/download-artifact@v3 + - name: Download Android artifacts + with: + name: android + - name: Download macOS artifacts + with: + name: macos + - name: Release to GitHub + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + with: + draft: false + prerelease: false + name: v${{ github.event.inputs.version }} + tag_name: ${{ github.event.inputs.version }} + files: | + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg \ No newline at end of file From 04df55865ff60ded5865e0820c523c8c2b6e119c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 14:37:34 +0200 Subject: [PATCH 198/676] Fixed job --- .github/workflows/release.yaml | 49 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e669a67..b04cea1 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -90,27 +90,30 @@ jobs: with: name: macos path: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg - release-builds: + release-builds-github: + name: Release builds to GitHub + runs-on: ubuntu-latest needs: [build-android, build-macos] - - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 - - name: Download Android artifacts - with: - name: android - - name: Download macOS artifacts - with: - name: macos - - name: Release to GitHub - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - with: - draft: false - prerelease: false - name: v${{ github.event.inputs.version }} - tag_name: ${{ github.event.inputs.version }} - files: | - AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg \ No newline at end of file + steps: + - uses: actions/checkout@v3 + - uses: actions/download-artifact@v3 + - name: Download Android artifacts + with: + name: android + - name: Download macOS artifacts + with: + name: macos + - name: Release to GitHub + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + with: + draft: false + prerelease: false + name: v${{ github.event.inputs.version }} + tag_name: ${{ github.event.inputs.version }} + files: | + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg \ No newline at end of file From cfba2dc96bb03276f12fb1b75e9fe1dac4b4ed84 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 14:39:14 +0200 Subject: [PATCH 199/676] Fixed job --- .github/workflows/release.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b04cea1..007de10 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -96,11 +96,12 @@ jobs: needs: [build-android, build-macos] steps: - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 - name: Download Android artifacts + uses: actions/download-artifact@v3 with: name: android - name: Download macOS artifacts + uses: actions/download-artifact@v3 with: name: macos - name: Release to GitHub From beb7960874bff448f1bc9dd1e3d8986510116e50 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 14:58:29 +0200 Subject: [PATCH 200/676] Changed release --- .github/workflows/release.yaml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 007de10..791b52d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -32,7 +32,7 @@ jobs: run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties run: sed -i 's/#{KEYSTORE_KEY_PASS}#/${{ secrets.KEYSTORE_KEY_PASS }}/g' android/key.properties - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v3 with: distribution: 'zulu' java-version: '18.x' @@ -96,25 +96,25 @@ jobs: needs: [build-android, build-macos] steps: - uses: actions/checkout@v3 + - name: Create builds directory + run: mkdir releases - name: Download Android artifacts uses: actions/download-artifact@v3 with: name: android + path: releases/ - name: Download macOS artifacts uses: actions/download-artifact@v3 with: name: macos + path: releases/ - name: Release to GitHub - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + uses: ncipollo/release-action@v1 with: + artifacts: "releases/*" + token: ${{ secrets.GH_TOKEN }} + tag: ${{ github.event.inputs.version }} + name: v${{ github.event.inputs.version }} draft: false prerelease: false - name: v${{ github.event.inputs.version }} - tag_name: ${{ github.event.inputs.version }} - files: | - AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk - AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg \ No newline at end of file + commit: ${{ github.sha }} \ No newline at end of file From 177848530fb71d5d27e348187cd06cac85481285 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 19:40:56 +0200 Subject: [PATCH 201/676] Added linux job --- .github/workflows/release.yaml | 41 ++++++++++++++++++++++++++++++++++ debian/debian.yaml | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 791b52d..fecf2ca 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -90,6 +90,42 @@ jobs: with: name: macos path: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + build-linux: + name: Build Linux .tar.gz + runs-on: ubuntu-latest + env: + LINUX_APP_RELEASE_PATH: build/linux/x64/release/bundle + steps: + - uses: actions/checkout@v3 + - name: Decode .env + run: echo "${{ secrets.ENV }}" | base64 --decode > .env + - name: Update version in pubspec.yaml + run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml + - name: Update version in debian.yaml + run: sed -i 's//${{ github.event.inputs.version }}/g' debian/debian.yaml + - uses: subosito/flutter-action@v2 + with: + channel: "stable" + - run: flutter clean + - run: flutter pub get + - run: flutter build linux --release + - name: Install flutter_to_debian + run: dart pub global activate flutter_to_debian + - name: Generate .deb package + run: flutter_to_debian + - name: Move .deb package to project root + run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb + - name: Generate .tar.gz + run: tar -czaf AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz $LINUX_APP_RELEASE_PATH/* + - name: Move .tar.gz package to project root + run: mv $LINUX_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: linux + path: | + AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb + AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz release-builds-github: name: Release builds to GitHub runs-on: ubuntu-latest @@ -108,6 +144,11 @@ jobs: with: name: macos path: releases/ + - name: Download Linux artifacts + uses: actions/download-artifact@v3 + with: + name: linux + path: releases/ - name: Release to GitHub uses: ncipollo/release-action@v1 with: diff --git a/debian/debian.yaml b/debian/debian.yaml index 7adcb2a..876c66e 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.3.2 + Version: Architecture: amd64 Essential: no Priority: optional From 715a65619e573ab6da77ad16f30a97305f03f9de Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 19:42:03 +0200 Subject: [PATCH 202/676] Added linux build dependency --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fecf2ca..3d11408 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -129,7 +129,7 @@ jobs: release-builds-github: name: Release builds to GitHub runs-on: ubuntu-latest - needs: [build-android, build-macos] + needs: [build-android, build-macos, build-linux] steps: - uses: actions/checkout@v3 - name: Create builds directory From 8115408e3865b57012ea84a35e8aaef7a2bdbb8f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 19:47:48 +0200 Subject: [PATCH 203/676] Added install dependencies --- .github/workflows/release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3d11408..c9884c9 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -103,6 +103,8 @@ jobs: run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml - name: Update version in debian.yaml run: sed -i 's//${{ github.event.inputs.version }}/g' debian/debian.yaml + - name: Install dependencies + run: sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev - uses: subosito/flutter-action@v2 with: channel: "stable" From 1a0261330047b8b53afdb9deb2d6df6bc809b780 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 19:59:57 +0200 Subject: [PATCH 204/676] Removed move targz --- .github/workflows/release.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c9884c9..0951a5f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -119,8 +119,6 @@ jobs: run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb - name: Generate .tar.gz run: tar -czaf AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz $LINUX_APP_RELEASE_PATH/* - - name: Move .tar.gz package to project root - run: mv $LINUX_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz - name: Upload artifact uses: actions/upload-artifact@v3 with: From ff5517e90feaa3a9c421fa14e7204ece93b98298 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 20:17:30 +0200 Subject: [PATCH 205/676] Changed targz build route --- .github/workflows/release.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0951a5f..ec1a9ca 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -118,7 +118,8 @@ jobs: - name: Move .deb package to project root run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb - name: Generate .tar.gz - run: tar -czaf AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz $LINUX_APP_RELEASE_PATH/* + run: cd $LINUX_APP_RELEASE_PATH + run: tar -czaf AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz ./* - name: Upload artifact uses: actions/upload-artifact@v3 with: From 7dc0e53e72b83af6cc45e050927ae66d4072d038 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 20:21:43 +0200 Subject: [PATCH 206/676] Changed targz route --- .github/workflows/release.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ec1a9ca..98a7af9 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -117,9 +117,12 @@ jobs: run: flutter_to_debian - name: Move .deb package to project root run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb - - name: Generate .tar.gz + - name: Cd to build dir run: cd $LINUX_APP_RELEASE_PATH + - name: Generate .tar.gz run: tar -czaf AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz ./* + - name: Cd to root dir + run: cd ../../../../../ - name: Upload artifact uses: actions/upload-artifact@v3 with: From a7f11d596987921e1e2d99d53eb99fc2ff811ab6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 20:35:56 +0200 Subject: [PATCH 207/676] Changed .tar.gz generation --- .github/workflows/release.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 98a7af9..064beb0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -116,13 +116,14 @@ jobs: - name: Generate .deb package run: flutter_to_debian - name: Move .deb package to project root - run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb - - name: Cd to build dir - run: cd $LINUX_APP_RELEASE_PATH - - name: Generate .tar.gz - run: tar -czaf AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz ./* - - name: Cd to root dir - run: cd ../../../../../ + - name: Generate .tar.gz package + uses: a7ul/tar-action@v1.1.0 + id: compress + with: + command: c + cwd: $LINUX_APP_RELEASE_PATH + files: ./* + outPath: AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz - name: Upload artifact uses: actions/upload-artifact@v3 with: From 246e4a66e229c87754802d5487a5ab58d8c35c80 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 20:36:33 +0200 Subject: [PATCH 208/676] Fixes --- .github/workflows/release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 064beb0..b87911c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -116,6 +116,7 @@ jobs: - name: Generate .deb package run: flutter_to_debian - name: Move .deb package to project root + run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb - name: Generate .tar.gz package uses: a7ul/tar-action@v1.1.0 id: compress From bd75c789ff81744f4a6fb2802d661c6ac10938ab Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 20:37:03 +0200 Subject: [PATCH 209/676] Changed version --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b87911c..ec3e76b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -118,7 +118,7 @@ jobs: - name: Move .deb package to project root run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb - name: Generate .tar.gz package - uses: a7ul/tar-action@v1.1.0 + uses: a7ul/tar-action@v1.1.3 id: compress with: command: c From d0f5c1713d5cd2fb58a1f6b82659db75ce2897e9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 20:43:07 +0200 Subject: [PATCH 210/676] Changed route --- .github/workflows/release.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ec3e76b..36303f2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -93,8 +93,6 @@ jobs: build-linux: name: Build Linux .tar.gz runs-on: ubuntu-latest - env: - LINUX_APP_RELEASE_PATH: build/linux/x64/release/bundle steps: - uses: actions/checkout@v3 - name: Decode .env @@ -122,7 +120,7 @@ jobs: id: compress with: command: c - cwd: $LINUX_APP_RELEASE_PATH + cwd: build/linux/x64/release/bundle files: ./* outPath: AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz - name: Upload artifact From e10b4eb7df093215a74cede12c7c885d141b3838 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 20:57:21 +0200 Subject: [PATCH 211/676] Changed targz generation --- .github/workflows/release.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 36303f2..2437dc2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -121,7 +121,10 @@ jobs: with: command: c cwd: build/linux/x64/release/bundle - files: ./* + files: | + build/linux/x64/release/bundle/data + build/linux/x64/release/bundle/lib + build/linux/x64/release/bundle/AdGuardHomeManager outPath: AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz - name: Upload artifact uses: actions/upload-artifact@v3 From e299ddadd2da71daa13d160aadba106db5cc109a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 21:06:09 +0200 Subject: [PATCH 212/676] Changed routes --- .github/workflows/release.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2437dc2..427c5f9 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -115,6 +115,8 @@ jobs: run: flutter_to_debian - name: Move .deb package to project root run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb + - name: build dir + run: ls build/linux/x64/release/bundle - name: Generate .tar.gz package uses: a7ul/tar-action@v1.1.3 id: compress @@ -122,9 +124,9 @@ jobs: command: c cwd: build/linux/x64/release/bundle files: | - build/linux/x64/release/bundle/data - build/linux/x64/release/bundle/lib - build/linux/x64/release/bundle/AdGuardHomeManager + ./data + ./lib + ./AdGuardHomeManager outPath: AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz - name: Upload artifact uses: actions/upload-artifact@v3 From 84d72d87337482b8c51b61ac0e8c59d86c2746a8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 21:19:16 +0200 Subject: [PATCH 213/676] Removed ls --- .github/workflows/release.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 427c5f9..7374f28 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -115,8 +115,6 @@ jobs: run: flutter_to_debian - name: Move .deb package to project root run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb - - name: build dir - run: ls build/linux/x64/release/bundle - name: Generate .tar.gz package uses: a7ul/tar-action@v1.1.3 id: compress From 7a1f153fe7cc2fa404a1b0cbc380ae7d72c6850e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 21:51:10 +0200 Subject: [PATCH 214/676] Created windows job --- .github/workflows/release.yaml | 33 ++++++++++++++++++++++++- windows/innosetup_installer_builder.iss | 2 +- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7374f28..3e9e6c7 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -133,10 +133,36 @@ jobs: path: | AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz + build-windows: + name: Build Windows installer + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + - name: Decode .env + run: [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) + - name: Update version in pubspec.yaml + run: (Get-Content pubspec.yaml) -replace '99.99.99+99', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII pubspec.yaml + - name: Update version in innosetup config file + run: (Get-Content windows/innosetup_installer_builder.iss) -replace '', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII windows/innosetup_installer_builder.iss + - uses: subosito/flutter-action@v2 + with: + channel: "stable" + - run: flutter clean + - run: flutter pub get + - run: flutter build windows --release + - name: Build installer witn innosetup + run: iscc /Q windows/innosetup_installer_builder.iss + - name: Move installer file to root directory + run: move build/windows/aghm_installer.exe AdGuardHomeManager_${{ github.event.inputs.version }}_Windows_x64.exe + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: windows + path: AdGuardHomeManager_${{ github.event.inputs.version }}_Windows_x64.exe release-builds-github: name: Release builds to GitHub runs-on: ubuntu-latest - needs: [build-android, build-macos, build-linux] + needs: [build-android, build-macos, build-linux, build-windows] steps: - uses: actions/checkout@v3 - name: Create builds directory @@ -156,6 +182,11 @@ jobs: with: name: linux path: releases/ + - name: Download Windows artifacts + uses: actions/download-artifact@v3 + with: + name: windows + path: releases/ - name: Release to GitHub uses: ncipollo/release-action@v1 with: diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index c818a3e..85c0798 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AdGuard Home Manager" -#define MyAppVersion "2.3.2" +#define MyAppVersion "" #define MyAppPublisher "JGeek00" #define MyAppURL "https://github.com/JGeek00/adguard-home-manager" #define MyAppExeName "adguard_home_manager.exe" From dfa3d620c2ff6ceef45053afad4cd52e148e7c44 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 21:58:07 +0200 Subject: [PATCH 215/676] Version change --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3e9e6c7..a6bd0d1 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -137,7 +137,7 @@ jobs: name: Build Windows installer runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v2 - name: Decode .env run: [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Update version in pubspec.yaml From dcc57acf91ae0b65c7b9160e0edef4fec9d17b91 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 21:59:07 +0200 Subject: [PATCH 216/676] Test --- .github/workflows/release.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a6bd0d1..6c8bfd8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -137,7 +137,6 @@ jobs: name: Build Windows installer runs-on: windows-latest steps: - - uses: actions/checkout@v2 - name: Decode .env run: [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Update version in pubspec.yaml From d4462218e3f585e4d9151097af8fd8a9175d3088 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 22:02:25 +0200 Subject: [PATCH 217/676] Readded --- .github/workflows/release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6c8bfd8..3e9e6c7 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -137,6 +137,7 @@ jobs: name: Build Windows installer runs-on: windows-latest steps: + - uses: actions/checkout@v3 - name: Decode .env run: [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Update version in pubspec.yaml From 01708f612163220fe8261b4a9fb774bbeec4c020 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 22:05:45 +0200 Subject: [PATCH 218/676] Commands changes --- .github/workflows/release.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3e9e6c7..0576737 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -139,11 +139,17 @@ jobs: steps: - uses: actions/checkout@v3 - name: Decode .env - run: [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) + shell: pwsh + run: | + [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Update version in pubspec.yaml - run: (Get-Content pubspec.yaml) -replace '99.99.99+99', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII pubspec.yaml + shell: pwsh + run: | + (Get-Content pubspec.yaml) -replace '99.99.99+99', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII pubspec.yaml - name: Update version in innosetup config file - run: (Get-Content windows/innosetup_installer_builder.iss) -replace '', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII windows/innosetup_installer_builder.iss + shell: pwsh + run: | + (Get-Content windows/innosetup_installer_builder.iss) -replace '', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII windows/innosetup_installer_builder.iss - uses: subosito/flutter-action@v2 with: channel: "stable" From a222f8b6fb99fe088a5e226407ff1c2e1b09b9ad Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 22:16:02 +0200 Subject: [PATCH 219/676] Ls --- .github/workflows/release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0576737..03eefde 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -156,6 +156,8 @@ jobs: - run: flutter clean - run: flutter pub get - run: flutter build windows --release + - name: ls + rum: ls windows - name: Build installer witn innosetup run: iscc /Q windows/innosetup_installer_builder.iss - name: Move installer file to root directory From fb8022a799b45a07f0c761890e33d0af61c25705 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 22:16:34 +0200 Subject: [PATCH 220/676] Fix --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 03eefde..ef552a0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -157,7 +157,7 @@ jobs: - run: flutter pub get - run: flutter build windows --release - name: ls - rum: ls windows + run: ls windows - name: Build installer witn innosetup run: iscc /Q windows/innosetup_installer_builder.iss - name: Move installer file to root directory From 38726f8854aa04f141586cf7de5ae656dd2324e9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 22:28:37 +0200 Subject: [PATCH 221/676] Changed routes innosetup file --- .github/workflows/release.yaml | 2 -- windows/innosetup_installer_builder.iss | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ef552a0..0576737 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -156,8 +156,6 @@ jobs: - run: flutter clean - run: flutter pub get - run: flutter build windows --release - - name: ls - run: ls windows - name: Build installer witn innosetup run: iscc /Q windows/innosetup_installer_builder.iss - name: Move installer file to root directory diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 85c0798..b7a348d 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -22,9 +22,9 @@ DefaultDirName={autopf}\{#MyAppName} DisableProgramGroupPage=yes ; Remove the following line to run in administrative install mode (install for all users.) PrivilegesRequired=lowest -OutputDir=C:\Users\Juan\adguard_home_manager\build\windows +OutputDir=..\build\windows OutputBaseFilename=aghm_installer -SetupIconFile=C:\Users\Juan\adguard_home_manager\assets\icon\icon-circle.ico +SetupIconFile=..\assets\icon\icon-circle.ico Compression=lzma SolidCompression=yes WizardStyle=modern @@ -37,15 +37,15 @@ Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl" Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked [Files] -Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\dynamic_color_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\window_size_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\Juan\adguard_home_manager\build\windows\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "..\build\windows\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\runner\Release\dynamic_color_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\runner\Release\window_size_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] From a94fdc7407f1fd77c7910991e8ee9d851702a815 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 22:52:45 +0200 Subject: [PATCH 222/676] Changed to bash --- .github/workflows/release.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0576737..1e0389f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -143,9 +143,8 @@ jobs: run: | [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Update version in pubspec.yaml - shell: pwsh - run: | - (Get-Content pubspec.yaml) -replace '99.99.99+99', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII pubspec.yaml + shell: bash + run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml - name: Update version in innosetup config file shell: pwsh run: | From 5d2631bd0817b8016787f221a7ea2c78dc9f21c0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 23:07:29 +0200 Subject: [PATCH 223/676] Changed commands to bash --- .github/workflows/release.yaml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1e0389f..34ea6b2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -139,16 +139,14 @@ jobs: steps: - uses: actions/checkout@v3 - name: Decode .env - shell: pwsh - run: | - [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) + shell: bash + run: echo '${{ secrets.ENV }}'' | base64 --decode > .env - name: Update version in pubspec.yaml shell: bash run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml - name: Update version in innosetup config file - shell: pwsh - run: | - (Get-Content windows/innosetup_installer_builder.iss) -replace '', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII windows/innosetup_installer_builder.iss + shell: bash + run: sed -i 's//${{ github.event.inputs.version }}/g' windows/innosetup_installer_builder.iss - uses: subosito/flutter-action@v2 with: channel: "stable" From 86e05c103077b9e298595a4d3fc548886e3f36a7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 May 2023 23:10:14 +0200 Subject: [PATCH 224/676] Revert "Changed commands to bash" This reverts commit 5d2631bd0817b8016787f221a7ea2c78dc9f21c0. --- .github/workflows/release.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 34ea6b2..1e0389f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -139,14 +139,16 @@ jobs: steps: - uses: actions/checkout@v3 - name: Decode .env - shell: bash - run: echo '${{ secrets.ENV }}'' | base64 --decode > .env + shell: pwsh + run: | + [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Update version in pubspec.yaml shell: bash run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml - name: Update version in innosetup config file - shell: bash - run: sed -i 's//${{ github.event.inputs.version }}/g' windows/innosetup_installer_builder.iss + shell: pwsh + run: | + (Get-Content windows/innosetup_installer_builder.iss) -replace '', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII windows/innosetup_installer_builder.iss - uses: subosito/flutter-action@v2 with: channel: "stable" From c3253559a6b34a3e993c6ac04900ccbcde1860a2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 May 2023 01:38:06 +0200 Subject: [PATCH 225/676] Release draft by default --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1e0389f..8491f55 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -199,6 +199,6 @@ jobs: token: ${{ secrets.GH_TOKEN }} tag: ${{ github.event.inputs.version }} name: v${{ github.event.inputs.version }} - draft: false + draft: true prerelease: false commit: ${{ github.sha }} \ No newline at end of file From 1541961a2845abf47ca1cf3413bfb4ab0e17eee9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 May 2023 02:00:26 +0200 Subject: [PATCH 226/676] Added release to google play --- .github/workflows/release.yaml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8491f55..12ff4b6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -201,4 +201,23 @@ jobs: name: v${{ github.event.inputs.version }} draft: true prerelease: false - commit: ${{ github.sha }} \ No newline at end of file + commit: ${{ github.sha }} + release-build-google-play: + name: Release Android build to the Google Play Store + runs-on: ubuntu-latest + needs: [build-android] + steps: + - uses: actions/checkout@v3 + - name: Download Android artifacts + uses: actions/download-artifact@v3 + with: + name: android + - name: Release app to Google Play + uses: r0adkll/upload-google-play@v1 + with: + serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} + packageName: com.jgeek00.adguard_home_manager + releaseFiles: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + track: production + status: draft + releaseName: ${{ github.event.inputs.version }} \ No newline at end of file From 88c5742c1659601813daeb408a171e0e6ac2897a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 May 2023 02:27:20 +0200 Subject: [PATCH 227/676] Small changes --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 12ff4b6..ad6b088 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -91,7 +91,7 @@ jobs: name: macos path: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg build-linux: - name: Build Linux .tar.gz + name: Build Linux .tar.gz and .deb runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 From 83e518017e8c764ca8e70e510f38dcedd91d8322 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 May 2023 02:28:50 +0200 Subject: [PATCH 228/676] Add number on tag --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ad6b088..0f1c9c2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -197,7 +197,7 @@ jobs: with: artifacts: "releases/*" token: ${{ secrets.GH_TOKEN }} - tag: ${{ github.event.inputs.version }} + tag: '${{ github.event.inputs.version }} (${{ github.event.inputs.number }})' name: v${{ github.event.inputs.version }} draft: true prerelease: false From 0963336f6e940a5964ff5c74be3560829f9c2632 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 May 2023 02:32:29 +0200 Subject: [PATCH 229/676] Added beta workflow --- .github/workflows/release-beta.yaml | 102 ++++++++++++++++++ .../{release.yaml => release-stable.yaml} | 0 2 files changed, 102 insertions(+) create mode 100644 .github/workflows/release-beta.yaml rename .github/workflows/{release.yaml => release-stable.yaml} (100%) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml new file mode 100644 index 0000000..c5f2936 --- /dev/null +++ b/.github/workflows/release-beta.yaml @@ -0,0 +1,102 @@ +name: Compile and release beta build + +on: + workflow_dispatch: + inputs: + version: + description: "Version (beta)" + required: true + default: "1.0.0-beta.1" + number: + description: "Build number" + required: true + default: "1" +jobs: + build-android: + name: Build Android .apk and .aab + runs-on: ubuntu-latest + env: + ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release + ANDROID_APK_RELEASE_PATH: build/app/outputs/apk/release + steps: + - uses: actions/checkout@v3 + - name: Decode android/app/keystore.jks + run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/app/keystore.jks + - name: Decode android/key.properties + run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties + - name: Decode .env + run: echo "${{ secrets.ENV }}" | base64 --decode > .env + - name: Update version in YAML + run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml + - name: Update KeyStore password in gradle properties + run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties + - name: Update KeyStore key password in gradle properties + run: sed -i 's/#{KEYSTORE_KEY_PASS}#/${{ secrets.KEYSTORE_KEY_PASS }}/g' android/key.properties + - uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: '18.x' + - uses: subosito/flutter-action@v2 + with: + channel: "stable" + - run: flutter clean + - run: flutter pub get + - run: flutter build apk --release + - run: flutter build appbundle --release + - name: Rename apk + run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + - name: Rename aab + run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + - name: Copy apk to project root + run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + - name: Copy aab to project root + run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: android + path: | + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + release-builds-github: + name: Release beta build to GitHub + runs-on: ubuntu-latest + needs: [build-android] + steps: + - uses: actions/checkout@v3 + - name: Create builds directory + run: mkdir releases + - name: Download Android artifacts + uses: actions/download-artifact@v3 + with: + name: android + path: releases/ + - name: Release to GitHub + uses: ncipollo/release-action@v1 + with: + artifacts: "releases/*" + token: ${{ secrets.GH_TOKEN }} + tag: '${{ github.event.inputs.version }} (${{ github.event.inputs.number }})' + name: v${{ github.event.inputs.version }} + draft: true + prerelease: true + commit: ${{ github.sha }} + release-build-google-play: + name: Release Android beta build to the Google Play Store + runs-on: ubuntu-latest + needs: [build-android] + steps: + - uses: actions/checkout@v3 + - name: Download Android artifacts + uses: actions/download-artifact@v3 + with: + name: android + - name: Release app to Google Play + uses: r0adkll/upload-google-play@v1 + with: + serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} + packageName: com.jgeek00.adguard_home_manager + releaseFiles: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + track: beta + status: draft + releaseName: ${{ github.event.inputs.version }} \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release-stable.yaml similarity index 100% rename from .github/workflows/release.yaml rename to .github/workflows/release-stable.yaml From 15147bf16df1ad2324f85f0f007219ad6afa7c31 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 May 2023 03:08:05 +0200 Subject: [PATCH 230/676] Changed workflow --- .github/workflows/release-beta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index c5f2936..b3cd1eb 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -76,7 +76,7 @@ jobs: with: artifacts: "releases/*" token: ${{ secrets.GH_TOKEN }} - tag: '${{ github.event.inputs.version }} (${{ github.event.inputs.number }})' + tag: '${{ github.event.inputs.version }}_(${{ github.event.inputs.number }})' name: v${{ github.event.inputs.version }} draft: true prerelease: true From 6fcd03f899c97a03ba4267c08e163b951df84125 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 May 2023 03:08:25 +0200 Subject: [PATCH 231/676] Adapted version checker to new tag name --- lib/base.dart | 5 +- lib/functions/app_update_download_link.dart | 30 +++++---- lib/functions/check_app_updates.dart | 13 ++-- lib/functions/compare_versions.dart | 68 ++++++++------------- lib/screens/settings/general_settings.dart | 5 +- lib/widgets/update_modal.dart | 6 +- 6 files changed, 62 insertions(+), 65 deletions(-) diff --git a/lib/base.dart b/lib/base.dart index 5869774..b2b593b 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -39,9 +39,10 @@ class _BaseState extends State with WidgetsBindingObserver { WidgetsBinding.instance.addPostFrameCallback((_) async { final appConfigProvider = Provider.of(context, listen: false); final result = await checkAppUpdates( - appVersion: appConfigProvider.getAppInfo!.version, + currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, installationSource: appConfigProvider.installationSource, - setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable + setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, + isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), ); if (result != null && appConfigProvider.doNotRememberVersion != result.tagName) { diff --git a/lib/functions/app_update_download_link.dart b/lib/functions/app_update_download_link.dart index 76c1a2d..48c798a 100644 --- a/lib/functions/app_update_download_link.dart +++ b/lib/functions/app_update_download_link.dart @@ -3,19 +3,23 @@ import 'dart:io'; import 'package:adguard_home_manager/models/github_release.dart'; String? getAppUpdateDownloadLink(GitHubRelease gitHubRelease) { - if (Platform.isAndroid) { - return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('apk')).browserDownloadUrl; - } - else if (Platform.isMacOS) { - return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('macOS')).browserDownloadUrl; // macOS package is a zip - } - else if (Platform.isWindows) { - return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('exe')).browserDownloadUrl; - } - else if (Platform.isLinux) { - return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('deb')).browserDownloadUrl; - } - else { + try { + if (Platform.isAndroid) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('apk')).browserDownloadUrl; + } + else if (Platform.isMacOS) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('macOS')).browserDownloadUrl; + } + else if (Platform.isWindows) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('exe')).browserDownloadUrl; + } + else if (Platform.isLinux) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('deb')).browserDownloadUrl; + } + else { + return null; + } + } catch (e) { return null; } } \ No newline at end of file diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart index 2063f20..eb44177 100644 --- a/lib/functions/check_app_updates.dart +++ b/lib/functions/check_app_updates.dart @@ -7,17 +7,22 @@ import 'package:adguard_home_manager/models/github_release.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; Future checkAppUpdates({ - required String appVersion, + required String currentBuildNumber, required void Function(GitHubRelease?) setUpdateAvailable, - required Source installationSource + required Source installationSource, + required bool isBeta }) async { final result = await checkAppUpdatesGitHub(); if (result['result'] == 'success') { - final update = gitHubUpdateExists(appVersion, result['body']); + final update = gitHubUpdateExists( + currentBuildNumber: currentBuildNumber, + gitHubReleases: result['body'], + isBeta: isBeta + ); if (update == true) { - final release = appVersion.contains('beta') + final release = isBeta == true ? result['body'].firstWhere((release) => release.prerelease == true) : result['body'].firstWhere((release) => release.prerelease == false); diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index e10662a..4bdc178 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -149,52 +149,36 @@ bool serverVersionIsAhead({ } } -bool gitHubUpdateExists(String appVersion, List gitHubReleases) { - if (appVersion.contains('beta')) { - final gitHubVersion = gitHubReleases.firstWhere((release) => release.prerelease == true).tagName; +bool gitHubUpdateExists({ + required String currentBuildNumber, + required List gitHubReleases, + required bool isBeta +}) { + final release = isBeta == true + ? gitHubReleases.firstWhere((release) => release.prerelease == true) + : gitHubReleases.firstWhere((release) => release.prerelease == false); + + final versionNumberRegex = RegExp(r'\(\d+\)'); + final releaseNumberExtracted = versionNumberRegex.allMatches(release.tagName).first.group(0); - final appBetaSplit = appVersion.split('-'); - final gitHubBetaSplit = gitHubVersion.split('-'); - - final List appVersionSplit = List.from(appBetaSplit[0].split('.').map((e) => int.parse(e))); - final int appBetaNumber = int.parse(appBetaSplit[1].split('.')[1]); - - final List gitHubVersionSplit = List.from(gitHubBetaSplit[0].split('.').map((e) => int.parse(e))); - final int gitHubBetaNumber = int.parse(gitHubBetaSplit[1].split('.')[1]); - - if (gitHubVersionSplit[0] > appVersionSplit[0]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] > appVersionSplit[1]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] > appVersionSplit[2]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] == appVersionSplit[2] && gitHubBetaNumber > appBetaNumber) { - return true; - } - else { + if (releaseNumberExtracted != null) { + final releaseNumber = releaseNumberExtracted.replaceAll(RegExp(r'\(|\)'), ''); + try { + final newReleaseParsed = int.parse(releaseNumber); + final currentReleaseParsed = int.parse(currentBuildNumber); + if (newReleaseParsed > currentReleaseParsed) { + return true; + } + else { + return false; + } + } catch (e) { + Sentry.captureMessage("Invalid release number. Current release: $currentBuildNumber. New release: $releaseNumber"); return false; } } else { - final gitHubVersion = gitHubReleases.firstWhere((release) => release.prerelease == false).tagName; - - final List appVersionSplit = List.from(appVersion.split('.').map((e) => int.parse(e))); - final List gitHubVersionSplit = List.from(gitHubVersion.split('.').map((e) => int.parse(e))); - - if (gitHubVersionSplit[0] > appVersionSplit[0]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] > appVersionSplit[1]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] > appVersionSplit[2]) { - return true; - } - else { - return false; - } + Sentry.captureMessage("Invalid release number. Tagname: ${release.tagName}"); + return false; } } \ No newline at end of file diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index 718bda7..e68aae3 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -57,9 +57,10 @@ class _GeneralSettingsState extends State { setState(() => appUpdatesStatus = AppUpdatesStatus.checking); final res = await checkAppUpdates( - appVersion: appConfigProvider.getAppInfo!.version, + currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, - installationSource: appConfigProvider.installationSource + installationSource: appConfigProvider.installationSource, + isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), ); if (res != null) { diff --git a/lib/widgets/update_modal.dart b/lib/widgets/update_modal.dart index d8f164f..5b99b66 100644 --- a/lib/widgets/update_modal.dart +++ b/lib/widgets/update_modal.dart @@ -60,7 +60,7 @@ class _UpdateModalState extends State { ), const SizedBox(height: 10), Text( - "${AppLocalizations.of(context)!.newVersion}: ${widget.gitHubRelease.tagName}", + "${AppLocalizations.of(context)!.newVersion}: ${widget.gitHubRelease.name.replaceAll('v', '')}", style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant ), @@ -101,7 +101,9 @@ class _UpdateModalState extends State { ), actions: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: downloadLink != null + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.end, children: [ if (downloadLink != null) TextButton( onPressed: () { From 2fc78b415b55aec46cf03e8ef53742094fa09500 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 May 2023 03:14:16 +0200 Subject: [PATCH 232/676] Updated tag format --- .github/workflows/release-stable.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 0f1c9c2..7407c2e 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -197,7 +197,7 @@ jobs: with: artifacts: "releases/*" token: ${{ secrets.GH_TOKEN }} - tag: '${{ github.event.inputs.version }} (${{ github.event.inputs.number }})' + tag: '${{ github.event.inputs.version }}_(${{ github.event.inputs.number }})' name: v${{ github.event.inputs.version }} draft: true prerelease: false From e2ea7ba51a9f0f1358817d0ffbdc35666883ae9c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 May 2023 19:21:34 +0200 Subject: [PATCH 233/676] Small fix --- lib/services/http_requests.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 4d129ae..ce2c316 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -2025,8 +2025,8 @@ class ApiClient { ), ]); - if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { final Map obj = { ...jsonDecode(result[0]['body']), 'current_version': jsonDecode(result[1]['body'])['version'] From 83be151a57d088052433c0f1fe389dda4df454a1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 May 2023 19:27:53 +0200 Subject: [PATCH 234/676] Fixed dns config issue --- lib/providers/dns_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index 1468f18..0965725 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -66,7 +66,7 @@ class DnsProvider with ChangeNotifier { if (result['result'] == 'success') { DnsInfo data = dnsInfo!; if (value['local_ptr_upstreams'] != null) { - data.localPtrUpstreams = value['local_ptr_upsreams']; + data.localPtrUpstreams = value['local_ptr_upstreams']; } data.usePrivatePtrResolvers = value['use_private_ptr_resolvers']; data.resolveClients = value['resolve_clients']; From 5a31660f1bda4fac5a313649b1e81c39015ae0ae Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 3 Jun 2023 03:49:09 +0200 Subject: [PATCH 235/676] Small change --- lib/services/http_requests.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index ce2c316..c28733e 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -2029,7 +2029,7 @@ class ApiClient { if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { final Map obj = { ...jsonDecode(result[0]['body']), - 'current_version': jsonDecode(result[1]['body'])['version'] + 'current_version': ServerInfoData.fromJson(jsonDecode(result[1]['body'])).version }; return { 'result': 'success', From 9a1ffa43f4eccdab03508e06bd7c1a6b6f3a8bb0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 3 Jun 2023 04:04:30 +0200 Subject: [PATCH 236/676] Fixed issue top item selected not filtered --- lib/providers/logs_provider.dart | 5 +- lib/screens/home/top_items.dart | 78 +------------------------------- lib/screens/logs/logs.dart | 2 +- 3 files changed, 4 insertions(+), 81 deletions(-) diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index e999470..a3211b5 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -146,8 +146,7 @@ class LogsProvider with ChangeNotifier { }) async { int offst = inOffset ?? offset; - String resStatus = responseStatus ?? selectedResultStatus; - String? search = searchText ?? searchText; + String resStatus = responseStatus ?? _selectedResultStatus; if (loadingMore != null && loadingMore == true) { _isLoadingMore = true; @@ -159,7 +158,7 @@ class LogsProvider with ChangeNotifier { offset: offst, olderThan: logsOlderThan, responseStatus: resStatus, - search: search + search: _searchText ); if (loadingMore != null && loadingMore == true) { diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index f2b836c..c43ba3a 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -12,12 +11,10 @@ import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; + class TopItems extends StatelessWidget { final String type; final String label; @@ -40,79 +37,6 @@ class TopItems extends StatelessWidget { final width = MediaQuery.of(context).size.width; - bool? getIsBlocked() { - if (type == 'topBlockedDomains') { - return true; - } - else if (type == 'topQueriedDomains') { - return false; - } - else { - return null; - } - } - - void blockUnblock(String domain, String newStatus) async { - final ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.savingUserFilters); - - final rules = await statusProvider.blockUnblockDomain( - domain: domain, - newStatus: newStatus - ); - - processModal.close(); - - if (rules == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.userFilteringRulesUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, - color: Colors.red - - ); - } - } - - void copyDomainClipboard(String domain) async { - await Clipboard.setData( - ClipboardData(text: domain) - ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.domainCopiedClipboard), - backgroundColor: Colors.green, - ) - ); - } - - List generateOptions(String domain) { - final isBlocked = getIsBlocked(); - return [ - if (isBlocked == true) MenuOption( - title: AppLocalizations.of(context)!.unblock, - icon: Icons.check, - action: () => blockUnblock(domain, 'unblock') - ), - if (isBlocked == false) MenuOption( - title: AppLocalizations.of(context)!.block, - icon: Icons.check, - action: () => blockUnblock(domain, 'block') - ), - MenuOption( - title: AppLocalizations.of(context)!.copyClipboard, - icon: Icons.check, - action: () => copyDomainClipboard(domain) - ), - ]; - } - Widget rowItem(Map item) { String? name; if (clients != null && clients == true) { diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index a48024c..5ff0097 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -390,7 +390,7 @@ class _LogsState extends State { const SizedBox(width: 15), Chip( avatar: const Icon( - Icons.link_rounded, + Icons.search_rounded, ), label: Row( children: [ From 89aa022f2d233987b44d644e594a9b4132a2fbc0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 6 Jun 2023 00:14:48 +0200 Subject: [PATCH 237/676] Fixed show snackbar error --- lib/functions/copy_clipboard.dart | 23 +++++++++++-------- lib/screens/clients/active_client_tile.dart | 3 --- lib/screens/clients/added_client_tile.dart | 2 -- .../filters/filters_triple_column.dart | 2 -- lib/screens/filters/list_options_menu.dart | 2 -- lib/screens/settings/app_logs/app_logs.dart | 1 - 6 files changed, 13 insertions(+), 20 deletions(-) diff --git a/lib/functions/copy_clipboard.dart b/lib/functions/copy_clipboard.dart index 87c8135..fbd13ec 100644 --- a/lib/functions/copy_clipboard.dart +++ b/lib/functions/copy_clipboard.dart @@ -3,18 +3,21 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:adguard_home_manager/config/globals.dart'; + void copyToClipboard({ - required BuildContext context, required String value, required String successMessage }) async { - await Clipboard.setData( - ClipboardData(text: value) - ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(successMessage), - backgroundColor: Colors.green, - ) - ); + if (scaffoldMessengerKey.currentState != null) { + await Clipboard.setData( + ClipboardData(text: value) + ); + scaffoldMessengerKey.currentState!.showSnackBar( + SnackBar( + content: Text(successMessage), + backgroundColor: Colors.green, + ) + ); + } } \ No newline at end of file diff --git a/lib/screens/clients/active_client_tile.dart b/lib/screens/clients/active_client_tile.dart index c3e55cf..26cb30f 100644 --- a/lib/screens/clients/active_client_tile.dart +++ b/lib/screens/clients/active_client_tile.dart @@ -35,7 +35,6 @@ class ActiveClientTile extends StatelessWidget { icon: Icons.copy_rounded, action: () { copyToClipboard( - context: context, value: client.name != '' ? client.name! : client.ip, @@ -58,7 +57,6 @@ class ActiveClientTile extends StatelessWidget { icon: Icons.copy_rounded, onTap: () { copyToClipboard( - context: context, value: client.name != '' ? client.name! : client.ip, @@ -137,7 +135,6 @@ class ActiveClientTile extends StatelessWidget { icon: Icons.copy_rounded, onTap: () { copyToClipboard( - context: context, value: client.name != '' ? client.name! : client.ip, diff --git a/lib/screens/clients/added_client_tile.dart b/lib/screens/clients/added_client_tile.dart index ff6d566..c63c816 100644 --- a/lib/screens/clients/added_client_tile.dart +++ b/lib/screens/clients/added_client_tile.dart @@ -55,7 +55,6 @@ class AddedClientTile extends StatelessWidget { icon: Icons.copy_rounded, onTap: () { copyToClipboard( - context: context, value: client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), successMessage: AppLocalizations.of(context)!.copiedClipboard, ); @@ -189,7 +188,6 @@ class AddedClientTile extends StatelessWidget { icon: Icons.copy_rounded, onTap: () { copyToClipboard( - context: context, value: client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), successMessage: AppLocalizations.of(context)!.copiedClipboard, ); diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index c481749..de0ffb0 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -249,7 +249,6 @@ class FiltersTripleColumn extends StatelessWidget { icon: Icons.copy_rounded, onTap: () { copyToClipboard( - context: context, value: filteringProvider.filtering!.userRules[index], successMessage: AppLocalizations.of(context)!.copiedClipboard, ); @@ -266,7 +265,6 @@ class FiltersTripleColumn extends StatelessWidget { title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, action: () => copyToClipboard( - context: context, value: filteringProvider.filtering!.userRules[index], successMessage: AppLocalizations.of(context)!.copiedClipboard, ) diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 6482ecd..1d644a0 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -87,7 +87,6 @@ class ListOptionsMenu extends StatelessWidget { onTap: () { Navigator.pop(context); // Closes the context menu copyToClipboard( - context: context, value: list.url, successMessage: AppLocalizations.of(context)!.listUrlCopied ); @@ -114,7 +113,6 @@ class ListOptionsMenu extends StatelessWidget { title: AppLocalizations.of(context)!.copyListUrl, icon: Icons.copy_rounded, action: () => copyToClipboard( - context: context, value: list.url, successMessage: AppLocalizations.of(context)!.listUrlCopied ) diff --git a/lib/screens/settings/app_logs/app_logs.dart b/lib/screens/settings/app_logs/app_logs.dart index 48a3c9d..19a8502 100644 --- a/lib/screens/settings/app_logs/app_logs.dart +++ b/lib/screens/settings/app_logs/app_logs.dart @@ -25,7 +25,6 @@ class AppLogs extends StatelessWidget { IconButton( onPressed: appConfigProvider.logs.isNotEmpty ? () => copyToClipboard( - context: context, value: jsonEncode(appConfigProvider.logs.map((log) => log.toMap()).toList()), successMessage: AppLocalizations.of(context)!.logsCopiedClipboard ) From 1ae32467c6e044b867abd237faf8f3c1a079786d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 6 Jun 2023 00:18:19 +0200 Subject: [PATCH 238/676] Fix compare versions --- lib/functions/compare_versions.dart | 34 ++++++++++++++++++----------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index 4bdc178..a8005e6 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -159,26 +159,34 @@ bool gitHubUpdateExists({ : gitHubReleases.firstWhere((release) => release.prerelease == false); final versionNumberRegex = RegExp(r'\(\d+\)'); - final releaseNumberExtracted = versionNumberRegex.allMatches(release.tagName).first.group(0); + final releaseNumberExtractedMatches = versionNumberRegex.allMatches(release.tagName); - if (releaseNumberExtracted != null) { - final releaseNumber = releaseNumberExtracted.replaceAll(RegExp(r'\(|\)'), ''); - try { - final newReleaseParsed = int.parse(releaseNumber); - final currentReleaseParsed = int.parse(currentBuildNumber); - if (newReleaseParsed > currentReleaseParsed) { - return true; - } - else { + if (releaseNumberExtractedMatches.isNotEmpty) { + final releaseNumberExtracted = releaseNumberExtractedMatches.first.group(0); + + if (releaseNumberExtracted != null) { + final releaseNumber = releaseNumberExtracted.replaceAll(RegExp(r'\(|\)'), ''); + try { + final newReleaseParsed = int.parse(releaseNumber); + final currentReleaseParsed = int.parse(currentBuildNumber); + if (newReleaseParsed > currentReleaseParsed) { + return true; + } + else { + return false; + } + } catch (e) { + Sentry.captureMessage("Invalid release number. Current release: $currentBuildNumber. New release: $releaseNumber"); return false; } - } catch (e) { - Sentry.captureMessage("Invalid release number. Current release: $currentBuildNumber. New release: $releaseNumber"); + } + else { + Sentry.captureMessage("Invalid release number. Tagname: ${release.tagName}"); return false; } } else { - Sentry.captureMessage("Invalid release number. Tagname: ${release.tagName}"); + Sentry.captureMessage("No matches. ${release.tagName}"); return false; } } \ No newline at end of file From 11a2784f3c4bbf470278c498d98d24f1e3ba38b8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 6 Jun 2023 00:26:32 +0200 Subject: [PATCH 239/676] Fixed issue server info --- lib/screens/settings/server_info/server_info.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/settings/server_info/server_info.dart b/lib/screens/settings/server_info/server_info.dart index 35bbd82..a6a9fcc 100644 --- a/lib/screens/settings/server_info/server_info.dart +++ b/lib/screens/settings/server_info/server_info.dart @@ -48,12 +48,12 @@ class _ServerInformationWidgetState extends State { if (mounted) { if (result['result'] == 'success') { setState(() { - serverInfo.loadStatus = LoadStatus.loaded; serverInfo.data = result['data']; + serverInfo.loadStatus = LoadStatus.loaded; }); } else { - setState(() => serverInfo.loadStatus = LoadStatus.loaded); + setState(() => serverInfo.loadStatus = LoadStatus.error); } } } From 4d27774d1d01fcf7baaf20505cbdbedc8d4bfd25 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 6 Jun 2023 00:43:07 +0200 Subject: [PATCH 240/676] Small fix --- lib/providers/status_provider.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 7fa1682..5a4ef73 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -290,10 +290,12 @@ class StatusProvider with ChangeNotifier { required String domain, required String newStatus }) async { + if (_serverStatus == null) return false; + final rules = await _serversProvider!.apiClient!.getFilteringRules(); if (rules['result'] == 'success') { - FilteringStatus oldStatus = serverStatus!.filteringStatus; + FilteringStatus oldStatus = _serverStatus!.filteringStatus; List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); if (newStatus == 'block') { @@ -302,7 +304,7 @@ class StatusProvider with ChangeNotifier { else if (newStatus == 'unblock') { newRules.add("@@||$domain^"); } - FilteringStatus newObj = serverStatus!.filteringStatus; + FilteringStatus newObj = _serverStatus!.filteringStatus; newObj.userRules = newRules; _filteringStatus = newObj; From d6e3d16dffc1e7cf784217facc63aa7f4ec66ba6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Jun 2023 16:27:51 +0200 Subject: [PATCH 241/676] Fixed server updater --- lib/functions/compare_versions.dart | 2 +- lib/providers/servers_provider.dart | 42 ++++++++++++++++--- .../settings/update_server/update.dart | 6 ++- .../servers_list/servers_list_item.dart | 5 ++- .../servers_list/servers_tile_item.dart | 5 ++- 5 files changed, 50 insertions(+), 10 deletions(-) diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index a8005e6..33ae8fe 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -39,7 +39,7 @@ bool compareVersions({ } else { // stable final current = currentVersion.replaceAll('v', ''); - final newV = currentVersion.replaceAll('v', ''); + final newV = newVersion.replaceAll('v', ''); final currentSplit = current.split('.').map((e) => int.parse(e)).toList(); final newSplit = newV.split('.').map((e) => int.parse(e)).toList(); diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 4b45394..f558675 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; @@ -155,8 +157,11 @@ class ServersProvider with ChangeNotifier { } } - void checkServerUpdatesAvailable(Server server) async { - setUpdateAvailableLoadStatus(LoadStatus.loading, true); + void checkServerUpdatesAvailable({ + required Server server, + bool? setValues + }) async { + if (setValues == true) setUpdateAvailableLoadStatus(LoadStatus.loading, true); final result = await _apiClient!.checkServerUpdates(); if (result['result'] == 'success') { UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); @@ -170,11 +175,16 @@ class ServersProvider with ChangeNotifier { newVersion: data.newVersion!, ) : false; - setUpdateAvailableData(data); - setUpdateAvailableLoadStatus(LoadStatus.loaded, true); + if (setValues == true) { + setUpdateAvailableData(data); + } + else { + if (data.currentVersion == data.newVersion) setUpdateAvailableData(data); + } + if (setValues == true) setUpdateAvailableLoadStatus(LoadStatus.loaded, true); } else { - setUpdateAvailableLoadStatus(LoadStatus.error, true); + if (setValues == true) setUpdateAvailableLoadStatus(LoadStatus.error, true); } } @@ -189,7 +199,10 @@ class ServersProvider with ChangeNotifier { Future initializateServer(Server server) async { final serverStatus = await _apiClient!.getServerStatus(); if (serverStatus['result'] == 'success') { - checkServerUpdatesAvailable(server); // Do not await + checkServerUpdatesAvailable( + server: server, + setValues: true + ); // Do not await } } @@ -229,4 +242,21 @@ class ServersProvider with ChangeNotifier { return null; } } + + void recheckPeriodServerUpdated() { + if (_selectedServer != null) { + Server server = _selectedServer!; + Timer.periodic( + const Duration(seconds: 2), + (timer) { + if (_selectedServer != null && _selectedServer == server) { + checkServerUpdatesAvailable(server: server, setValues: false); + } + else { + timer.cancel(); + } + } + ); + } + } } \ No newline at end of file diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index f84e01a..78a8a0e 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -41,6 +41,7 @@ class UpdateScreen extends StatelessWidget { if (result['result'] == 'success') { serversProvider.clearUpdateAvailable(serversProvider.selectedServer!, serversProvider.updateAvailable.data!.newVersion!); + serversProvider.recheckPeriodServerUpdated(); showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.requestStartUpdateSuccessful, @@ -79,7 +80,10 @@ class UpdateScreen extends StatelessWidget { color: Theme.of(context).colorScheme.onSurfaceVariant, ), tooltip: AppLocalizations.of(context)!.checkUpdates, - onPressed: () => serversProvider.checkServerUpdatesAvailable(serversProvider.selectedServer!) + onPressed: () => serversProvider.checkServerUpdatesAvailable( + server: serversProvider.selectedServer!, + setValues: true + ) ), ], ), diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index fb3364e..5d269d1 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -145,7 +145,10 @@ class _ServersListItemState extends State with SingleTickerProv statusProvider.setServerStatusData( data: serverStatus['data'] ); - serversProvider.checkServerUpdatesAvailable(server); + serversProvider.checkServerUpdatesAvailable( + server: server, + setValues: true + ); statusProvider.setServerStatusLoad(LoadStatus.loaded); } else { diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index fd274d6..7a8be69 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -112,7 +112,10 @@ class _ServersTileItemState extends State with SingleTickerProv statusProvider.setServerStatusData( data: serverStatus['data'] ); - serversProvider.checkServerUpdatesAvailable(server); + serversProvider.checkServerUpdatesAvailable( + server: server, + setValues: true + ); statusProvider.setServerStatusLoad(LoadStatus.loaded); } else { From 39c871b72d21dfebf0b224b90e0a032a9ef1137b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Jun 2023 19:26:56 +0200 Subject: [PATCH 242/676] Fixed server updater --- lib/services/http_requests.dart | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index c28733e..cb384b4 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -2007,21 +2007,18 @@ class ApiClient { final result = await Future.wait([ apiRequest( urlPath: '/version.json', - method: 'get', + method: 'post', server: server, type: 'check_server_updates', - body: json.encode({ + body: { "recheck_now": true - }) + } ), apiRequest( urlPath: '/status', method: 'get', server: server, type: 'check_server_updates', - body: json.encode({ - "recheck_now": true - }) ), ]); From a4ae8c2cdf4f892b2e26dd88949faf9f159ee549 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Jun 2023 22:51:15 +0200 Subject: [PATCH 243/676] Improved updater --- lib/models/update_available.dart | 13 ++-- lib/providers/servers_provider.dart | 67 ++++++++++--------- lib/screens/settings/settings.dart | 3 +- .../settings/update_server/update.dart | 42 +++++------- lib/widgets/bottom_nav_bar.dart | 3 +- .../servers_list/servers_list_item.dart | 1 - .../servers_list/servers_tile_item.dart | 1 - 7 files changed, 66 insertions(+), 64 deletions(-) diff --git a/lib/models/update_available.dart b/lib/models/update_available.dart index ee766e0..c370e33 100644 --- a/lib/models/update_available.dart +++ b/lib/models/update_available.dart @@ -18,7 +18,6 @@ class UpdateAvailableData { final bool? canAutoupdate; final bool disabled; String? changelog; - bool? updateAvailable; UpdateAvailableData({ required this.currentVersion, @@ -28,7 +27,6 @@ class UpdateAvailableData { required this.canAutoupdate, required this.disabled, this.changelog, - this.updateAvailable }); factory UpdateAvailableData.fromJson(Map json) => UpdateAvailableData( @@ -39,7 +37,15 @@ class UpdateAvailableData { canAutoupdate: json["can_autoupdate"], disabled: json["disabled"], changelog: json["changelog"], - updateAvailable: json['update_available'] + ); + + factory UpdateAvailableData.fromJsonUpdate(Map json) => UpdateAvailableData( + currentVersion: json["current_version"], + newVersion: json["new_version"], + announcement: json["announcement"], + announcementUrl: json["announcement_url"], + canAutoupdate: json["can_autoupdate"], + disabled: json["disabled"], ); Map toJson() => { @@ -50,6 +56,5 @@ class UpdateAvailableData { "can_autoupdate": canAutoupdate, "disabled": disabled, "changelog": changelog, - "update_available": updateAvailable }; } diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index f558675..c745260 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -8,7 +8,6 @@ import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/services/db/queries.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/enums.dart'; class ServersProvider with ChangeNotifier { @@ -18,6 +17,8 @@ class ServersProvider with ChangeNotifier { Server? _selectedServer; ApiClient? _apiClient; + bool _updatingServer = false; + final UpdateAvailable _updateAvailable = UpdateAvailable( loadStatus: LoadStatus.loading, data: null, @@ -39,6 +40,10 @@ class ServersProvider with ChangeNotifier { return _updateAvailable; } + bool get updatingServer { + return _updatingServer; + } + void setDbInstance(Database db) { _dbInstance = db; } @@ -70,6 +75,11 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } + void setUpdatingServer(bool status) { + _updatingServer = status; + notifyListeners(); + } + Future createServer(Server server) async { final saved = await saveServerQuery(_dbInstance!, server); if (saved == null) { @@ -159,9 +169,8 @@ class ServersProvider with ChangeNotifier { void checkServerUpdatesAvailable({ required Server server, - bool? setValues }) async { - if (setValues == true) setUpdateAvailableLoadStatus(LoadStatus.loading, true); + setUpdateAvailableLoadStatus(LoadStatus.loading, true); final result = await _apiClient!.checkServerUpdates(); if (result['result'] == 'success') { UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); @@ -169,40 +178,20 @@ class ServersProvider with ChangeNotifier { if (gitHubResult['result'] == 'success') { data.changelog = gitHubResult['body']; } - data.updateAvailable = data.newVersion != null - ? compareVersions( - currentVersion: data.currentVersion, - newVersion: data.newVersion!, - ) - : false; - if (setValues == true) { - setUpdateAvailableData(data); - } - else { - if (data.currentVersion == data.newVersion) setUpdateAvailableData(data); - } - if (setValues == true) setUpdateAvailableLoadStatus(LoadStatus.loaded, true); + setUpdateAvailableData(data); + setUpdateAvailableLoadStatus(LoadStatus.loaded, true); } else { - if (setValues == true) setUpdateAvailableLoadStatus(LoadStatus.error, true); - } - } - - void clearUpdateAvailable(Server server, String newCurrentVersion) { - if (_updateAvailable.data != null) { - _updateAvailable.data!.updateAvailable = null; - _updateAvailable.data!.currentVersion = newCurrentVersion; - notifyListeners(); + setUpdateAvailableLoadStatus(LoadStatus.error, true); } } Future initializateServer(Server server) async { final serverStatus = await _apiClient!.getServerStatus(); if (serverStatus['result'] == 'success') { - checkServerUpdatesAvailable( + checkServerUpdatesAvailable( // Do not await server: server, - setValues: true - ); // Do not await + ); } } @@ -245,15 +234,33 @@ class ServersProvider with ChangeNotifier { void recheckPeriodServerUpdated() { if (_selectedServer != null) { + setUpdatingServer(true); Server server = _selectedServer!; Timer.periodic( const Duration(seconds: 2), - (timer) { + (timer) async { if (_selectedServer != null && _selectedServer == server) { - checkServerUpdatesAvailable(server: server, setValues: false); + final result = await _apiClient!.checkServerUpdates(); + if (result['result'] == 'success') { + UpdateAvailableData data = UpdateAvailableData.fromJsonUpdate(result['data']); + if (data.currentVersion == data.newVersion) { + final gitHubResult = await _apiClient!.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); + if (gitHubResult['result'] == 'success') { + data.changelog = gitHubResult['body']; + } + setUpdateAvailableData(data); + timer.cancel(); + setUpdatingServer(false); + } + } + else { + timer.cancel(); + setUpdatingServer(false); + } } else { timer.cancel(); + setUpdatingServer(false); } } ); diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index b0763f6..f3a08ba 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -188,8 +188,7 @@ class SettingsWidget extends StatelessWidget { title: AppLocalizations.of(context)!.updates, subtitle: AppLocalizations.of(context)!.updatesDescription, trailing: serversProvider.updateAvailable.data != null && - serversProvider.updateAvailable.data!.updateAvailable != null && - serversProvider.updateAvailable.data!.updateAvailable == true + serversProvider.updateAvailable.data!.canAutoupdate == true ? Container( width: 10, height: 10, diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index 78a8a0e..3467994 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -40,7 +40,6 @@ class UpdateScreen extends StatelessWidget { processModal.close(); if (result['result'] == 'success') { - serversProvider.clearUpdateAvailable(serversProvider.selectedServer!, serversProvider.updateAvailable.data!.newVersion!); serversProvider.recheckPeriodServerUpdated(); showSnacbkar( appConfigProvider: appConfigProvider, @@ -82,7 +81,6 @@ class UpdateScreen extends StatelessWidget { tooltip: AppLocalizations.of(context)!.checkUpdates, onPressed: () => serversProvider.checkServerUpdatesAvailable( server: serversProvider.selectedServer!, - setValues: true ) ), ], @@ -101,11 +99,9 @@ class UpdateScreen extends StatelessWidget { ], ) : Icon( - serversProvider.updateAvailable.data!.updateAvailable != null - ? serversProvider.updateAvailable.data!.updateAvailable == true - ? Icons.system_update_rounded - : Icons.system_security_update_good_rounded - : Icons.system_security_update_warning_rounded, + serversProvider.updateAvailable.data!.canAutoupdate == true + ? Icons.system_update_rounded + : Icons.system_security_update_good_rounded, size: 40, color: Theme.of(context).colorScheme.primary, ), @@ -113,11 +109,9 @@ class UpdateScreen extends StatelessWidget { Text( serversProvider.updateAvailable.loadStatus == LoadStatus.loading ? AppLocalizations.of(context)!.checkingUpdates - : serversProvider.updateAvailable.data!.updateAvailable != null - ? serversProvider.updateAvailable.data!.updateAvailable == true - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.serverUpdated - : AppLocalizations.of(context)!.unknownStatus, + : serversProvider.updateAvailable.data!.canAutoupdate == true + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.serverUpdated, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.w400 @@ -131,7 +125,7 @@ class UpdateScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true + serversProvider.updateAvailable.data!.canAutoupdate == true ? AppLocalizations.of(context)!.newVersion : AppLocalizations.of(context)!.currentVersion, style: const TextStyle( @@ -140,11 +134,9 @@ class UpdateScreen extends StatelessWidget { ), const SizedBox(height: 4), Text( - serversProvider.updateAvailable.data!.updateAvailable != null - ? serversProvider.updateAvailable.data!.updateAvailable == true - ? serversProvider.updateAvailable.data!.newVersion ?? 'N/A' - : serversProvider.updateAvailable.data!.currentVersion - : "N/A", + serversProvider.updateAvailable.data!.canAutoupdate == true + ? serversProvider.updateAvailable.data!.newVersion ?? 'N/A' + : serversProvider.updateAvailable.data!.currentVersion, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w700, @@ -157,11 +149,13 @@ class UpdateScreen extends StatelessWidget { FilledButton.icon( icon: const Icon(Icons.download_rounded), label: Text(AppLocalizations.of(context)!.updateNow), - onPressed: serversProvider.updateAvailable.data!.updateAvailable != null && serversProvider.updateAvailable.data!.updateAvailable == true - ? serversProvider.updateAvailable.data!.canAutoupdate != null && serversProvider.updateAvailable.data!.canAutoupdate == true - ? () => update() - : () => showAutoUpdateUnavailableModal() - : null + onPressed: serversProvider.updatingServer == true + ? null + : serversProvider.updateAvailable.data!.canAutoupdate == true + ? serversProvider.updateAvailable.data!.canAutoupdate != null && serversProvider.updateAvailable.data!.canAutoupdate == true + ? () => update() + : () => showAutoUpdateUnavailableModal() + : null ) ], ), @@ -178,7 +172,7 @@ class UpdateScreen extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( - "Changelog ${serversProvider.updateAvailable.data!.updateAvailable == true + "Changelog ${serversProvider.updateAvailable.data!.canAutoupdate == true ? serversProvider.updateAvailable.data!.newVersion : serversProvider.updateAvailable.data!.currentVersion}", style: TextStyle( diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index 8465844..366fe2c 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -66,8 +66,7 @@ class BottomNavBar extends StatelessWidget { if ( screen.name == 'settings' && serversProvider.updateAvailable.data != null && - serversProvider.updateAvailable.data!.updateAvailable != null && - serversProvider.updateAvailable.data!.updateAvailable == true + serversProvider.updateAvailable.data!.canAutoupdate == true ) Positioned( bottom: 0, right: -12, diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 5d269d1..724be22 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -147,7 +147,6 @@ class _ServersListItemState extends State with SingleTickerProv ); serversProvider.checkServerUpdatesAvailable( server: server, - setValues: true ); statusProvider.setServerStatusLoad(LoadStatus.loaded); } diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index 7a8be69..c45b90e 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -114,7 +114,6 @@ class _ServersTileItemState extends State with SingleTickerProv ); serversProvider.checkServerUpdatesAvailable( server: server, - setValues: true ); statusProvider.setServerStatusLoad(LoadStatus.loaded); } From 2b3b70451fc9a7f753de4f703385179d109f7981 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Jun 2023 23:03:10 +0200 Subject: [PATCH 244/676] Updated beta workflow --- .github/workflows/release-beta.yaml | 33 +++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index b3cd1eb..42eb951 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -4,9 +4,13 @@ on: workflow_dispatch: inputs: version: - description: "Version (beta)" + description: "Version" required: true - default: "1.0.0-beta.1" + default: "1.0.0" + beta-number: + description: "Beta number" + required: true + default: "1" number: description: "Build number" required: true @@ -18,8 +22,11 @@ jobs: env: ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release ANDROID_APK_RELEASE_PATH: build/app/outputs/apk/release + VERSION_NAME: ${{ github.event.inputs.version }}-beta.${{ github.event.inputs.beta-number }} steps: - uses: actions/checkout@v3 + with: + ref: beta - name: Decode android/app/keystore.jks run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/app/keystore.jks - name: Decode android/key.properties @@ -27,7 +34,7 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Update version in YAML - run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml + run: sed -i 's/99.99.99+99/$VERSION_NAME+${{ github.event.inputs.number }}/g' pubspec.yaml - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties @@ -44,20 +51,20 @@ jobs: - run: flutter build apk --release - run: flutter build appbundle --release - name: Rename apk - run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_$VERSION_NAME_Android.apk - name: Rename aab - run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_$VERSION_NAME_Android.aab - name: Copy apk to project root - run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_$VERSION_NAME_Android.apk AdGuardHomeManager_$VERSION_NAME_Android.apk - name: Copy aab to project root - run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_$VERSION_NAME_Android.aab AdGuardHomeManager_$VERSION_NAME_Android.aab - name: Upload artifact uses: actions/upload-artifact@v3 with: name: android path: | - AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + AdGuardHomeManager_$VERSION_NAME_Android.aab + AdGuardHomeManager_$VERSION_NAME_Android.apk release-builds-github: name: Release beta build to GitHub runs-on: ubuntu-latest @@ -76,8 +83,8 @@ jobs: with: artifacts: "releases/*" token: ${{ secrets.GH_TOKEN }} - tag: '${{ github.event.inputs.version }}_(${{ github.event.inputs.number }})' - name: v${{ github.event.inputs.version }} + tag: '$VERSION_NAME_(${{ github.event.inputs.number }})' + name: v$VERSION_NAME draft: true prerelease: true commit: ${{ github.sha }} @@ -96,7 +103,7 @@ jobs: with: serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} packageName: com.jgeek00.adguard_home_manager - releaseFiles: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + releaseFiles: AdGuardHomeManager_$VERSION_NAME_Android.aab track: beta status: draft - releaseName: ${{ github.event.inputs.version }} \ No newline at end of file + releaseName: $VERSION_NAMEz \ No newline at end of file From ba76824039caefb33339c6562f97be341a1e4cbd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Jun 2023 23:08:30 +0200 Subject: [PATCH 245/676] Fixed workflow --- .github/workflows/release-beta.yaml | 30 ++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 42eb951..89d6ec2 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -34,7 +34,7 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Update version in YAML - run: sed -i 's/99.99.99+99/$VERSION_NAME+${{ github.event.inputs.number }}/g' pubspec.yaml + run: sed -i 's/99.99.99+99/${{ VERSION_NAME }}+${{ github.event.inputs.number }}/g' pubspec.yaml - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties @@ -51,26 +51,30 @@ jobs: - run: flutter build apk --release - run: flutter build appbundle --release - name: Rename apk - run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_$VERSION_NAME_Android.apk + run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ VERSION_NAME }}_Android.apk - name: Rename aab - run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_$VERSION_NAME_Android.aab + run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab - name: Copy apk to project root - run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_$VERSION_NAME_Android.apk AdGuardHomeManager_$VERSION_NAME_Android.apk + run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ VERSION_NAME }}_Android.apk AdGuardHomeManager_${{ VERSION_NAME }}_Android.apk - name: Copy aab to project root - run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_$VERSION_NAME_Android.aab AdGuardHomeManager_$VERSION_NAME_Android.aab + run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab - name: Upload artifact uses: actions/upload-artifact@v3 with: name: android path: | - AdGuardHomeManager_$VERSION_NAME_Android.aab - AdGuardHomeManager_$VERSION_NAME_Android.apk + AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab + AdGuardHomeManager_${{ VERSION_NAME }}_Android.apk release-builds-github: name: Release beta build to GitHub runs-on: ubuntu-latest needs: [build-android] + env: + VERSION_NAME: ${{ github.event.inputs.version }}-beta.${{ github.event.inputs.beta-number }} steps: - uses: actions/checkout@v3 + with: + ref: beta - name: Create builds directory run: mkdir releases - name: Download Android artifacts @@ -83,8 +87,8 @@ jobs: with: artifacts: "releases/*" token: ${{ secrets.GH_TOKEN }} - tag: '$VERSION_NAME_(${{ github.event.inputs.number }})' - name: v$VERSION_NAME + tag: '${{ VERSION_NAME }}_(${{ github.event.inputs.number }})' + name: v${{ VERSION_NAME }} draft: true prerelease: true commit: ${{ github.sha }} @@ -92,8 +96,12 @@ jobs: name: Release Android beta build to the Google Play Store runs-on: ubuntu-latest needs: [build-android] + env: + VERSION_NAME: ${{ github.event.inputs.version }}-beta.${{ github.event.inputs.beta-number }} steps: - uses: actions/checkout@v3 + with: + ref: beta - name: Download Android artifacts uses: actions/download-artifact@v3 with: @@ -103,7 +111,7 @@ jobs: with: serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} packageName: com.jgeek00.adguard_home_manager - releaseFiles: AdGuardHomeManager_$VERSION_NAME_Android.aab + releaseFiles: AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab track: beta status: draft - releaseName: $VERSION_NAMEz \ No newline at end of file + releaseName: ${{ VERSION_NAME }}z \ No newline at end of file From c562e4841cc6e5542e9955afb6cebbbaef058163 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Jun 2023 23:10:33 +0200 Subject: [PATCH 246/676] Fixed workflow --- .github/workflows/release-beta.yaml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 89d6ec2..472e119 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -34,7 +34,7 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Update version in YAML - run: sed -i 's/99.99.99+99/${{ VERSION_NAME }}+${{ github.event.inputs.number }}/g' pubspec.yaml + run: sed -i 's/99.99.99+99/${{ env.VERSION_NAME }}+${{ github.event.inputs.number }}/g' pubspec.yaml - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties @@ -51,20 +51,20 @@ jobs: - run: flutter build apk --release - run: flutter build appbundle --release - name: Rename apk - run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ VERSION_NAME }}_Android.apk + run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - name: Rename aab - run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab + run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - name: Copy apk to project root - run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ VERSION_NAME }}_Android.apk AdGuardHomeManager_${{ VERSION_NAME }}_Android.apk + run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - name: Copy aab to project root - run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab + run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - name: Upload artifact uses: actions/upload-artifact@v3 with: name: android path: | - AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab - AdGuardHomeManager_${{ VERSION_NAME }}_Android.apk + AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab + AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk release-builds-github: name: Release beta build to GitHub runs-on: ubuntu-latest @@ -87,8 +87,8 @@ jobs: with: artifacts: "releases/*" token: ${{ secrets.GH_TOKEN }} - tag: '${{ VERSION_NAME }}_(${{ github.event.inputs.number }})' - name: v${{ VERSION_NAME }} + tag: '${{ env.VERSION_NAME }}_(${{ github.event.inputs.number }})' + name: v${{ env.VERSION_NAME }} draft: true prerelease: true commit: ${{ github.sha }} @@ -111,7 +111,7 @@ jobs: with: serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} packageName: com.jgeek00.adguard_home_manager - releaseFiles: AdGuardHomeManager_${{ VERSION_NAME }}_Android.aab + releaseFiles: AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab track: beta status: draft - releaseName: ${{ VERSION_NAME }}z \ No newline at end of file + releaseName: ${{ env.VERSION_NAME }} \ No newline at end of file From f5cdfc44112b3859fecff4bc376719c53cc28c23 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Jun 2023 23:24:13 +0200 Subject: [PATCH 247/676] Updated workflow --- .github/workflows/release-stable.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 7407c2e..382ebec 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -205,7 +205,7 @@ jobs: release-build-google-play: name: Release Android build to the Google Play Store runs-on: ubuntu-latest - needs: [build-android] + needs: [build-android, build-macos, build-linux, build-windows] steps: - uses: actions/checkout@v3 - name: Download Android artifacts From 329d2195a716f2931dbf252264f647900cfdc263 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 13 Jun 2023 12:53:10 +0200 Subject: [PATCH 248/676] Bugs fixed --- lib/models/logs.dart | 2 +- lib/models/server_info.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/models/logs.dart b/lib/models/logs.dart index 9c21bca..0dd5f6e 100644 --- a/lib/models/logs.dart +++ b/lib/models/logs.dart @@ -80,7 +80,7 @@ class Log { elapsedMs: json["elapsedMs"], question: Question.fromJson(json["question"]), reason: json["reason"], - rules: List.from(json["rules"].map((x) => Rule.fromJson(x))), + rules: json["rules"] != null ? List.from(json["rules"].map((x) => Rule.fromJson(x))) : [], status: json["status"], time: DateTime.parse(json["time"]), upstream: json["upstream"], diff --git a/lib/models/server_info.dart b/lib/models/server_info.dart index 84f9a57..8d26857 100644 --- a/lib/models/server_info.dart +++ b/lib/models/server_info.dart @@ -43,7 +43,7 @@ class ServerInfoData { dnsPort: json["dns_port"], httpPort: json["http_port"], protectionEnabled: json["protection_enabled"], - dhcpAvailable: json["dhcp_available"], + dhcpAvailable: json["dhcp_available"] ?? false, running: json["running"], version: json["version"], language: json["language"], From d1973a55dbe81d1489c4f94335f48ccbdfffddae Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 13 Jun 2023 12:56:35 +0200 Subject: [PATCH 249/676] Bug fix --- lib/widgets/add_server_modal.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 51d8b22..3f384e8 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -392,7 +392,7 @@ class _AddServerModalState extends State { (version['data'].contains('a') || version['data'].contains('b')) // alpha or beta ) { Navigator.pop(context); - widget.onUnsupportedVersion(version); + widget.onUnsupportedVersion(version['data']); } else { Navigator.pop(context); From c1c8ab10a0737c2e4a65000a179013d06dc15621 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 15 Jun 2023 14:27:08 +0200 Subject: [PATCH 250/676] Bug fixes --- lib/models/dhcp.dart | 2 +- lib/models/dns_info.dart | 2 +- lib/models/encryption.dart | 2 +- lib/models/logs.dart | 2 +- lib/models/update_available.dart | 2 +- lib/screens/logs/log_details_screen.dart | 2 +- lib/screens/settings/dhcp/select_interface_modal.dart | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index c870b9b..26caac0 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -17,7 +17,7 @@ class NetworkInterface { String name; String hardwareAddress; List flags; - String gatewayIp; + String? gatewayIp; List ipv4Addresses; List ipv6Addresses; diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 1fc1979..d1e0107 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -1,6 +1,6 @@ class DnsInfo { List upstreamDns; - String upstreamDnsFile; + String? upstreamDnsFile; List bootstrapDns; bool protectionEnabled; int ratelimit; diff --git a/lib/models/encryption.dart b/lib/models/encryption.dart index 6187faf..3e2e230 100644 --- a/lib/models/encryption.dart +++ b/lib/models/encryption.dart @@ -31,7 +31,7 @@ class EncryptionData { final int? portHttps; final int? portDnsOverTls; final int? portDnsOverQuic; - final int portDnscrypt; + final int? portDnscrypt; final String dnscryptConfigFile; final bool allowUnencryptedDoh; final String certificateChain; diff --git a/lib/models/logs.dart b/lib/models/logs.dart index 0dd5f6e..9ba3738 100644 --- a/lib/models/logs.dart +++ b/lib/models/logs.dart @@ -46,7 +46,7 @@ class Log { final List rules; final String? status; final DateTime time; - final String upstream; + final String? upstream; final List answer; final int? filterId; final String? rule; diff --git a/lib/models/update_available.dart b/lib/models/update_available.dart index c370e33..890e99c 100644 --- a/lib/models/update_available.dart +++ b/lib/models/update_available.dart @@ -16,7 +16,7 @@ class UpdateAvailableData { final String? announcement; final String? announcementUrl; final bool? canAutoupdate; - final bool disabled; + final bool? disabled; String? changelog; UpdateAvailableData({ diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 32fbd73..440c9c1 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -136,7 +136,7 @@ class LogDetailsScreen extends StatelessWidget { subtitle: log.question.questionClass ), SectionLabel(label: AppLocalizations.of(context)!.response), - if (log.upstream != '') LogListTile( + if (log.upstream != null && log.upstream != '') LogListTile( icon: Icons.dns_rounded, title: AppLocalizations.of(context)!.dnsServer, subtitle: log.upstream diff --git a/lib/screens/settings/dhcp/select_interface_modal.dart b/lib/screens/settings/dhcp/select_interface_modal.dart index 9827f11..01b7e06 100644 --- a/lib/screens/settings/dhcp/select_interface_modal.dart +++ b/lib/screens/settings/dhcp/select_interface_modal.dart @@ -118,7 +118,7 @@ class SelectInterfaceModal extends StatelessWidget { ), const SizedBox(height: 5), ], - if (interfaces[index].gatewayIp != '') ...[ + if (interfaces[index].gatewayIp != null && interfaces[index].gatewayIp != '') ...[ Row( children: [ Text( @@ -129,7 +129,7 @@ class SelectInterfaceModal extends StatelessWidget { ), ), Text( - interfaces[index].gatewayIp, + interfaces[index].gatewayIp!, style: TextStyle( fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant From 6de9f80d2bb8f1deaad524c56a0b3d1736ad5549 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 15 Jun 2023 14:46:09 +0200 Subject: [PATCH 251/676] Changed servers list design --- lib/widgets/servers_list/servers_list.dart | 45 +++------ .../servers_list/servers_tile_item.dart | 93 ++++++++++--------- macos/Podfile.lock | 2 +- 3 files changed, 65 insertions(+), 75 deletions(-) diff --git a/lib/widgets/servers_list/servers_list.dart b/lib/widgets/servers_list/servers_list.dart index d4cd9cf..030ad74 100644 --- a/lib/widgets/servers_list/servers_list.dart +++ b/lib/widgets/servers_list/servers_list.dart @@ -28,38 +28,23 @@ class ServersList extends StatelessWidget { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); - - final width = MediaQuery.of(context).size.width; if (serversProvider.serversList.isNotEmpty) { - if (width > breakingWidth) { - return ListView( - children: [ - Wrap( - children: serversProvider.serversList.asMap().entries.map( - (s) => ServersTileItem( - server: serversProvider.serversList[s.key], - index: s.key, - onChange: onChange - ) - ).toList(), - ), - const SizedBox(height: 8) - ], - ); - } - else { - return ListView.builder( - controller: scrollController, - itemCount: serversProvider.serversList.length, - itemBuilder: (context, index) => ServersListItem( - expandableController: controllers[index], - server: serversProvider.serversList[index], - index: index, - onChange: onChange - ) - ); - } + return ListView( + children: [ + Wrap( + children: serversProvider.serversList.asMap().entries.map( + (s) => ServersTileItem( + breakingWidth: breakingWidth, + server: serversProvider.serversList[s.key], + index: s.key, + onChange: onChange + ) + ).toList(), + ), + const SizedBox(height: 8) + ], + ); } else { return SizedBox( diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index c45b90e..1cbd622 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -22,12 +22,14 @@ class ServersTileItem extends StatefulWidget { final Server server; final int index; final void Function(int) onChange; + final double breakingWidth; const ServersTileItem({ Key? key, required this.server, required this.index, - required this.onChange + required this.onChange, + required this.breakingWidth }) : super(key: key); @override @@ -262,12 +264,10 @@ class _ServersTileItemState extends State with SingleTickerProv Widget bottomRow(Server server, int index) { return Column( children: [ - const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ PopupMenuButton( - // color: Theme.of(context).dialogBackgroundColor, itemBuilder: (context) => [ PopupMenuItem( enabled: server.defaultServer == false @@ -316,41 +316,39 @@ class _ServersTileItemState extends State with SingleTickerProv child: serversProvider.selectedServer != null && serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null && serversProvider.selectedServer?.id == server.id - ? Container( - margin: const EdgeInsets.only(right: 12), - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), - decoration: BoxDecoration( - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null - ? Colors.green - : Colors.orange, - borderRadius: BorderRadius.circular(30) - ), - child: Row( - children: [ - Icon( - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null - ? Icons.check - : Icons.warning, - color: Colors.white, + ? Padding( + padding: const EdgeInsets.only(right: 16), + child: Row( + children: [ + Icon( + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null + ? Icons.check + : Icons.warning, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null + ? Colors.green + : Colors.orange, + ), + const SizedBox(width: 10), + Text( + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null + ? AppLocalizations.of(context)!.connected + : AppLocalizations.of(context)!.selectedDisconnected, + style: TextStyle( + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null + ? Colors.green + : Colors.orange, + fontWeight: FontWeight.w500 + ), + ) + ], ), - const SizedBox(width: 10), - Text( - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null - ? AppLocalizations.of(context)!.connected - : AppLocalizations.of(context)!.selectedDisconnected, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ) - ], - ), - ) + ) : Container( margin: const EdgeInsets.only(right: 10), - child: TextButton( + child: FilledButton.icon( + icon: const Icon(Icons.login), onPressed: () => connectToServer(server), - child: Text(AppLocalizations.of(context)!.connect), + label: Text(AppLocalizations.of(context)!.connect), ), ), ) @@ -384,17 +382,24 @@ class _ServersTileItemState extends State with SingleTickerProv } return FractionallySizedBox( - widthFactor: 0.5, + widthFactor: width > widget.breakingWidth ? 0.5 : 1, child: Card( - margin: generateMargins(widget.index), - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - topRow(widget.server, widget.index), - bottomRow(widget.server, widget.index) - ], - ), + margin: width > widget.breakingWidth + ? generateMargins(widget.index) + : const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: topRow(widget.server, widget.index), + ), + Padding( + padding: const EdgeInsets.only( + left: 8, right: 8, bottom: 16 + ), + child: bottomRow(widget.server, widget.index), + ) + ], ), ), ); diff --git a/macos/Podfile.lock b/macos/Podfile.lock index bf5412f..f8ac696 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -94,4 +94,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 -COCOAPODS: 1.11.2 +COCOAPODS: 1.12.1 From cddc964276c3a28e8927b025f0870e40efa7dd27 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 15 Jun 2023 14:46:32 +0200 Subject: [PATCH 252/676] Removed import --- lib/widgets/servers_list/servers_list.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/widgets/servers_list/servers_list.dart b/lib/widgets/servers_list/servers_list.dart index 030ad74..8e530f2 100644 --- a/lib/widgets/servers_list/servers_list.dart +++ b/lib/widgets/servers_list/servers_list.dart @@ -4,7 +4,6 @@ import 'package:expandable/expandable.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/servers_list/servers_list_item.dart'; import 'package:adguard_home_manager/widgets/servers_list/servers_tile_item.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; From 665eb5a0c2a83b700f1e71a8553b4d84af97fcc8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 15 Jun 2023 14:53:37 +0200 Subject: [PATCH 253/676] Changed design dns rewrites --- .../settings/dns_rewrites/dns_rewrites.dart | 118 +++++++++--------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index d2ec726..17f267e 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -123,71 +123,69 @@ class _DnsRewritesScreenState extends State { child: ListView.builder( padding: const EdgeInsets.only(top: 0), itemCount: rewriteRulesProvider.rewriteRules!.length, - itemBuilder: (context, index) => Container( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - width: 1, - color: Theme.of(context).colorScheme.outline.withOpacity(0.2) - ) - ) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.domain}: ", - style: TextStyle( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface + itemBuilder: (context, index) => Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Padding( + padding: const EdgeInsets.only( + left: 16, top: 16, bottom: 16, right: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.domain}: ", + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - Text( - rewriteRulesProvider.rewriteRules![index].domain, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface + Text( + rewriteRulesProvider.rewriteRules![index].domain, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - ], - ), - const SizedBox(height: 3), - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.answer}: ", - style: TextStyle( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface + ], + ), + const SizedBox(height: 3), + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.answer}: ", + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - Text( - rewriteRulesProvider.rewriteRules![index].answer, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface + Text( + rewriteRulesProvider.rewriteRules![index].answer, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - ], - ), - ], - ), - IconButton( - onPressed: () => { - showDialog( - context: context, - builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(rewriteRulesProvider.rewriteRules![index]) + ], + ), + ], + ), + IconButton( + onPressed: () => { + showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rewriteRulesProvider.rewriteRules![index]) + ) ) - ) - }, - icon: const Icon(Icons.delete) - ) - ], + }, + icon: const Icon(Icons.delete), + tooltip: AppLocalizations.of(context)!.delete, + ) + ], + ), ), ) ), From d16a3c759e0b3b1e760c2aa3a2b3ceb66aad8e84 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 16 Jun 2023 14:38:19 +0200 Subject: [PATCH 254/676] Bug fixes --- lib/models/dhcp.dart | 2 +- lib/models/dns_info.dart | 2 +- lib/screens/settings/dhcp/dhcp.dart | 2 +- lib/screens/settings/dns/upstream_dns.dart | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index 26caac0..7bba2ca 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -54,7 +54,7 @@ DhcpStatus dhcpStatusFromJson(String str) => DhcpStatus.fromJson(json.decode(str String dhcpStatusToJson(DhcpStatus data) => json.encode(data.toJson()); class DhcpStatus { - String interfaceName; + String? interfaceName; IpVersion v4; IpVersion v6; List leases; diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index d1e0107..2f23fd5 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -8,7 +8,7 @@ class DnsInfo { bool ednsCsEnabled; bool dnssecEnabled; bool disableIpv6; - String upstreamMode; + String? upstreamMode; int cacheSize; int cacheTtlMin; int cacheTtlMax; diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 49ab29c..d0ab42c 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -58,7 +58,7 @@ class _DhcpScreenState extends State { final dhcpProvider = Provider.of(context, listen: false); if (dhcpProvider.dhcp != null) { setState(() { - if (dhcpProvider.dhcp!.dhcpStatus.interfaceName != '') { + if (dhcpProvider.dhcp!.dhcpStatus.interfaceName != null && dhcpProvider.dhcp!.dhcpStatus.interfaceName != '') { selectedInterface = dhcpProvider.dhcp!.networkInterfaces.firstWhere((iface) => iface.name == dhcpProvider.dhcp!.dhcpStatus.interfaceName); enabled = dhcpProvider.dhcp!.dhcpStatus.enabled; ipv4StartRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.rangeStart; diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 3041da4..a46dab7 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -59,7 +59,7 @@ class _UpstreamDnsScreenState extends State { }); } } - upstreamMode = dnsProvider.dnsInfo!.upstreamMode; + upstreamMode = dnsProvider.dnsInfo!.upstreamMode ?? ""; validValues = true; super.initState(); } From d43398e6e8725abf47c856ac654379b8d0ab7221 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 9 Jul 2023 22:16:25 +0200 Subject: [PATCH 255/676] Added edit rewrite rules --- lib/l10n/app_en.arb | 8 +- lib/l10n/app_es.arb | 8 +- lib/providers/rewrite_rules_provider.dart | 27 ++ ...rite_modal.dart => dns_rewrite_modal.dart} | 121 +++++--- .../settings/dns_rewrites/dns_rewrites.dart | 265 ++++++++++++------ .../settings/dns_rewrites/rule_modal.dart | 0 .../dns_rewrites/server_version_needed.dart | 46 +++ lib/services/http_requests.dart | 34 ++- 8 files changed, 391 insertions(+), 118 deletions(-) rename lib/screens/settings/dns_rewrites/{add_dns_rewrite_modal.dart => dns_rewrite_modal.dart} (56%) create mode 100644 lib/screens/settings/dns_rewrites/rule_modal.dart create mode 100644 lib/screens/settings/dns_rewrites/server_version_needed.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 1504716..bd82ea1 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -630,5 +630,11 @@ "combinedChartDescription": "Combine all charts into one", "statistics": "Statistics", "errorLoadFilters": "Error when loading filters.", - "clientRemovedSuccessfully": "Client removed successfully." + "clientRemovedSuccessfully": "Client removed successfully.", + "editRewriteRule": "Edit rewrite rule", + "dnsRewriteRuleUpdated": "DNS rewrite rule updated successfully", + "dnsRewriteRuleNotUpdated": "DNS rewrite rule could not be updated", + "updatingRule": "Updating rule...", + "serverUpdateNeeded": "Server update needed", + "updateYourServer": "Update your AdGuard Home server to {version} or greater to use this feature." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 88d248f..76f97e9 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -630,5 +630,11 @@ "combinedChartDescription": "Combina todos los gráficos en uno solo", "statistics": "Estadísticas", "errorLoadFilters": "Error al cargar los filtros.", - "clientRemovedSuccessfully": "Cliente eliminado correctamente." + "clientRemovedSuccessfully": "Cliente eliminado correctamente.", + "editRewriteRule": "Editar reescritura DNS", + "dnsRewriteRuleUpdated": "Regla de reescritura DNS actualizada correctamente", + "dnsRewriteRuleNotUpdated": "La regla de reescritura DNS no ha podido ser actualizada", + "updatingRule": "Actualizando regla...", + "serverUpdateNeeded": "Actualización del servidor necesaria", + "updateYourServer": "Actualiza tu servidor AdGuard Home a {version} para utilizar esta funcionalidad." } \ No newline at end of file diff --git a/lib/providers/rewrite_rules_provider.dart b/lib/providers/rewrite_rules_provider.dart index 1db40c5..1e3bda3 100644 --- a/lib/providers/rewrite_rules_provider.dart +++ b/lib/providers/rewrite_rules_provider.dart @@ -54,6 +54,33 @@ class RewriteRulesProvider with ChangeNotifier { } } + Future editDnsRewrite(RewriteRules newRule, RewriteRules oldRule) async { + final result = await _serversProvider!.apiClient!.updateRewriteRule( + body: { + "target": { + "answer": oldRule.answer, + "domain": oldRule.domain + }, + "update": { + "answer": newRule.answer, + "domain": newRule.domain + } + } + ); + + if (result['result'] == 'success') { + List data = rewriteRules!; + final index = data.indexOf(oldRule); + data[index] = newRule; + setRewriteRulesData(data); + return true; + } + else { + notifyListeners(); + return false; + } + } + Future deleteDnsRewrite(RewriteRules rule) async { final result = await _serversProvider!.apiClient!.deleteDnsRewriteRule( data: { diff --git a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart similarity index 56% rename from lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart rename to lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart index 24ee717..b43c168 100644 --- a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart @@ -1,25 +1,34 @@ 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/settings/dns_rewrites/server_version_needed.dart'; + +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; -class AddDnsRewriteModal extends StatefulWidget { - final void Function(RewriteRules) onConfirm; +class DnsRewriteModal extends StatefulWidget { + final void Function(RewriteRules newRule, RewriteRules? previousRule) onConfirm; final bool dialog; + final RewriteRules? rule; + final void Function(RewriteRules) onDelete; - const AddDnsRewriteModal({ + const DnsRewriteModal({ Key? key, required this.onConfirm, - required this.dialog + required this.dialog, + this.rule, + required this.onDelete }) : super(key: key); @override - State createState() => _AddDnsRewriteModalState(); + State createState() => _AddDnsRewriteModalState(); } -class _AddDnsRewriteModalState extends State { +class _AddDnsRewriteModalState extends State { final TextEditingController domainController = TextEditingController(); String? domainError; final TextEditingController answerController = TextEditingController(); @@ -50,8 +59,20 @@ class _AddDnsRewriteModalState extends State { } } + @override + void initState() { + if (widget.rule != null) { + domainController.text = widget.rule!.domain; + answerController.text = widget.rule!.answer; + validData = true; + } + super.initState(); + } + @override Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + Widget content() { return Column( mainAxisSize: MainAxisSize.min, @@ -68,14 +89,18 @@ class _AddDnsRewriteModalState extends State { Padding( padding: const EdgeInsets.only(top: 24), child: Icon( - Icons.add, + widget.rule != null + ? Icons.edit + : Icons.add, size: 24, color: Theme.of(context).listTileTheme.iconColor ), ), const SizedBox(height: 16), Text( - AppLocalizations.of(context)!.addDnsRewrite, + widget.rule != null + ? AppLocalizations.of(context)!.editRewriteRule + : AppLocalizations.of(context)!.addDnsRewrite, textAlign: TextAlign.center, style: TextStyle( fontSize: 24, @@ -131,34 +156,64 @@ class _AddDnsRewriteModalState extends State { Padding( padding: const EdgeInsets.all(24), child: Row( - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel), + if (widget.rule != null) TextButton( + onPressed: () { + Navigator.pop(context); + widget.onDelete( + RewriteRules( + domain: domainController.text, + answer: answerController.text + ) + ); + }, + child: Text(AppLocalizations.of(context)!.delete), ), - const SizedBox(width: 20), - TextButton( - onPressed: validData == true - ? () { - Navigator.pop(context); - widget.onConfirm( - RewriteRules( - domain: domainController.text, - answer: answerController.text - ) - ); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: validData == true - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + if (widget.rule == null) const SizedBox(), + Row( + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel), ), - ), - ), + const SizedBox(width: 20), + TextButton( + onPressed: validData == true + ? () { + if (serverVersionIsAhead( + currentVersion: statusProvider.serverStatus!.serverVersion, + referenceVersion: '0.107.33', + referenceVersionBeta: '0.108.0-b.39' + )) { + Navigator.pop(context); + widget.onConfirm( + RewriteRules( + domain: domainController.text, + answer: answerController.text + ), + widget.rule + ); + } + else { + showDialog( + context: context, + builder: (context) => const ServerVersionNeeded(version: 'v0.107.33') + ); + } + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, + style: TextStyle( + color: validData == true + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + ), + ), + ), + ], + ) ], ), ), diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 17f267e..fda731e 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -3,11 +3,12 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart'; import 'package:adguard_home_manager/screens/settings/dns_rewrites/delete_dns_rewrite.dart'; +import 'package:adguard_home_manager/screens/settings/dns_rewrites/dns_rewrite_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -24,10 +25,29 @@ class DnsRewritesScreen extends StatefulWidget { } class _DnsRewritesScreenState extends State { + late bool isVisible; + final ScrollController scrollController = ScrollController(); + @override void initState() { Provider.of(context, listen: false).fetchRules(); super.initState(); + + isVisible = true; + scrollController.addListener(() { + if (scrollController.position.userScrollDirection == ScrollDirection.reverse) { + if (mounted && isVisible == true) { + setState(() => isVisible = false); + } + } + else { + if (scrollController.position.userScrollDirection == ScrollDirection.forward) { + if (mounted && isVisible == false) { + setState(() => isVisible = true); + } + } + } + }); } @override @@ -61,7 +81,7 @@ class _DnsRewritesScreenState extends State { } } - void addDnsRewrite(RewriteRules rule) async { + void addDnsRewrite(RewriteRules rule, _) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingRewrite); @@ -85,6 +105,30 @@ class _DnsRewritesScreenState extends State { } } + void updateRewriteRule(RewriteRules newRule, RewriteRules? previousRule) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.updatingRule); + + final result = await rewriteRulesProvider.editDnsRewrite(newRule, previousRule!); + + processModal.close(); + + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsRewriteRuleUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsRewriteRuleNotUpdated, + color: Colors.red + ); + } + } + Widget generateBody() { switch (rewriteRulesProvider.loadStatus) { case LoadStatus.loading: @@ -121,70 +165,102 @@ class _DnsRewritesScreenState extends State { } }, child: ListView.builder( + controller: scrollController, padding: const EdgeInsets.only(top: 0), itemCount: rewriteRulesProvider.rewriteRules!.length, itemBuilder: (context, index) => Card( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Padding( - padding: const EdgeInsets.only( - left: 16, top: 16, bottom: 16, right: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.domain}: ", - style: TextStyle( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Text( - rewriteRulesProvider.rewriteRules![index].domain, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - const SizedBox(height: 3), - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.answer}: ", - style: TextStyle( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Text( - rewriteRulesProvider.rewriteRules![index].answer, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ], - ), - IconButton( - onPressed: () => { - showDialog( + child: InkWell( + onTap: () => { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => DnsRewriteModal( + onConfirm: updateRewriteRule, + dialog: true, + rule: rewriteRulesProvider.rewriteRules![index], + onDelete: (rule) => showDialog( context: context, builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(rewriteRulesProvider.rewriteRules![index]) + onConfirm: () => deleteDnsRewrite(rule) ) - ) - }, - icon: const Icon(Icons.delete), - tooltip: AppLocalizations.of(context)!.delete, + ), + ), ) - ], + } + else { + showModalBottomSheet( + context: context, + builder: (context) => DnsRewriteModal( + onConfirm: updateRewriteRule, + dialog: false, + rule: rewriteRulesProvider.rewriteRules![index], + onDelete: (rule) => showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rule) + ) + ), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + ) + } + }, + borderRadius: BorderRadius.circular(10), + child: Padding( + padding: const EdgeInsets.only( + left: 16, top: 16, bottom: 16, right: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.domain}: ", + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Text( + rewriteRulesProvider.rewriteRules![index].domain, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + const SizedBox(height: 3), + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.answer}: ", + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Text( + rewriteRulesProvider.rewriteRules![index].answer, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ], + ), + Icon( + Icons.keyboard_arrow_right_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ) + ], + ), ), ), ) @@ -237,31 +313,56 @@ class _DnsRewritesScreenState extends State { title: Text(AppLocalizations.of(context)!.dnsRewrites), centerTitle: false, ), - body: generateBody(), - floatingActionButton: FloatingActionButton( - onPressed: () => { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => AddDnsRewriteModal( - onConfirm: addDnsRewrite, - dialog: true, + body: Stack( + children: [ + generateBody(), + AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: isVisible ? + appConfigProvider.showingSnackbar + ? 70 : 20 + : -70, + right: 20, + child: FloatingActionButton( + onPressed: () => { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => DnsRewriteModal( + onConfirm: addDnsRewrite, + dialog: true, + onDelete: (rule) => showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rule) + ) + ), + ), + ) + } + else { + showModalBottomSheet( + context: context, + builder: (context) => DnsRewriteModal( + onConfirm: addDnsRewrite, + dialog: false, + onDelete: (rule) => showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rule) + ) + ), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ) + } + }, + child: const Icon(Icons.add), ), - ) - } - else { - showModalBottomSheet( - context: context, - builder: (context) => AddDnsRewriteModal( - onConfirm: addDnsRewrite, - dialog: false, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ) - } - }, - child: const Icon(Icons.add), + ) + ], ), ); } diff --git a/lib/screens/settings/dns_rewrites/rule_modal.dart b/lib/screens/settings/dns_rewrites/rule_modal.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/screens/settings/dns_rewrites/server_version_needed.dart b/lib/screens/settings/dns_rewrites/server_version_needed.dart new file mode 100644 index 0000000..88888c6 --- /dev/null +++ b/lib/screens/settings/dns_rewrites/server_version_needed.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class ServerVersionNeeded extends StatelessWidget { + final String version; + + const ServerVersionNeeded({ + Key? key, + required this.version + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Column( + children: [ + Icon( + Icons.system_update_rounded, + size: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.serverUpdateNeeded, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: Text( + AppLocalizations.of(context)!.updateYourServer(version), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.confirm) + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index cb384b4..85de805 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -2164,7 +2164,6 @@ class ApiClient { } Future updateSafeSearchSettings({ - required Map body }) async { final result = await apiRequest( @@ -2196,6 +2195,39 @@ class ApiClient { return result; } } + + Future updateRewriteRule({ + required Map body + }) async { + final result = await apiRequest( + urlPath: '/rewrite/update', + method: 'put', + server: server, + type: 'update_rewrite', + body: body + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_rewrite', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } } Future checkAppUpdatesGitHub() async { From 97d113f16207987a74e2ac5c056265d5a95b8639 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 9 Jul 2023 22:29:41 +0200 Subject: [PATCH 256/676] Bug fixes --- lib/models/dns_info.dart | 2 +- lib/screens/logs/logs.dart | 2 +- lib/screens/settings/dhcp/dhcp.dart | 2 +- .../settings/encryption/encryption.dart | 52 ++++++++++--------- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 2f23fd5..10d5030 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -46,7 +46,7 @@ class DnsInfo { factory DnsInfo.fromJson(Map json) => DnsInfo( upstreamDns: json["upstream_dns"] != null ? List.from(json["upstream_dns"].map((x) => x)) : [], upstreamDnsFile: json["upstream_dns_file"], - bootstrapDns: List.from(json["bootstrap_dns"].map((x) => x)), + bootstrapDns: json["bootstrap_dns"] != null ? List.from(json["bootstrap_dns"].map((x) => x)) : [], protectionEnabled: json["protection_enabled"], ratelimit: json["ratelimit"], blockingMode: json["blocking_mode"], diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 5ff0097..f44a760 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -334,7 +334,7 @@ class _LogsState extends State { tooltip: AppLocalizations.of(context)!.filters, ) : const SizedBox(), - IconButton( + if (statusProvider.serverStatus != null) IconButton( tooltip: AppLocalizations.of(context)!.settings, onPressed: () => { if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index d0ab42c..402a063 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -59,7 +59,7 @@ class _DhcpScreenState extends State { if (dhcpProvider.dhcp != null) { setState(() { if (dhcpProvider.dhcp!.dhcpStatus.interfaceName != null && dhcpProvider.dhcp!.dhcpStatus.interfaceName != '') { - selectedInterface = dhcpProvider.dhcp!.networkInterfaces.firstWhere((iface) => iface.name == dhcpProvider.dhcp!.dhcpStatus.interfaceName); + try {selectedInterface = dhcpProvider.dhcp!.networkInterfaces.firstWhere((iface) => iface.name == dhcpProvider.dhcp!.dhcpStatus.interfaceName);} catch (_) {} enabled = dhcpProvider.dhcp!.dhcpStatus.enabled; ipv4StartRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.rangeStart; ipv4EndRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.rangeEnd ?? ''; diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 1282279..de75918 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -103,32 +103,34 @@ class _EncryptionSettingsWidgetState extends State { if (result['result'] == 'success') { await checkValidDataApi(data: result['data'].toJson()); - setState(() { - enabled = result['data'].enabled; - domainNameController.text = result['data'].serverName ?? ''; - redirectHttps = result['data'].forceHttps; - httpsPortController.text = result['data'].portHttps != null ? result['data'].portHttps.toString() : ''; - tlsPortController.text = result['data'].portDnsOverTls != null ? result['data'].portDnsOverTls.toString() : ''; - dnsOverQuicPortController.text = result['data'].portDnsOverQuic != null ? result['data'].portDnsOverQuic.toString() : ''; - if (result['data'].certificateChain != '') { - certificateOption = 1; - certificateContentController.text = decodeBase64(result['data'].certificateChain); - } - else { - certificateOption = 0; - certificatePathController.text = result['data'].certificatePath; - } - if (result['data'].privateKey != '' || result['data'].privateKeySaved == true) { - privateKeyOption = 1; - } - else { - privateKeyOption = 0; - privateKeyPathController.text = result['data'].privateKeyPath; - } - usePreviouslySavedKey = result['data'].privateKeySaved; + if (mounted) { + setState(() { + enabled = result['data'].enabled; + domainNameController.text = result['data'].serverName ?? ''; + redirectHttps = result['data'].forceHttps; + httpsPortController.text = result['data'].portHttps != null ? result['data'].portHttps.toString() : ''; + tlsPortController.text = result['data'].portDnsOverTls != null ? result['data'].portDnsOverTls.toString() : ''; + dnsOverQuicPortController.text = result['data'].portDnsOverQuic != null ? result['data'].portDnsOverQuic.toString() : ''; + if (result['data'].certificateChain != '') { + certificateOption = 1; + certificateContentController.text = decodeBase64(result['data'].certificateChain); + } + else { + certificateOption = 0; + certificatePathController.text = result['data'].certificatePath; + } + if (result['data'].privateKey != '' || result['data'].privateKeySaved == true) { + privateKeyOption = 1; + } + else { + privateKeyOption = 0; + privateKeyPathController.text = result['data'].privateKeyPath; + } + usePreviouslySavedKey = result['data'].privateKeySaved; - loadStatus = 1; - }); + loadStatus = 1; + }); + } } else { widget.appConfigProvider.addLog(result['log']); From 2fed0e584cdd32912cb161115aaf61f5a1eb9db1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 10 Jul 2023 20:45:03 +0200 Subject: [PATCH 257/676] Added date on home charts tooltip --- lib/l10n/app_en.arb | 17 +++++- lib/l10n/app_es.arb | 17 +++++- lib/screens/home/chart.dart | 22 ++++--- lib/screens/home/combined_chart.dart | 17 +++++- lib/screens/home/home.dart | 4 ++ lib/widgets/combined_line_chart.dart | 87 ++++++++++++++++++++++++---- lib/widgets/line_chart.dart | 53 ++++++++++++++++- 7 files changed, 194 insertions(+), 23 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index bd82ea1..942e952 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -636,5 +636,20 @@ "dnsRewriteRuleNotUpdated": "DNS rewrite rule could not be updated", "updatingRule": "Updating rule...", "serverUpdateNeeded": "Server update needed", - "updateYourServer": "Update your AdGuard Home server to {version} or greater to use this feature." + "updateYourServer": "Update your AdGuard Home server to {version} or greater to use this feature.", + "january": "January", + "february": "February", + "march": "March", + "april": "April", + "may": "May", + "june": "June", + "july": "July", + "august": "August", + "september": "September", + "october": "October", + "november": "November", + "december": "December", + "malwarePhising": "Malware/phising", + "queries": "Queries", + "adultSites": "Adult sites" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 76f97e9..6d335c6 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -636,5 +636,20 @@ "dnsRewriteRuleNotUpdated": "La regla de reescritura DNS no ha podido ser actualizada", "updatingRule": "Actualizando regla...", "serverUpdateNeeded": "Actualización del servidor necesaria", - "updateYourServer": "Actualiza tu servidor AdGuard Home a {version} para utilizar esta funcionalidad." + "updateYourServer": "Actualiza tu servidor AdGuard Home a {version} para utilizar esta funcionalidad.", + "january": "Enero", + "february": "Febrero", + "march": "Marzo", + "april": "Abril", + "may": "Mayo", + "june": "Junio", + "july": "Julio", + "august": "Agosto", + "september": "Septiembre", + "october": "Octubre", + "november": "Noviembre", + "december": "Diciembre", + "malwarePhising": "Malware/phising", + "queries": "Peticiones", + "adultSites": "Sitios de adultos" } \ No newline at end of file diff --git a/lib/screens/home/chart.dart b/lib/screens/home/chart.dart index cf2550a..f69f59d 100644 --- a/lib/screens/home/chart.dart +++ b/lib/screens/home/chart.dart @@ -11,6 +11,7 @@ class HomeChart extends StatelessWidget { final String primaryValue; final String secondaryValue; final Color color; + final int hoursInterval; const HomeChart({ Key? key, @@ -18,22 +19,24 @@ class HomeChart extends StatelessWidget { required this.label, required this.primaryValue, required this.secondaryValue, - required this.color + required this.color, + required this.hoursInterval }) : super(key: key); @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - bool isEmpty = true; - for (int item in data) { - if (item > 0) { - isEmpty = false; - break; - } - } + final bool isEmpty = data.any((i) => i == 0); if (!(appConfigProvider.hideZeroValues == true && isEmpty == true)) { + List dateTimes = []; + DateTime currentDate = DateTime.now().subtract(Duration(hours: hoursInterval*data.length+1)); + for (var i = 0; i < data.length; i++) { + currentDate = currentDate.add(Duration(hours: hoursInterval)); + dateTimes.add(currentDate); + } + return Column( children: [ Padding( @@ -109,6 +112,9 @@ class HomeChart extends StatelessWidget { child: CustomLineChart( data: data, color: color, + dates: dateTimes, + daysInterval: hoursInterval == 24, + context: context, ) ), ], diff --git a/lib/screens/home/combined_chart.dart b/lib/screens/home/combined_chart.dart index 3de92f9..d7328d1 100644 --- a/lib/screens/home/combined_chart.dart +++ b/lib/screens/home/combined_chart.dart @@ -20,7 +20,7 @@ class CombinedChartData { required this.totalQueries, this.blockedFilters, this.replacedSafeBrowsing, - this.replacedParental + this.replacedParental, }); } @@ -149,6 +149,15 @@ class CombinedHomeChart extends StatelessWidget { ); } + final hoursInterval = statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1; + + List dateTimes = []; + DateTime currentDate = DateTime.now().subtract(Duration(hours: hoursInterval*statusProvider.serverStatus!.stats.dnsQueries.length+1)); + for (var i = 0; i < statusProvider.serverStatus!.stats.dnsQueries.length; i++) { + currentDate = currentDate.add(Duration(hours: hoursInterval)); + dateTimes.add(currentDate); + } + if (width > 700) { return Column( children: [ @@ -170,6 +179,9 @@ class CombinedHomeChart extends StatelessWidget { width: double.maxFinite, child: CustomCombinedLineChart( inputData: data, + context: context, + dates: dateTimes, + daysInterval: hoursInterval == 24, ), ), ), @@ -241,6 +253,9 @@ class CombinedHomeChart extends StatelessWidget { width: double.maxFinite, child: CustomCombinedLineChart( inputData: data, + context: context, + dates: dateTimes, + daysInterval: hoursInterval == 24, ), ), const SizedBox(height: 16), diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index e288175..41f8b26 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -131,6 +131,7 @@ class _HomeState extends State { primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", color: Colors.blue, + hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, ), ), FractionallySizedBox( @@ -141,6 +142,7 @@ class _HomeState extends State { primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.red, + hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, ), ), FractionallySizedBox( @@ -151,6 +153,7 @@ class _HomeState extends State { primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.green, + hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, ), ), FractionallySizedBox( @@ -161,6 +164,7 @@ class _HomeState extends State { primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.orange, + hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, ), ), ], diff --git a/lib/widgets/combined_line_chart.dart b/lib/widgets/combined_line_chart.dart index 0ce6a58..14d6d3e 100644 --- a/lib/widgets/combined_line_chart.dart +++ b/lib/widgets/combined_line_chart.dart @@ -1,20 +1,57 @@ -import 'package:adguard_home_manager/screens/home/combined_chart.dart'; import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/home/combined_chart.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class CustomCombinedLineChart extends StatelessWidget { final CombinedChartData inputData; + final List dates; + final BuildContext context; + final bool daysInterval; const CustomCombinedLineChart({ Key? key, required this.inputData, + required this.context, + required this.dates, + required this.daysInterval }) : super(key: key); LineChartData mainData(Map data, ThemeMode selectedTheme) { + String chartDate(DateTime date) { + String twoDigits(int number) => number.toString().padLeft(2, '0'); + + String getMonth(int month) { + final List months = [ + AppLocalizations.of(context)!.january, + AppLocalizations.of(context)!.february, + AppLocalizations.of(context)!.march, + AppLocalizations.of(context)!.april, + AppLocalizations.of(context)!.may, + AppLocalizations.of(context)!.june, + AppLocalizations.of(context)!.july, + AppLocalizations.of(context)!.august, + AppLocalizations.of(context)!.september, + AppLocalizations.of(context)!.october, + AppLocalizations.of(context)!.november, + AppLocalizations.of(context)!.december, + ]; + return months[month-1]; + } + + if (daysInterval == true) { + return "${date.day} ${getMonth(date.month).substring(0, 3)}"; + } + else { + return "${date.day} ${getMonth(date.month).substring(0, 3)} ${twoDigits(date.hour)}:00"; + } + } + return LineChartData( gridData: FlGridData( show: false, @@ -49,14 +86,26 @@ class CustomCombinedLineChart extends StatelessWidget { tooltipBgColor: selectedTheme == ThemeMode.light ? const Color.fromRGBO(220, 220, 220, 0.9) : const Color.fromRGBO(35, 35, 35, 0.9), - getTooltipItems: (items) => items.asMap().entries.map((item) => LineTooltipItem( - "${data['lines'][item.key]['label']}: ${item.value.y.toInt().toString()}", - TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: data['lines'][item.key]['color'] - ) - )).toList() + getTooltipItems: (items) { + return [ + LineTooltipItem( + chartDate(dates[items[0].x.toInt()]), + TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: Theme.of(context).colorScheme.onSurface + ) + ), + ...items.sublist(0, items.length-1).asMap().entries.map((item) => LineTooltipItem( + "${data['lines'][item.key]['label']}: ${item.value.y.toInt().toString()}", + TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: data['lines'][item.key]['color'] + ) + )) + ]; + } ), ) ); @@ -89,8 +138,22 @@ class CustomCombinedLineChart extends StatelessWidget { return formattedData; } - List> toDraw = []; + List datesLine(int number) { + final List formattedData = []; + for (int i = 0; i < number; i++) { + formattedData.add( + FlSpot( + i.toDouble(), + 0 + ) + ); + } + + return formattedData; + } + + List> toDraw = []; toDraw.add({ "data": dataLine(unformattedData.totalQueries.data), "color": unformattedData.totalQueries.color, @@ -117,6 +180,10 @@ class CustomCombinedLineChart extends StatelessWidget { "label": unformattedData.replacedParental!.label }); } + toDraw.add({ + "data": datesLine(dates.length), + "color": Colors.transparent, + }); return { 'lines': toDraw, diff --git a/lib/widgets/line_chart.dart b/lib/widgets/line_chart.dart index 78338a5..92814b1 100644 --- a/lib/widgets/line_chart.dart +++ b/lib/widgets/line_chart.dart @@ -1,20 +1,56 @@ import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; - class CustomLineChart extends StatelessWidget { final List data; final Color color; + final List dates; + final bool daysInterval; + final BuildContext context; const CustomLineChart({ Key? key, required this.data, - required this.color + required this.color, + required this.dates, + required this.daysInterval, + required this.context }) : super(key: key); + String chartDate(DateTime date) { + String twoDigits(int number) => number.toString().padLeft(2, '0'); + + String getMonth(int month) { + final List months = [ + AppLocalizations.of(context)!.january, + AppLocalizations.of(context)!.february, + AppLocalizations.of(context)!.march, + AppLocalizations.of(context)!.april, + AppLocalizations.of(context)!.may, + AppLocalizations.of(context)!.june, + AppLocalizations.of(context)!.july, + AppLocalizations.of(context)!.august, + AppLocalizations.of(context)!.september, + AppLocalizations.of(context)!.october, + AppLocalizations.of(context)!.november, + AppLocalizations.of(context)!.december, + ]; + + return months[month-1]; + } + + if (daysInterval == true) { + return "${date.day} ${getMonth(date.month).substring(0, 3)}"; + } + else { + return "${date.day} ${getMonth(date.month).substring(0, 3)} ${twoDigits(date.hour)}:00"; + } + } + LineChartData mainData(Map data, ThemeMode selectedTheme) { return LineChartData( gridData: FlGridData( @@ -43,6 +79,11 @@ class CustomLineChart extends StatelessWidget { color: color.withOpacity(0.2) ), ), + LineChartBarData( + spots: data['data'], + color: Colors.transparent, + barWidth: 0, + ), ], lineTouchData: LineTouchData( enabled: true, @@ -51,6 +92,14 @@ class CustomLineChart extends StatelessWidget { ? const Color.fromRGBO(220, 220, 220, 0.9) : const Color.fromRGBO(35, 35, 35, 0.9), getTooltipItems: (items) => [ + LineTooltipItem( + chartDate(dates[items[0].x.toInt()]), + TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: Theme.of(context).colorScheme.onSurface + ) + ), LineTooltipItem( items[0].y.toInt().toString(), TextStyle( From 8cce3268c3f0c6b4c345cf8c7f50fdbac2e07130 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 14 Jul 2023 19:39:35 +0200 Subject: [PATCH 258/676] Added quick filters --- lib/l10n/app_en.arb | 3 ++- lib/l10n/app_es.arb | 3 ++- lib/screens/logs/logs_filters_modal.dart | 33 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 942e952..8d4ab5f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -651,5 +651,6 @@ "december": "December", "malwarePhising": "Malware/phising", "queries": "Queries", - "adultSites": "Adult sites" + "adultSites": "Adult sites", + "quickFilters": "Quick filters" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 6d335c6..eddf876 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -651,5 +651,6 @@ "december": "Diciembre", "malwarePhising": "Malware/phising", "queries": "Peticiones", - "adultSites": "Sitios de adultos" + "adultSites": "Sitios de adultos", + "quickFilters": "Filtros rápidos" } \ No newline at end of file diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/logs_filters_modal.dart index 6b040d3..5251d9a 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/logs_filters_modal.dart @@ -8,6 +8,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/clients_modal.dart'; import 'package:adguard_home_manager/screens/logs/filter_status_modal.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/constants/enums.dart'; @@ -219,6 +220,38 @@ class _LogsFiltersModalWidgetState extends State { ) : null, ), + SectionLabel( + label: AppLocalizations.of(context)!.quickFilters, + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 16 + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + FilterChip( + selected: logsProvider.selectedResultStatus == "all", + label: Text(AppLocalizations.of(context)!.all), + onSelected: (_) => logsProvider.setSelectedResultStatus("all") + ), + FilterChip( + selected: logsProvider.selectedResultStatus == "processed" || + logsProvider.selectedResultStatus == "whitelisted", + label: Text(AppLocalizations.of(context)!.allowed), + onSelected: (_) => logsProvider.setSelectedResultStatus("processed") + ), + FilterChip( + selected: logsProvider.selectedResultStatus == "blocked" || + logsProvider.selectedResultStatus == "blocked_safebrowsing" || + logsProvider.selectedResultStatus == "blocked_parental" || + logsProvider.selectedResultStatus == "safe_search", + label: Text(AppLocalizations.of(context)!.blocked), + onSelected: (_) => logsProvider.setSelectedResultStatus("blocked") + ), + ], + ), + const Padding(padding: EdgeInsets.all(8)), CustomListTile( title: AppLocalizations.of(context)!.responseStatus, subtitle: "${translatedString[logsProvider.selectedResultStatus]}", From 2d3a858f597bf12668b2ed1414d151c75c9dc660 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 14 Jul 2023 19:51:18 +0200 Subject: [PATCH 259/676] Added search domain internet --- lib/constants/urls.dart | 1 + lib/l10n/app_en.arb | 3 ++- lib/l10n/app_es.arb | 3 ++- lib/screens/logs/log_details_screen.dart | 14 +++++++++++++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart index cd92b8c..6626285 100644 --- a/lib/constants/urls.dart +++ b/lib/constants/urls.dart @@ -4,4 +4,5 @@ class Urls { static const String customRuleDocs = "https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters"; static const String getReleasesGitHub = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases"; static const String adGuardHomeReleasesTags = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/tags"; + static const String googleSearchUrl = "https://www.google.com/search"; } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 8d4ab5f..f203286 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -652,5 +652,6 @@ "malwarePhising": "Malware/phising", "queries": "Queries", "adultSites": "Adult sites", - "quickFilters": "Quick filters" + "quickFilters": "Quick filters", + "searchDomainInternet": "Search domain on the Internet" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index eddf876..ab71f10 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -652,5 +652,6 @@ "malwarePhising": "Malware/phising", "queries": "Peticiones", "adultSites": "Sitios de adultos", - "quickFilters": "Filtros rápidos" + "quickFilters": "Filtros rápidos", + "searchDomainInternet": "Buscar dominio en internet" } \ No newline at end of file diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 440c9c1..96ac2bf 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -8,6 +8,8 @@ import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/screens/logs/log_list_tile.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; +import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -223,7 +225,7 @@ class LogDetailsScreen extends StatelessWidget { children: [ Row( children: [ - IconButton( + IconButton( onPressed: () => Navigator.pop(context), icon: const Icon(Icons.clear_rounded) ), @@ -238,6 +240,11 @@ class LogDetailsScreen extends StatelessWidget { ), Row( children: [ + IconButton( + onPressed: () => openUrl("${Urls.googleSearchUrl}?q=${log.question.name}"), + icon: const Icon(Icons.travel_explore_rounded), + tooltip: AppLocalizations.of(context)!.searchDomainInternet + ), IconButton( onPressed: log.question.name != null ? () => blockUnblock( @@ -276,6 +283,11 @@ class LogDetailsScreen extends StatelessWidget { centerTitle: false, title: Text(AppLocalizations.of(context)!.logDetails), actions: [ + IconButton( + onPressed: () => openUrl("${Urls.googleSearchUrl}?q=${log.question.name}"), + icon: const Icon(Icons.travel_explore_rounded), + tooltip: AppLocalizations.of(context)!.searchDomainInternet + ), if (statusProvider.filteringStatus != null) IconButton( onPressed: log.question.name != null ? () => blockUnblock( From 969b9796c0d56f36d39fbc826356233c48e6e353 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 26 Jul 2023 18:49:48 +0200 Subject: [PATCH 260/676] Bugfix --- lib/models/dns_info.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 10d5030..528ca5b 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -9,7 +9,7 @@ class DnsInfo { bool dnssecEnabled; bool disableIpv6; String? upstreamMode; - int cacheSize; + int? cacheSize; int cacheTtlMin; int cacheTtlMax; bool cacheOptimistic; From 314face934e242d2717478b33c3b1592b9cc9b55 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 11:28:46 +0800 Subject: [PATCH 261/676] Create app_zh.arb --- lib/l10n/app_zh.arb | 657 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 657 insertions(+) create mode 100644 lib/l10n/app_zh.arb diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb new file mode 100644 index 0000000..01f17ee --- /dev/null +++ b/lib/l10n/app_zh.arb @@ -0,0 +1,657 @@ +{ + "home": "主页", + "settings": "设置", + "connect": "连接", + "servers": "æœåС噍", + "createConnection": "新建连接", + "name": "åç§°", + "ipDomain": "IPåœ°å€æˆ–域å", + "path": "路径", + "port": "端å£", + "username": "用户å", + "password": "密ç ", + "defaultServer": "默认æœåС噍", + "general": "常规", + "connection": "连接", + "authentication": "身份验è¯", + "other": "å…¶ä»–", + "invalidPort": "无效端å£", + "invalidPath": "无效路径", + "invalidIpDomain": "无效IP或域å ", + "ipDomainNotEmpty": "IP 或域åä¸èƒ½ä¸ºç©º", + "nameNotEmpty": "åç§°ä¸èƒ½ä¸ºç©º", + "invalidUsernamePassword": "ç”¨æˆ·åæˆ–å¯†ç æ— æ•ˆ", + "tooManyAttempts": "å°è¯•次数过多,请ç¨åŽå†è¯•", + "cantReachServer": "无法连接æœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥è¿žæŽ¥ä¿¡æ¯æ˜¯å¦æ­£ç¡®", + "sslError": "SSL 错误。转到 设置 > 高级设置 å¹¶å¯ç”¨ 忽略 SSL 验è¯", + "unknownError": "未知错误", + "connectionNotCreated": "连接无法创建", + "connecting": "连接æˆåŠŸ...", + "connected": "已连接", + "selectedDisconnected": "已选择但未连接", + "connectionDefaultSuccessfully": "将连接设置为默认æˆåŠŸ", + "connectionDefaultFailed": "连接无法设置为默认", + "noSavedConnections": "未ä¿å­˜è¿žæŽ¥", + "cannotConnect": "无法连接æœåС噍", + "connectionRemoved": "移除连接æˆåŠŸ", + "connectionCannotBeRemoved": "无法删除连接", + "remove": "移除", + "removeWarning": "您确定è¦åˆ é™¤ä¸Žæ­¤ AdGuard Home æœåŠ¡å™¨çš„è¿žæŽ¥å—?", + "cancel": "å–æ¶ˆ", + "defaultConnection": "默认链接", + "setDefault": "设为默认", + "edit": "编辑", + "delete": "删除", + "save": "ä¿å­˜", + "serverStatus": "æœåС噍è¿è¡Œçж况", + "connectionNotUpdated": "连接未更新", + "ruleFilteringWidget": "规则过滤", + "safeBrowsingWidget": "æµè§ˆå®‰å…¨", + "parentalFilteringWidget": "家长控制", + "safeSearchWidget": "安全æœç´¢", + "ruleFiltering": "规则过滤", + "safeBrowsing": "æµè§ˆå®‰å…¨", + "parentalFiltering": "家长控制", + "safeSearch": "安全æœç´¢", + "serverStatusNotRefreshed": "无法刷新æœåŠ¡å™¨çŠ¶æ€", + "loadingStatus": "正在加载状æ€...", + "errorLoadServerStatus": "æœåŠ¡å™¨çŠ¶æ€æ— æ³•加载", + "topQueriedDomains": "è¯·æ±‚åŸŸåæŽ’行", + "viewMore": "查看更多", + "topClients": "客户端排行", + "topBlockedDomains": "è¢«æ‹¦æˆªåŸŸåæŽ’行", + "appSettings": "应用设置", + "theme": "主题", + "light": "白", + "dark": "黑", + "systemDefined": "系统定义", + "close": "关闭", + "connectedTo": "连接到:", + "selectedServer": "选定的æœåŠ¡å™¨ï¼š", + "noServerSelected": "未选择æœåС噍", + "manageServer": "ç®¡ç†æœåС噍", + "allProtections": "æ‰€æœ‰ä¿æŠ¤", + "userNotEmpty": "用户åä¸èƒ½ä¸ºç©º", + "passwordNotEmpty": "密ç ä¸èƒ½ä¸ºç©º", + "examplePath": "示例: /adguard", + "helperPath": "如果您使用的是åå‘代ç†", + "aboutApp": "关于应用程åº", + "appVersion": "应用版本", + "createdBy": "制作", + "clients": "客户端", + "allowed": "å…许", + "blocked": "拦截", + "noClientsList": "列表中没有客户端", + "activeClients": "活动的", + "removeClient": "删除客户端", + "removeClientMessage": "您确定è¦ä»Žåˆ—表中删除此客户端å—?", + "confirm": "确认", + "removingClient": "删除客户端...", + "clientNotRemoved": "客户端无法从列表中删除", + "addClient": "添加客户端", + "list": "列表", + "ipAddress": "IP地å€", + "ipNotValid": "IPåœ°å€æ— æ•ˆ", + "clientAddedSuccessfully": "客户端æˆåŠŸæ·»åŠ åˆ°åˆ—è¡¨ä¸­", + "addingClient": "添加客户端...", + "clientNotAdded": "客户端无法添加到列表中", + "clientAnotherList": "这个客户端还在å¦ä¸€ä¸ªåˆ—表中", + "noSavedLogs": "没有ä¿å­˜çš„æ—¥å¿—", + "logs": "日志", + "copyLogsClipboard": "将日志å¤åˆ¶åˆ°å‰ªè´´æ¿", + "logsCopiedClipboard": "日志å¤åˆ¶åˆ°å‰ªè´´æ¿", + "advancedSettings": "高级设置", + "dontCheckCertificate": "䏿£€æŸ¥ SSL è¯ä¹¦", + "dontCheckCertificateDescription": "忽略æœåŠ¡å™¨çš„ SSL è¯ä¹¦éªŒè¯", + "advancedSetupDescription": "高级选项", + "settingsUpdatedSuccessfully": "设置æˆåŠŸæ›´æ–°", + "cannotUpdateSettings": "设置无法更新", + "restartAppTakeEffect": "釿–°å¯åŠ¨åº”ç”¨ç¨‹åº", + "loadingLogs": "加载日志...", + "logsNotLoaded": "日志列表无法加载", + "processed": "已处ç†\n无列表拦截", + "processedRow": "已处ç†ï¼ˆæ— åˆ—表拦截)", + "blockedBlacklist": "已拦截\n黑åå•", + "blockedBlacklistRow": "已拦截(黑åå•)", + "blockedSafeBrowsing": "已拦截\n安全æµè§ˆ", + "blockedSafeBrowsingRow": "已拦截(安全æµè§ˆï¼‰", + "blockedParental": "已拦截\n家长过滤", + "blockedParentalRow": "已拦截(家长过滤)", + "blockedInvalid": "已拦截\n无效", + "blockedInvalidRow": "已拦截(无效)", + "blockedSafeSearch": "已拦截\n安全æœç´¢", + "blockedSafeSearchRow": "已拦截(安全æœç´¢ï¼‰", + "blockedService": "已拦截\n已拦截的æœåŠ¡", + "blockedServiceRow": "已拦截(已拦截的æœåŠ¡ï¼‰", + "processedWhitelist": "已处ç†\n白åå•", + "processedWhitelistRow": "已处ç†ï¼ˆç™½åå•)", + "processedError": "已处ç†\n错误", + "processedErrorRow": "已处ç†ï¼ˆé”™è¯¯ï¼‰", + "rewrite": "é‡å†™", + "status": "状æ€", + "result": "结果", + "time": "æ—¶é—´", + "blocklist": "黑åå•列表", + "request": "请求", + "domain": "域å", + "type": "类型", + "clas": "类别", + "response": "å“应", + "dnsServer": "DNS æœåС噍", + "elapsedTime": "å¤„ç†æ—¶é—´", + "responseCode": "å“应代ç ", + "client": "客户端", + "deviceIp": "IP 地å€", + "deviceName": "åç§°", + "logDetails": "日志详细信æ¯", + "blockingRule": "拦截规则", + "blockDomain": "拦截域å", + "couldntGetFilteringStatus": "无法获å–过滤状æ€", + "unblockDomain": "è§£é™¤åŸŸåæ‹¦æˆª", + "userFilteringRulesNotUpdated": "用户过滤规则未能更新", + "userFilteringRulesUpdated": "用户过滤规则已æˆåŠŸæ›´æ–°", + "savingUserFilters": "正在ä¿å­˜ç”¨æˆ·è¿‡æ»¤å™¨...", + "filters": "过滤器", + "logsOlderThan": "早于日志", + "responseStatus": "å“应状æ€", + "selectTime": "选择时间", + "notSelected": "未选定", + "resetFilters": "é‡ç½®è¿‡æ»¤å™¨", + "noLogsDisplay": "æ— æ—¥å¿—å¯æ˜¾ç¤º", + "noLogsThatOld": "å¯èƒ½æ²¡æœ‰ä¿å­˜é€‰å®šæ—¶é—´çš„æ—¥å¿—。å°è¯•选择更近的时间。", + "apply": "应用", + "selectAll": "全选", + "unselectAll": "å–æ¶ˆå…¨é€‰", + "all": "全部", + "filtered": "已筛选", + "checkAppLogs": "检查应用日志", + "refresh": "刷新", + "search": "æœç´¢", + "dnsQueries": "DNS 查询", + "average": "å¹³å‡å€¼", + "blockedFilters": "已被过滤器拦截", + "malwarePhisingBlocked": "è¢«æ‹¦æˆªçš„æ¶æ„软件/é’“é±¼", + "blockedAdultWebsites": "被拦截的æˆäººç½‘ç«™", + "generalSettings": "常规设置", + "generalSettingsDescription": "å„ç§ä¸åŒçš„设置", + "hideZeroValues": "éšè—零值", + "hideZeroValuesDescription": "在主å±å¹•上éšè—零值å—", + "webAdminPanel": "Web 管ç†é¢æ¿", + "visitGooglePlay": "访问 Google Play 页é¢", + "gitHub": "å¼€æºä»£ç å¯åœ¨ GitHub 上获得", + "blockClient": "拦截客户端", + "selectTags": "选择标签", + "noTagsSelected": "未选择标签", + "tags": "标签", + "identifiers": "标识符", + "identifier": "标识符", + "identifierHelper": "IP 地å€ã€CIDRã€MAC åœ°å€æˆ–客户端ID", + "noIdentifiers": "未添加标识符", + "useGlobalSettings": "使用全局设置", + "enableFiltering": "å¯ç”¨è¿‡æ»¤", + "enableSafeBrowsing": "å¯ç”¨å®‰å…¨æµè§ˆ", + "enableParentalControl": "å¯ç”¨å®¶é•¿æŽ§åˆ¶", + "enableSafeSearch": "å¯ç”¨å®‰å…¨æœç´¢", + "blockedServices": "被拦截的æœåŠ¡", + "selectBlockedServices": "é€‰æ‹©è¦æ‹¦æˆªçš„æœåŠ¡", + "noBlockedServicesSelected": "未选择被拦截的æœåŠ¡", + "services": "æœåŠ¡", + "servicesBlocked": "被拦截的æœåŠ¡", + "tagsSelected": "已选择标签", + "upstreamServers": "上游æœåС噍", + "serverAddress": "æœåŠ¡å™¨åœ°å€", + "noUpstreamServers": "无上游æœåŠ¡å™¨ã€‚", + "willBeUsedGeneralServers": "将使用常规上游æœåŠ¡å™¨ã€‚", + "added": "已添加", + "clientUpdatedSuccessfully": "客户端已æˆåŠŸæ›´æ–°", + "clientNotUpdated": "客户端未能更新", + "clientDeletedSuccessfully": "客户端已æˆåŠŸåˆ é™¤", + "clientNotDeleted": "客户端未能删除", + "options": "选项", + "loadingFilters": "正在加载过滤器...", + "filtersNotLoaded": "无法加载过滤器。", + "whitelists": "白åå•", + "blacklists": "黑åå•", + "rules": "规则", + "customRules": "自定义规则", + "enabledRules": "å·²å¯ç”¨çš„规则", + "enabled": "å·²å¯ç”¨", + "disabled": "å·²ç¦ç”¨", + "rule": "规则", + "addCustomRule": "添加自定义规则", + "removeCustomRule": "移除自定义规则", + "removeCustomRuleMessage": "您确定è¦ç§»é™¤æ­¤è‡ªå®šä¹‰è§„则å—?", + "updatingRules": "正在更新自定义规则...", + "ruleRemovedSuccessfully": "规则已æˆåŠŸç§»é™¤", + "ruleNotRemoved": "无法移除规则", + "ruleAddedSuccessfully": "规则已æˆåŠŸæ·»åŠ ", + "ruleNotAdded": "无法添加规则", + "noCustomFilters": "无自定义过滤器", + "noBlockedClients": "无已拦截的客户端", + "noBlackLists": "无黑åå•", + "noWhiteLists": "无白åå•", + "addWhitelist": "添加白åå•", + "addBlacklist": "添加黑åå•", + "urlNotValid": "URL 无效", + "urlAbsolutePath": "URL 或ç»å¯¹è·¯å¾„", + "addingList": "正在添加列表...", + "listAdded": "列表已æˆåŠŸæ·»åŠ ã€‚å·²æ·»åŠ é¡¹ç›®ï¼š", + "listAlreadyAdded": "列表已添加", + "listUrlInvalid": "列表 URL 无效", + "listNotAdded": "无法添加列表", + "listDetails": "列表详细信æ¯", + "listType": "列表类型", + "whitelist": "白åå•", + "blacklist": "黑åå•", + "latestUpdate": "最近更新", + "disable": "ç¦ç”¨", + "enable": "å¯ç”¨", + "currentStatus": "当å‰çжæ€", + "listDataUpdated": "列表数æ®å·²æˆåŠŸæ›´æ–°", + "listDataNotUpdated": "无法更新列表数æ®", + "updatingListData": "正在更新列表数æ®...", + "editWhitelist": "编辑白åå•", + "editBlacklist": "编辑黑åå•", + "deletingList": "正在删除列表...", + "listDeleted": "列表已æˆåŠŸåˆ é™¤", + "listNotDeleted": "无法删除列表", + "deleteList": "删除列表", + "deleteListMessage": "您确定è¦åˆ é™¤æ­¤åˆ—表å—?此æ“作无法撤消。", + "serverSettings": "æœåŠ¡å™¨è®¾ç½®", + "serverInformation": "æœåŠ¡å™¨ä¿¡æ¯", + "serverInformationDescription": "æœåŠ¡å™¨ä¿¡æ¯å’Œçжæ€", + "loadingServerInfo": "正在加载æœåŠ¡å™¨ä¿¡æ¯...", + "serverInfoNotLoaded": "无法加载æœåŠ¡å™¨ä¿¡æ¯ã€‚", + "dnsAddresses": "DNS 地å€", + "seeDnsAddresses": "查看 DNS 地å€", + "dnsPort": "DNS 端å£", + "httpPort": "HTTP 端å£", + "protectionEnabled": "å·²å¯ç”¨ä¿æŠ¤", + "dhcpAvailable": "å¯ç”¨ DHCP", + "serverRunning": "æœåС噍è¿è¡Œä¸­", + "serverVersion": "æœåŠ¡å™¨ç‰ˆæœ¬", + "serverLanguage": "æœåŠ¡å™¨è¯­è¨€", + "yes": "是", + "no": "å¦", + "allowedClients": "å·²å…许的客户端", + "disallowedClients": "å·²ç¦æ­¢çš„客户端", + "disallowedDomains": "å·²ç¦æ­¢çš„域å", + "accessSettings": "访问设置", + "accessSettingsDescription": "为æœåС噍é…置访问规则", + "loadingClients": "正在加载客户端...", + "clientsNotLoaded": "无法加载客户端。", + "noAllowedClients": "æ— å·²å…许的客户端", + "allowedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†ä»…æŽ¥å—æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求。", + "blockedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†æ‹’ç»æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求。如果已å…许客户端中有æ¡ç›®ï¼Œåˆ™ä¼šå¿½ç•¥æ­¤å­—段。", + "disallowedDomainsDescription": "AdGuard Home 会丢弃与这些域å匹é…çš„ DNS 查询,这些查询甚至ä¸ä¼šå‡ºçŽ°åœ¨æŸ¥è¯¢æ—¥å¿—ä¸­ã€‚", + "addClientFieldDescription": "CIDRã€IP åœ°å€æˆ–客户端ID", + "clientIdentifier": "客户端标识符", + "allowClient": "å…许客户端", + "disallowClient": "ç¦æ­¢å®¢æˆ·ç«¯", + "noDisallowedDomains": "æ— å·²ç¦æ­¢çš„域å", + "domainNotAdded": "无法添加域å", + "statusSelected": "已选择状æ€", + "updateLists": "更新列表", + "checkHostFiltered": "检查域å", + "updatingLists": "正在更新列表...", + "listsUpdated": "已更新列表", + "listsNotUpdated": "无法更新列表", + "listsNotLoaded": "无法加载列表", + "domainNotValid": "åŸŸåæ— æ•ˆ", + "check": "检查", + "checkingHost": "正在检查域å...", + "errorCheckingHost": "无法检查域å", + "block": "拦截", + "unblock": "解除拦截", + "custom": "自定义", + "addImportant": "添加 $important", + "howCreateRules": "如何创建自定义规则", + "examples": "示例", + "example1": "拦截访问 example.org åŠå…¶æ‰€æœ‰å­åŸŸã€‚", + "example2": "解除对 example.org åŠå…¶æ‰€æœ‰å­åŸŸçš„访问é™åˆ¶ã€‚", + "example3": "添加注释。", + "example4": "拦截访问与指定正则表达å¼åŒ¹é…的域。", + "moreInformation": "更多信æ¯", + "addingRule": "正在添加规则...", + "deletingRule": "正在删除规则...", + "enablingList": "正在å¯ç”¨åˆ—表...", + "disablingList": "正在ç¦ç”¨åˆ—表...", + "disableFiltering": "ç¦ç”¨è¿‡æ»¤", + "enablingFiltering": "正在å¯ç”¨è¿‡æ»¤...", + "disablingFiltering": "正在ç¦ç”¨è¿‡æ»¤...", + "filteringStatusUpdated": "过滤状æ€å·²æˆåŠŸæ›´æ–°", + "filteringStatusNotUpdated": "无法更新过滤状æ€", + "updateFrequency": "更新频率", + "never": "从ä¸", + "hour1": "1 å°æ—¶", + "hours12": "12 å°æ—¶", + "hours24": "24 å°æ—¶", + "days3": "3 天", + "days7": "7 天", + "changingUpdateFrequency": "正在更改...", + "updateFrequencyChanged": "更新频率已æˆåŠŸæ›´æ”¹", + "updateFrequencyNotChanged": "无法更改更新频率", + "updating": "正在更新值...", + "blockedServicesUpdated": "å·²æˆåŠŸæ›´æ–°è¢«æ‹¦æˆªçš„æœåŠ¡", + "blockedServicesNotUpdated": "无法更新被拦截的æœåŠ¡", + "insertDomain": "è¾“å…¥è¦æ£€æŸ¥çš„域å以查看其状æ€ã€‚", + "dhcpSettings": "DHCP 设置", + "dhcpSettingsDescription": "é…ç½® DHCP æœåС噍", + "dhcpSettingsNotLoaded": "无法加载 DHCP 设置", + "loadingDhcp": "正在加载 DHCP 设置...", + "enableDhcpServer": "å¯ç”¨ DHCP æœåС噍", + "selectInterface": "选择接å£", + "hardwareAddress": "硬件地å€", + "gatewayIp": "网关 IP", + "ipv4addresses": "IPv4 地å€", + "ipv6addresses": "IPv6 地å€", + "neededSelectInterface": "您需è¦é€‰æ‹©ä¸€ä¸ªæŽ¥å£æ¥é…ç½® DHCP æœåŠ¡å™¨ã€‚", + "ipv4settings": "IPv4 设置", + "startOfRange": "起始范围", + "endOfRange": "结æŸèŒƒå›´", + "ipv6settings": "IPv6 设置", + "subnetMask": "å­ç½‘掩ç ", + "subnetMaskNotValid": "å­ç½‘æŽ©ç æ— æ•ˆ", + "gateway": "网关", + "gatewayNotValid": "网关无效", + "leaseTime": "租期", + "seconds": "{time} ç§’", + "leaseTimeNotValid": "租期无效", + "restoreConfiguration": "é‡ç½®é…ç½®", + "restoreConfigurationMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰é…置。此æ“作无法撤消。", + "changeInterface": "更改接å£", + "savingSettings": "正在ä¿å­˜è®¾ç½®...", + "settingsSaved": "设置已æˆåŠŸä¿å­˜", + "settingsNotSaved": "无法ä¿å­˜è®¾ç½®", + "restoringConfig": "正在还原é…ç½®...", + "configRestored": "é…置已æˆåŠŸé‡ç½®", + "configNotRestored": "é…置无法é‡ç½®", + "dhcpStatic": "DHCP 陿€ç§Ÿç”¨", + "noDhcpStaticLeases": "未找到 DHCP 陿€ç§Ÿç”¨", + "deleting": "正在删除...", + "staticLeaseDeleted": "DHCP 陿€ç§Ÿç”¨å·²æˆåŠŸåˆ é™¤", + "staticLeaseNotDeleted": "无法删除 DHCP 陿€ç§Ÿç”¨", + "deleteStaticLease": "åˆ é™¤é™æ€ç§Ÿç”¨", + "deleteStaticLeaseDescription": "DHCP 陿€ç§Ÿç”¨å°†è¢«åˆ é™¤ã€‚æ­¤æ“作无法撤消。", + "addStaticLease": "æ·»åŠ é™æ€ç§Ÿç”¨", + "macAddress": "MAC 地å€", + "macAddressNotValid": "MAC åœ°å€æ— æ•ˆ", + "hostName": "主机å", + "hostNameError": "主机åä¸èƒ½ä¸ºç©º", + "creating": "正在创建...", + "staticLeaseCreated": "DHCP 陿€ç§Ÿç”¨å·²æˆåŠŸåˆ›å»º", + "staticLeaseNotCreated": "无法创建 DHCP 陿€ç§Ÿç”¨", + "staticLeaseExists": "DHCP 陿€ç§Ÿç”¨å·²å­˜åœ¨", + "serverNotConfigured": "未é…ç½®æœåС噍", + "restoreLeases": "é‡ç½®ç§Ÿç”¨", + "restoreLeasesMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰çŽ°æœ‰ç§Ÿç”¨ã€‚æ­¤æ“作无法撤消。", + "restoringLeases": "正在é‡ç½®ç§Ÿç”¨...", + "leasesRestored": "租用已æˆåŠŸé‡ç½®", + "leasesNotRestored": "租用无法é‡ç½®", + "dhcpLeases": "DHCP 租用", + "noLeases": "æ— å¯ç”¨çš„ DHCP 租用", + "dnsRewrites": "DNS é‡å†™", + "dnsRewritesDescription": "é…置自定义 DNS 规则", + "loadingRewriteRules": "正在加载é‡å†™è§„则...", + "rewriteRulesNotLoaded": "无法加载 DNS é‡å†™è§„则。", + "noRewriteRules": "æ—  DNS é‡å†™è§„则", + "answer": "回答", + "deleteDnsRewrite": "删除 DNS é‡å†™", + "deleteDnsRewriteMessage": "您确定è¦åˆ é™¤æ­¤ DNS é‡å†™å—?此æ“作无法撤消。", + "dnsRewriteRuleDeleted": "DNS é‡å†™è§„则已æˆåŠŸåˆ é™¤", + "dnsRewriteRuleNotDeleted": "无法删除 DNS é‡å†™è§„则", + "addDnsRewrite": "添加 DNS é‡å†™", + "addingRewrite": "正在添加é‡å†™...", + "dnsRewriteRuleAdded": "DNS é‡å†™è§„则已æˆåŠŸæ·»åŠ ", + "dnsRewriteRuleNotAdded": "无法添加 DNS é‡å†™è§„则", + "logsSettings": "日志设置", + "enableLog": "å¯ç”¨æ—¥å¿—", + "clearLogs": "清除日志", + "anonymizeClientIp": "匿å化客户端 IP", + "hours6": "6 å°æ—¶", + "days30": "30 天", + "days90": "90 天", + "retentionTime": "ä¿ç•™æ—¶é—´", + "selectOneItem": "选择一项", + "logSettingsNotLoaded": "无法加载日志设置。", + "updatingSettings": "正在更新设置...", + "logsConfigUpdated": "日志设置已æˆåŠŸæ›´æ–°", + "logsConfigNotUpdated": "无法更新日志设置", + "deletingLogs": "正在清除日志...", + "logsCleared": "日志已æˆåŠŸæ¸…é™¤", + "logsNotCleared": "无法清除日志", + "runningHomeAssistant": "在 Home Assistant 上è¿è¡Œ", + "serverError": "æœåŠ¡å™¨é”™è¯¯", + "noItems": "è¿™é‡Œæ²¡æœ‰è¦æ˜¾ç¤ºçš„项目", + "dnsSettings": "DNS 设置", + "dnsSettingsDescription": "é…置与 DNS æœåŠ¡å™¨çš„è¿žæŽ¥", + "upstreamDns": "上游 DNS æœåС噍", + "bootstrapDns": "引导 DNS æœåС噍", + "noUpstreamDns": "未添加上游 DNS æœåŠ¡å™¨ã€‚", + "dnsMode": "DNS 模å¼", + "noDnsMode": "未选择 DNS 模å¼", + "loadBalancing": "è´Ÿè½½å‡è¡¡", + "parallelRequests": "并行请求", + "fastestIpAddress": "最快的 IP 地å€", + "loadBalancingDescription": "æ¯æ¬¡æŸ¥è¯¢ä¸€ä¸ªä¸Šæ¸¸æœåŠ¡å™¨ã€‚AdGuard Home 使用其加æƒéšæœºç®—æ³•é€‰æ‹©æœåŠ¡å™¨ï¼Œä»¥ä¾¿æ›´é¢‘ç¹åœ°ä½¿ç”¨æœ€å¿«çš„æœåŠ¡å™¨ã€‚", + "parallelRequestsDescription": "ä½¿ç”¨å¹¶è¡ŒæŸ¥è¯¢åŒæ—¶åŠ é€Ÿè§£æžï¼ŒåŒæ—¶æŸ¥è¯¢æ‰€æœ‰ä¸Šæ¸¸æœåŠ¡å™¨ã€‚", + "fastestIpAddressDescription": "查询所有 DNS æœåŠ¡å™¨å¹¶è¿”å›žæ‰€æœ‰å“应中最快的 IP 地å€ã€‚è¿™ä¼šå‡æ…¢ DNS 查询,因为 AdGuard Home 必须等待所有 DNS æœåŠ¡å™¨çš„å“应,但å¯ä»¥æ”¹å–„整体连接性。", + "noBootstrapDns": "未添加引导 DNS æœåŠ¡å™¨ã€‚", + "bootstrapDnsServersInfo": "引导 DNS æœåŠ¡å™¨ç”¨äºŽè§£æžæ‚¨æŒ‡å®šçš„上游 DoH/DoT è§£æžå™¨çš„ IP 地å€ã€‚", + "privateReverseDnsServers": "ç§æœ‰åå‘ DNS æœåС噍", + "privateReverseDnsServersDescription": "AdGuard Home 用于本地 PTR 查询的 DNS æœåŠ¡å™¨ã€‚è¿™äº›æœåŠ¡å™¨ç”¨äºŽè§£æžç§æœ‰ IP 范围内的地å€çš„ PTR 请求,例如 \"192.168.12.34\"。如果未设置,AdGuard Home 将使用æ“作系统的默认 DNS è§£æžå™¨åœ°å€ï¼Œä½†ä¸åŒ…括 AdGuard Home 本身的地å€ã€‚", + "reverseDnsDefault": "默认情况下,AdGuard Home 使用以下默认åå‘ DNS è§£æžå™¨", + "addItem": "添加项目", + "noServerAddressesAdded": "未添加æœåŠ¡å™¨åœ°å€ã€‚", + "usePrivateReverseDnsResolvers": "ä½¿ç”¨ç§æœ‰åå‘ DNS è§£æžå™¨", + "usePrivateReverseDnsResolversDescription": "使用这些上游æœåŠ¡å™¨æ‰§è¡Œæœ¬åœ°æä¾›çš„地å€çš„åå‘ DNS 查询。如果ç¦ç”¨ï¼ŒAdGuard Home 会对所有此类 PTR 请求(除了æ¥è‡ª DHCPã€/etc/hosts 等已知客户端)å“应 NXDOMAIN。", + "enableReverseResolving": "å¯ç”¨å®¢æˆ·ç«¯ IP 地å€çš„åå‘è§£æž", + "enableReverseResolvingDescription": "通过å‘相应的解æžå™¨å‘é€ PTR 查询,将客户端 IP 地å€è¿›è¡Œåå‘è§£æžä¸ºä¸»æœºåï¼ˆå¯¹äºŽæœ¬åœ°å®¢æˆ·ç«¯ä½¿ç”¨ç§æœ‰ DNS æœåŠ¡å™¨ï¼Œå¯¹äºŽå…·æœ‰å…¬å…± IP 地å€çš„客户端使用上游æœåŠ¡å™¨ï¼‰ã€‚", + "dnsServerSettings": "AdGuard Home DNS æœåŠ¡å™¨è®¾ç½®", + "limitRequestsSecond": "æ¯ç§’速率é™åˆ¶", + "valueNotNumber": "值䏿˜¯æ•°å­—", + "enableEdns": "å¯ç”¨ EDNS 客户å­ç½‘", + "enableEdnsDescription": "在上游请求中添加 EDNS 客户å­ç½‘选项(ECS),并在查询日志中记录客户端å‘é€çš„值。", + "enableDnssec": "å¯ç”¨ DNSSEC", + "enableDnssecDescription": "在传出的 DNS 查询中设置 DNSSEC 标志并检查结果(需è¦å¯ç”¨ DNSSEC 的解æžå™¨ï¼‰ã€‚", + "disableResolvingIpv6": "ç¦ç”¨ IPv6 地å€è§£æž", + "disableResolvingIpv6Description": "丢弃所有用于 IPv6 地å€ï¼ˆç±»åž‹ AAAA)的 DNS 查询。", + "blockingMode": "拦截模å¼", + "defaultMode": "默认", + "defaultDescription": "当按照 Adblock æ ·å¼è§„则被拦截时,返回零 IP 地å€ï¼ˆ0.0.0.0 对应 Aï¼›:: 对应 AAAA);当按照 /etc/hosts æ ·å¼è§„则被拦截时,返回规则中指定的 IP 地å€", + "refusedDescription": "返回 REFUSED 代ç ", + "nxdomainDescription": "返回 NXDOMAIN 代ç ", + "nullIp": "空 IP", + "nullIpDescription": "返回零 IP 地å€ï¼ˆ0.0.0.0 对应 Aï¼›:: 对应 AAAA)", + "customIp": "自定义 IP", + "customIpDescription": "返回手动设置的 IP 地å€", + "dnsCacheConfig": "DNS 缓存é…ç½®", + "cacheSize": "缓存大å°", + "inBytes": "字节", + "overrideMinimumTtl": "è¦†ç›–æœ€å° TTL", + "overrideMinimumTtlDescription": "在缓存 DNS å“应时,从上游æœåŠ¡å™¨æŽ¥æ”¶åˆ°çš„æœ€çŸ­çš„å­˜æ´»æ—¶é—´å€¼ï¼ˆç§’ï¼‰ã€‚", + "overrideMaximumTtl": "覆盖最大 TTL", + "overrideMaximumTtlDescription": "为 DNS 缓存æ¡ç›®è®¾ç½®æœ€å¤§å­˜æ´»æ—¶é—´å€¼ï¼ˆç§’)。", + "optimisticCaching": "ä¹è§‚缓存", + "optimisticCachingDescription": "å³ä½¿æ¡ç›®å·²è¿‡æœŸï¼ŒAdGuard Home 也将从缓存中å“应,并å°è¯•刷新它们。", + "loadingDnsConfig": "正在加载 DNS é…ç½®...", + "dnsConfigNotLoaded": "无法加载 DNS é…置。", + "blockingIpv4": "拦截 IPv4", + "blockingIpv4Description": "当 A 请求被拦截时返回的 IP 地å€", + "blockingIpv6": "拦截 IPv6", + "blockingIpv6Description": "当 AAAA 请求被拦截时返回的 IP 地å€", + "invalidIp": "无效的 IP 地å€", + "dnsConfigSaved": "DNS æœåС噍é…置已æˆåŠŸä¿å­˜", + "dnsConfigNotSaved": "DNS æœåС噍é…置无法ä¿å­˜", + "savingConfig": "正在ä¿å­˜é…ç½®...", + "someValueNotValid": "æŸäº›å€¼æ— æ•ˆ", + "upstreamDnsDescription": "é…置上游æœåŠ¡å™¨å’Œ DNS 模å¼", + "bootstrapDnsDescription": "é…置引导 DNS æœåС噍", + "privateReverseDnsDescription": "é…置自定义 DNS è§£æžå™¨å¹¶å¯ç”¨ç§æœ‰åå‘ DNS è§£æž", + "dnsServerSettingsDescription": "é…置速率é™åˆ¶ã€æ‹¦æˆªæ¨¡å¼ç­‰", + "dnsCacheConfigDescription": "é…ç½®æœåŠ¡å™¨å¦‚ä½•ç®¡ç† DNS 缓存", + "comment": "注释", + "address": "地å€", + "commentsDescription": "注释始终以 # 开头。您无需添加它,系统将自动添加。", + "encryptionSettings": "加密设置", + "encryptionSettingsDescription": "加密(HTTPS/QUIC/TLS)支æŒ", + "loadingEncryptionSettings": "正在加载加密设置...", + "encryptionSettingsNotLoaded": "无法加载加密设置。", + "enableEncryption": "å¯ç”¨åР坆", + "enableEncryptionTypes": "HTTPSã€DNS-over-HTTPS å’Œ DNS-over-TLS", + "enableEncryptionDescription": "如果å¯ç”¨åŠ å¯†ï¼ŒAdGuard Home 管ç†ç•Œé¢å°†é€šè¿‡ HTTPS è¿è¡Œï¼Œå¹¶ä¸” DNS æœåŠ¡å™¨å°†ç›‘å¬ DNS-over-HTTPS å’Œ DNS-over-TLS 请求。", + "serverConfiguration": "æœåС噍é…ç½®", + "domainName": "域å", + "domainNameDescription": "如果设置,AdGuard Home 将检测 ClientIDã€å“应 DDR 查询并执行其他连接验è¯ã€‚如果未设置,这些功能将被ç¦ç”¨ã€‚必须与è¯ä¹¦ä¸­çš„ DNS å称之一匹é…。", + "redirectHttps": "自动é‡å®šå‘到 HTTPS", + "httpsPort": "HTTPS 端å£", + "tlsPort": "DNS-over-TLS 端å£", + "dnsOverQuicPort": "DNS-over-QUIC 端å£", + "certificates": "è¯ä¹¦", + "certificatesDescription": "为了使用加密,您需è¦ä¸ºæ‚¨çš„域æä¾›æœ‰æ•ˆçš„ SSL è¯ä¹¦é“¾ã€‚您å¯ä»¥åœ¨ letsencrypt.org 上获得å…è´¹è¯ä¹¦ï¼Œä¹Ÿå¯ä»¥ä»Žå—信任的è¯ä¹¦é¢å‘机构购买。", + "certificateFilePath": "设置è¯ä¹¦æ–‡ä»¶è·¯å¾„", + "pasteCertificateContent": "粘贴è¯ä¹¦å†…容", + "certificatePath": "è¯ä¹¦è·¯å¾„", + "certificateContent": "è¯ä¹¦å†…容", + "privateKey": "ç§é’¥", + "privateKeyFile": "设置ç§é’¥æ–‡ä»¶", + "pastePrivateKey": "粘贴ç§é’¥å†…容", + "usePreviousKey": "使用先å‰ä¿å­˜çš„密钥", + "privateKeyPath": "ç§é’¥è·¯å¾„", + "invalidCertificate": "无效的è¯ä¹¦", + "invalidPrivateKey": "无效的ç§é’¥", + "validatingData": "æ­£åœ¨éªŒè¯æ•°æ®", + "dataValid": "æ•°æ®æœ‰æ•ˆ", + "dataNotValid": "æ•°æ®æ— æ•ˆ", + "encryptionConfigSaved": "加密é…置已æˆåŠŸä¿å­˜", + "encryptionConfigNotSaved": "无法ä¿å­˜åР坆é…ç½®", + "configError": "é…置错误", + "enterOnlyCertificate": "åªè¾“å…¥è¯ä¹¦ã€‚ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", + "enterOnlyPrivateKey": "åªè¾“入密钥。ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", + "noItemsSearch": "没有匹é…的项目。", + "clearSearch": "清除æœç´¢", + "exitSearch": "退出æœç´¢", + "searchClients": "æœç´¢å®¢æˆ·ç«¯", + "noClientsSearch": "没有匹é…的客户端。", + "customization": "定制", + "customizationDescription": "自定义此应用程åº", + "color": "颜色", + "useDynamicTheme": "使用动æ€ä¸»é¢˜", + "red": "红色", + "green": "绿色", + "blue": "è“色", + "yellow": "黄色", + "orange": "橙色", + "brown": "棕色", + "cyan": "é’色", + "purple": "紫色", + "pink": "粉色", + "deepOrange": "深橙色", + "indigo": "é›è“色", + "useThemeColorStatus": "使用主题颜色æ¥è¡¨ç¤ºçжæ€", + "useThemeColorStatusDescription": "用主题颜色和ç°è‰²æ›¿æ¢ç»¿è‰²å’Œçº¢è‰²çжæ€é¢œè‰²", + "invalidCertificateChain": "无效的è¯ä¹¦é“¾", + "validCertificateChain": "有效的è¯ä¹¦é“¾", + "subject": "主题", + "issuer": "å‘行人", + "expires": "过期", + "validPrivateKey": "有效的ç§é’¥", + "expirationDate": "到期日期", + "keysNotMatch": "无效的è¯ä¹¦æˆ–密钥:tls: private key does not match public key", + "timeLogs": "日志时间", + "timeLogsDescription": "åœ¨æ—¥å¿—åˆ—è¡¨ä¸­æ˜¾ç¤ºå¤„ç†æ—¶é—´", + "hostNames": "主机å", + "keyType": "密钥类型", + "updateAvailable": "å¯ç”¨æ›´æ–°", + "installedVersion": "已安装版本", + "newVersion": "新版本", + "source": "æ¥æº", + "downloadUpdate": "下载更新", + "download": "下载", + "doNotRememberAgainUpdate": "ä¸è¦å†æ¬¡æé†’此版本", + "downloadingUpdate": "正在下载", + "completed": "已完æˆ", + "permissionNotGranted": "未授予æƒé™", + "inputSearchTerm": "输入æœç´¢è¯ã€‚", + "answers": "回答", + "copyClipboard": "å¤åˆ¶åˆ°å‰ªè´´æ¿", + "domainCopiedClipboard": "域åå·²å¤åˆ¶åˆ°å‰ªè´´æ¿", + "clearDnsCache": "清除 DNS 缓存", + "clearDnsCacheMessage": "æ‚¨ç¡®å®šè¦æ¸…除 DNS 缓存å—?", + "dnsCacheCleared": "DNS 缓存已æˆåŠŸæ¸…é™¤", + "clearingDnsCache": "正在清除缓存...", + "dnsCacheNotCleared": "无法清除 DNS 缓存", + "clientsSelected": "已选择客户端", + "invalidDomain": "无效的域å", + "loadingBlockedServicesList": "正在加载已拦截的æœåŠ¡åˆ—è¡¨...", + "blockedServicesListNotLoaded": "无法加载已拦截的æœåŠ¡åˆ—è¡¨", + "error": "错误", + "updates": "æ›´æ–°", + "updatesDescription": "æ›´æ–° AdGuard Home ", + "updateNow": "ç«‹å³æ›´æ–°", + "currentVersion": "当å‰ç‰ˆæœ¬", + "requestStartUpdateFailed": "请求开始更新失败", + "requestStartUpdateSuccessful": "请求开始更新æˆåŠŸ", + "serverUpdated": "AdGuardHome 已是最新版", + "unknownStatus": "未知状æ€", + "checkingUpdates": "正在检查更新...", + "checkUpdates": "检查更新", + "requestingUpdate": "请求更新中...", + "autoupdateUnavailable": "自动更新ä¸å¯ç”¨", + "autoupdateUnavailableDescription": "æ­¤æœåС噍䏿”¯æŒè‡ªåŠ¨æ›´æ–°æœåŠ¡ã€‚è¿™å¯èƒ½æ˜¯å› ä¸ºæœåŠ¡å™¨æ­£åœ¨ Docker 容器中è¿è¡Œã€‚æ‚¨éœ€è¦æ‰‹åŠ¨æ›´æ–°æœåŠ¡å™¨ã€‚", + "minute": "{time} 分钟", + "minutes": "{time} 分钟", + "hour": "{time} å°æ—¶", + "hours": "{time} å°æ—¶", + "remainingTime": "剩余时间", + "safeSearchSettings": "安全æœç´¢è®¾ç½®", + "loadingSafeSearchSettings": "正在加载安全æœç´¢è®¾ç½®...", + "safeSearchSettingsNotLoaded": "加载安全æœç´¢è®¾ç½®æ—¶å‡ºé”™ã€‚", + "loadingLogsSettings": "正在加载日志设置...", + "selectOptionLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªé€‰é¡¹", + "selectClientLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªå®¢æˆ·ç«¯", + "disableList": "ç¦ç”¨åˆ—表", + "enableList": "å¯ç”¨åˆ—表", + "screens": "å±å¹•", + "copiedClipboard": "å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", + "seeDetails": "查看详细信æ¯", + "listNotAvailable": "列表ä¸å¯ç”¨", + "copyListUrl": "å¤åˆ¶åˆ—表 URL", + "listUrlCopied": "列表 URL å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", + "unsupportedVersion": "䏿”¯æŒçš„版本", + "unsupprtedVersionMessage": "对于您的æœåŠ¡å™¨ç‰ˆæœ¬ {version},支æŒä¸ä¿è¯ã€‚该应用程åºåœ¨ä½¿ç”¨è¯¥æœåŠ¡å™¨ç‰ˆæœ¬æ—¶å¯èƒ½ä¼šå‡ºçŽ°ä¸€äº›é—®é¢˜ã€‚\n\nAdGuard Home 管ç†å™¨è®¾è®¡ç”¨äºŽä¸Ž AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬é…åˆä½¿ç”¨ã€‚它å¯èƒ½ä¸Ž alpha å’Œ beta 版本一起工作,但ä¸ä¿è¯å…¼å®¹æ€§ï¼Œè¯¥ç‰ˆæœ¬çš„应用程åºå¯èƒ½åœ¨ä¸Žè¯¥ç‰ˆæœ¬ä¸€èµ·å·¥ä½œæ—¶ä¼šå‡ºçŽ°ä¸€äº›é—®é¢˜ã€‚", + "iUnderstand": "我了解", + "appUpdates": "åº”ç”¨ç¨‹åºæ›´æ–°", + "usingLatestVersion": "您正在使用最新版本", + "ipLogs": "日志中的 IP", + "ipLogsDescription": "始终在日志中显示 IP 地å€ï¼Œè€Œä¸æ˜¯å®¢æˆ·ç«¯åç§°", + "application": "应用程åº", + "combinedChart": "åˆå¹¶å›¾è¡¨", + "combinedChartDescription": "将所有图表åˆå¹¶ä¸ºä¸€ä¸ª", + "statistics": "统计", + "errorLoadFilters": "加载过滤器时出错。", + "clientRemovedSuccessfully": "客户端已æˆåŠŸç§»é™¤ã€‚", + "editRewriteRule": "编辑é‡å†™è§„则", + "dnsRewriteRuleUpdated": "DNS é‡å†™è§„则已æˆåŠŸæ›´æ–°", + "dnsRewriteRuleNotUpdated": "无法更新 DNS é‡å†™è§„则", + "updatingRule": "正在更新规则...", + "serverUpdateNeeded": "éœ€è¦æ›´æ–°æœåС噍", + "updateYourServer": "å°† AdGuard Home æœåŠ¡å™¨æ›´æ–°åˆ° {version} 或更高版本以使用此功能。", + "january": "1月", + "february": "2月", + "march": "3月", + "april": "4月", + "may": "5月", + "june": "6月", + "july": "7月", + "august": "8月", + "september": "9月", + "october": "10月", + "november": "11月", + "december": "12月", + "malwarePhising": "æ¶æ„软件/é’“é±¼", + "queries": "查询", + "adultSites": "æˆäººç½‘ç«™", + "quickFilters": "快速过滤器", + "searchDomainInternet": "在互è”网上æœç´¢è¯¥åŸŸå" +} From f0633e7cff3cfd963c7f08f72ad89f74c9dfa0ed Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 11:29:59 +0800 Subject: [PATCH 262/676] Update main.dart --- lib/main.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 4dcd872..20b94bb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -226,7 +226,8 @@ class _MainState extends State
{ ], supportedLocales: const [ Locale('en', ''), - Locale('es', '') + Locale('es', ''), + Locale('zh', '') ], scaffoldMessengerKey: scaffoldMessengerKey, builder: (context, child) { From 82df5b597d70ac3c283023290d8b8b2388bb6136 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 13:42:11 +0800 Subject: [PATCH 263/676] Update app_zh.arb --- lib/l10n/app_zh.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 01f17ee..4710b88 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -619,7 +619,7 @@ "copyListUrl": "å¤åˆ¶åˆ—表 URL", "listUrlCopied": "列表 URL å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", "unsupportedVersion": "䏿”¯æŒçš„版本", - "unsupprtedVersionMessage": "对于您的æœåŠ¡å™¨ç‰ˆæœ¬ {version},支æŒä¸ä¿è¯ã€‚该应用程åºåœ¨ä½¿ç”¨è¯¥æœåŠ¡å™¨ç‰ˆæœ¬æ—¶å¯èƒ½ä¼šå‡ºçŽ°ä¸€äº›é—®é¢˜ã€‚\n\nAdGuard Home 管ç†å™¨è®¾è®¡ç”¨äºŽä¸Ž AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬é…åˆä½¿ç”¨ã€‚它å¯èƒ½ä¸Ž alpha å’Œ beta 版本一起工作,但ä¸ä¿è¯å…¼å®¹æ€§ï¼Œè¯¥ç‰ˆæœ¬çš„应用程åºå¯èƒ½åœ¨ä¸Žè¯¥ç‰ˆæœ¬ä¸€èµ·å·¥ä½œæ—¶ä¼šå‡ºçŽ°ä¸€äº›é—®é¢˜ã€‚", + "unsupprtedVersionMessage": "对于您的æœåŠ¡å™¨ç‰ˆæœ¬ {version},ä¸ä¿è¯æ”¯æŒã€‚该应用程åºåœ¨ä½¿ç”¨è¯¥æœåŠ¡å™¨ç‰ˆæœ¬æ—¶å¯èƒ½ä¼šå‡ºçŽ°ä¸€äº›é—®é¢˜ã€‚\n\nAdGuard Home 管ç†å™¨è®¾è®¡ç”¨äºŽä¸Ž AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬é…åˆä½¿ç”¨ã€‚它å¯èƒ½ä¸Ž Alpha å’Œ Beta 版本一起工作,但ä¸ä¿è¯å…¼å®¹æ€§ï¼Œè¯¥ç‰ˆæœ¬çš„应用程åºå¯èƒ½åœ¨ä¸Žè¯¥ç‰ˆæœ¬ä¸€èµ·å·¥ä½œæ—¶ä¼šå‡ºçŽ°ä¸€äº›é—®é¢˜ã€‚", "iUnderstand": "我了解", "appUpdates": "åº”ç”¨ç¨‹åºæ›´æ–°", "usingLatestVersion": "您正在使用最新版本", From bf335bc2db661f69503a4631af867177892966f7 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 18:57:02 +0800 Subject: [PATCH 264/676] Update app_zh.arb --- lib/l10n/app_zh.arb | 76 ++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 4710b88..a867d73 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -3,7 +3,7 @@ "settings": "设置", "connect": "连接", "servers": "æœåС噍", - "createConnection": "新建连接", + "createConnection": "创建连接", "name": "åç§°", "ipDomain": "IPåœ°å€æˆ–域å", "path": "路径", @@ -14,57 +14,57 @@ "general": "常规", "connection": "连接", "authentication": "身份验è¯", - "other": "å…¶ä»–", - "invalidPort": "无效端å£", - "invalidPath": "无效路径", - "invalidIpDomain": "无效IP或域å ", - "ipDomainNotEmpty": "IP 或域åä¸èƒ½ä¸ºç©º", + "other": "其它", + "invalidPort": "ç«¯å£æ— æ•ˆ", + "invalidPath": "路径无效", + "invalidIpDomain": "IP åœ°å€æˆ–åŸŸåæ— æ•ˆ", + "ipDomainNotEmpty": "IP åœ°å€æˆ–域åä¸èƒ½ä¸ºç©º", "nameNotEmpty": "åç§°ä¸èƒ½ä¸ºç©º", - "invalidUsernamePassword": "ç”¨æˆ·åæˆ–å¯†ç æ— æ•ˆ", + "invalidUsernamePassword": "ç”¨æˆ·åæˆ–密ç é”™è¯¯", "tooManyAttempts": "å°è¯•次数过多,请ç¨åŽå†è¯•", "cantReachServer": "无法连接æœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥è¿žæŽ¥ä¿¡æ¯æ˜¯å¦æ­£ç¡®", "sslError": "SSL 错误。转到 设置 > 高级设置 å¹¶å¯ç”¨ 忽略 SSL 验è¯", "unknownError": "未知错误", "connectionNotCreated": "连接无法创建", - "connecting": "连接æˆåŠŸ...", + "connecting": "正在连接...", "connected": "已连接", "selectedDisconnected": "已选择但未连接", - "connectionDefaultSuccessfully": "将连接设置为默认æˆåŠŸ", - "connectionDefaultFailed": "连接无法设置为默认", - "noSavedConnections": "未ä¿å­˜è¿žæŽ¥", - "cannotConnect": "无法连接æœåС噍", - "connectionRemoved": "移除连接æˆåŠŸ", + "connectionDefaultSuccessfully": "æˆåŠŸå°†è¿žæŽ¥è®¾ä¸ºé»˜è®¤", + "connectionDefaultFailed": "无法将连接设为默认", + "noSavedConnections": "连接为空", + "cannotConnect": "无法连接到æœåС噍", + "connectionRemoved": "连接删除æˆåŠŸ", "connectionCannotBeRemoved": "无法删除连接", "remove": "移除", - "removeWarning": "您确定è¦åˆ é™¤ä¸Žæ­¤ AdGuard Home æœåŠ¡å™¨çš„è¿žæŽ¥å—?", + "removeWarning": "您确定è¦åˆ é™¤ä¸Žæ­¤ AdGuard Home æœåŠ¡å™¨çš„è¿žæŽ¥å—?", "cancel": "å–æ¶ˆ", - "defaultConnection": "默认链接", + "defaultConnection": "默认连接", "setDefault": "设为默认", "edit": "编辑", "delete": "删除", "save": "ä¿å­˜", - "serverStatus": "æœåС噍è¿è¡Œçж况", - "connectionNotUpdated": "连接未更新", + "serverStatus": "æœåŠ¡å™¨çŠ¶æ€", + "connectionNotUpdated": "没有更新连接é…ç½®", "ruleFilteringWidget": "规则过滤", - "safeBrowsingWidget": "æµè§ˆå®‰å…¨", - "parentalFilteringWidget": "家长控制", + "safeBrowsingWidget": "安全æµè§ˆ", + "parentalFilteringWidget": "家长过滤", "safeSearchWidget": "安全æœç´¢", "ruleFiltering": "规则过滤", - "safeBrowsing": "æµè§ˆå®‰å…¨", - "parentalFiltering": "家长控制", + "safeBrowsing": "安全æµè§ˆ", + "parentalFiltering": "家长过滤", "safeSearch": "安全æœç´¢", - "serverStatusNotRefreshed": "无法刷新æœåŠ¡å™¨çŠ¶æ€", - "loadingStatus": "正在加载状æ€...", - "errorLoadServerStatus": "æœåŠ¡å™¨çŠ¶æ€æ— æ³•加载", + "serverStatusNotRefreshed": "无法更新æœåŠ¡å™¨çŠ¶æ€", + "loadingStatus": "加载æœåŠ¡å™¨çŠ¶æ€...", + "errorLoadServerStatus": "无法加载æœåŠ¡å™¨çŠ¶æ€", "topQueriedDomains": "è¯·æ±‚åŸŸåæŽ’行", "viewMore": "查看更多", "topClients": "客户端排行", "topBlockedDomains": "è¢«æ‹¦æˆªåŸŸåæŽ’行", - "appSettings": "应用设置", + "appSettings": "App 设置", "theme": "主题", - "light": "白", - "dark": "黑", - "systemDefined": "系统定义", + "light": "明亮", + "dark": "暗夜", + "systemDefined": "è·Ÿéšç³»ç»Ÿ", "close": "关闭", "connectedTo": "连接到:", "selectedServer": "选定的æœåŠ¡å™¨ï¼š", @@ -73,21 +73,21 @@ "allProtections": "æ‰€æœ‰ä¿æŠ¤", "userNotEmpty": "用户åä¸èƒ½ä¸ºç©º", "passwordNotEmpty": "密ç ä¸èƒ½ä¸ºç©º", - "examplePath": "示例: /adguard", - "helperPath": "如果您使用的是åå‘代ç†", - "aboutApp": "关于应用程åº", - "appVersion": "应用版本", - "createdBy": "制作", + "examplePath": "例如: /adguard", + "helperPath": "如果使用åå‘代ç†ï¼Œå¯å¡«å†™è·¯å¾„", + "aboutApp": "关于本应用", + "appVersion": "App 版本", + "createdBy": "作者", "clients": "客户端", "allowed": "å…许", "blocked": "拦截", "noClientsList": "列表中没有客户端", - "activeClients": "活动的", + "activeClients": "活跃", "removeClient": "删除客户端", - "removeClientMessage": "您确定è¦ä»Žåˆ—表中删除此客户端å—?", - "confirm": "确认", - "removingClient": "删除客户端...", - "clientNotRemoved": "客户端无法从列表中删除", + "removeClientMessage": "您确定è¦ä»Žåˆ—è¡¨ä¸­åˆ é™¤æ­¤å®¢æˆ·ç«¯å— ?", + "confirm": "确定", + "removingClient": "正在删除客户端...", + "clientNotRemoved": "无法从列表中删除客户端", "addClient": "添加客户端", "list": "列表", "ipAddress": "IP地å€", From bce11df768e903d4cc06e5b47868569081382397 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 18:58:15 +0800 Subject: [PATCH 265/676] Update app_zh.arb --- lib/l10n/app_zh.arb | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index a867d73..504cdaf 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -90,27 +90,27 @@ "clientNotRemoved": "无法从列表中删除客户端", "addClient": "添加客户端", "list": "列表", - "ipAddress": "IP地å€", - "ipNotValid": "IPåœ°å€æ— æ•ˆ", - "clientAddedSuccessfully": "客户端æˆåŠŸæ·»åŠ åˆ°åˆ—è¡¨ä¸­", - "addingClient": "添加客户端...", - "clientNotAdded": "客户端无法添加到列表中", - "clientAnotherList": "这个客户端还在å¦ä¸€ä¸ªåˆ—表中", - "noSavedLogs": "没有ä¿å­˜çš„æ—¥å¿—", + "ipAddress": "IP 地å€", + "ipNotValid": "IP åœ°å€æ— æ•ˆ", + "clientAddedSuccessfully": "æˆåŠŸå°†å®¢æˆ·ç«¯æ·»åŠ åˆ°åˆ—è¡¨", + "addingClient": "正在添加客户端...", + "clientNotAdded": "无法将客户端添加到列表", + "clientAnotherList": "å…¶å®ƒåˆ—è¡¨é‡Œå·²ç»æœ‰è¿™ä¸ªå®¢æˆ·ç«¯äº†", + "noSavedLogs": "没有日志", "logs": "日志", "copyLogsClipboard": "将日志å¤åˆ¶åˆ°å‰ªè´´æ¿", - "logsCopiedClipboard": "日志å¤åˆ¶åˆ°å‰ªè´´æ¿", + "logsCopiedClipboard": "日志已å¤åˆ¶åˆ°å‰ªè´´æ¿", "advancedSettings": "高级设置", "dontCheckCertificate": "䏿£€æŸ¥ SSL è¯ä¹¦", "dontCheckCertificateDescription": "忽略æœåŠ¡å™¨çš„ SSL è¯ä¹¦éªŒè¯", "advancedSetupDescription": "高级选项", - "settingsUpdatedSuccessfully": "设置æˆåŠŸæ›´æ–°", - "cannotUpdateSettings": "设置无法更新", + "settingsUpdatedSuccessfully": "设置更新æˆåŠŸ", + "cannotUpdateSettings": "无法更新设置", "restartAppTakeEffect": "釿–°å¯åŠ¨åº”ç”¨ç¨‹åº", - "loadingLogs": "加载日志...", - "logsNotLoaded": "日志列表无法加载", - "processed": "已处ç†\n无列表拦截", - "processedRow": "已处ç†ï¼ˆæ— åˆ—表拦截)", + "loadingLogs": "正在加载日志...", + "logsNotLoaded": "无法加载日志列表", + "processed": "已处ç†\n无订阅规则拦截", + "processedRow": "已处ç†ï¼ˆæ— è®¢é˜…规则拦截)", "blockedBlacklist": "已拦截\n黑åå•", "blockedBlacklistRow": "已拦截(黑åå•)", "blockedSafeBrowsing": "已拦截\n安全æµè§ˆ", @@ -143,13 +143,13 @@ "client": "客户端", "deviceIp": "IP 地å€", "deviceName": "åç§°", - "logDetails": "日志详细信æ¯", + "logDetails": "日志详情", "blockingRule": "拦截规则", "blockDomain": "拦截域å", "couldntGetFilteringStatus": "无法获å–过滤状æ€", - "unblockDomain": "è§£é™¤åŸŸåæ‹¦æˆª", - "userFilteringRulesNotUpdated": "用户过滤规则未能更新", - "userFilteringRulesUpdated": "用户过滤规则已æˆåŠŸæ›´æ–°", + "unblockDomain": "放行域å", + "userFilteringRulesNotUpdated": "无法更新用户过滤规则", + "userFilteringRulesUpdated": "æˆåŠŸæ›´æ–°ç”¨æˆ·è¿‡æ»¤è§„åˆ™", "savingUserFilters": "正在ä¿å­˜ç”¨æˆ·è¿‡æ»¤å™¨...", "filters": "过滤器", "logsOlderThan": "早于日志", From 57ebcd221e047d0ec5279e9272039cdcf665f4a6 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 18:59:07 +0800 Subject: [PATCH 266/676] Update app_zh.arb --- lib/l10n/app_zh.arb | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 504cdaf..edc54a9 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -152,13 +152,13 @@ "userFilteringRulesUpdated": "æˆåŠŸæ›´æ–°ç”¨æˆ·è¿‡æ»¤è§„åˆ™", "savingUserFilters": "正在ä¿å­˜ç”¨æˆ·è¿‡æ»¤å™¨...", "filters": "过滤器", - "logsOlderThan": "早于日志", + "logsOlderThan": "日志早于", "responseStatus": "å“应状æ€", "selectTime": "选择时间", - "notSelected": "未选定", + "notSelected": "未选择", "resetFilters": "é‡ç½®è¿‡æ»¤å™¨", "noLogsDisplay": "æ— æ—¥å¿—å¯æ˜¾ç¤º", - "noLogsThatOld": "å¯èƒ½æ²¡æœ‰ä¿å­˜é€‰å®šæ—¶é—´çš„æ—¥å¿—。å°è¯•选择更近的时间。", + "noLogsThatOld": "选择的时间段å¯èƒ½æ²¡æœ‰æ—¥å¿—。å°è¯•选择近期时间。", "apply": "应用", "selectAll": "全选", "unselectAll": "å–æ¶ˆå…¨é€‰", @@ -169,8 +169,8 @@ "search": "æœç´¢", "dnsQueries": "DNS 查询", "average": "å¹³å‡å€¼", - "blockedFilters": "已被过滤器拦截", - "malwarePhisingBlocked": "è¢«æ‹¦æˆªçš„æ¶æ„软件/é’“é±¼", + "blockedFilters": "被过滤器拦截", + "malwarePhisingBlocked": "è¢«æ‹¦æˆªçš„æ¶æ„/钓鱼网站", "blockedAdultWebsites": "被拦截的æˆäººç½‘ç«™", "generalSettings": "常规设置", "generalSettingsDescription": "å„ç§ä¸åŒçš„设置", @@ -185,7 +185,7 @@ "tags": "标签", "identifiers": "标识符", "identifier": "标识符", - "identifierHelper": "IP 地å€ã€CIDRã€MAC åœ°å€æˆ–客户端ID", + "identifierHelper": "IP 地å€ã€CIDRã€MAC åœ°å€æˆ–客户端 ID", "noIdentifiers": "未添加标识符", "useGlobalSettings": "使用全局设置", "enableFiltering": "å¯ç”¨è¿‡æ»¤", @@ -200,16 +200,16 @@ "tagsSelected": "已选择标签", "upstreamServers": "上游æœåС噍", "serverAddress": "æœåŠ¡å™¨åœ°å€", - "noUpstreamServers": "无上游æœåŠ¡å™¨ã€‚", - "willBeUsedGeneralServers": "将使用常规上游æœåŠ¡å™¨ã€‚", + "noUpstreamServers": "无上游æœåС噍", + "willBeUsedGeneralServers": "将使用常规上游æœåС噍", "added": "已添加", - "clientUpdatedSuccessfully": "客户端已æˆåŠŸæ›´æ–°", - "clientNotUpdated": "客户端未能更新", - "clientDeletedSuccessfully": "客户端已æˆåŠŸåˆ é™¤", - "clientNotDeleted": "客户端未能删除", + "clientUpdatedSuccessfully": "客户端更新æˆåŠŸ", + "clientNotUpdated": "无法更新客户端", + "clientDeletedSuccessfully": "客户端删除æˆåŠŸ", + "clientNotDeleted": "无法删除客户端", "options": "选项", "loadingFilters": "正在加载过滤器...", - "filtersNotLoaded": "无法加载过滤器。", + "filtersNotLoaded": "无法加载过滤器", "whitelists": "白åå•", "blacklists": "黑åå•", "rules": "规则", From 7f45ed4fc7f95a1035c8d9006d4355d5d660948a Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 19:00:49 +0800 Subject: [PATCH 267/676] Update app_zh.arb --- lib/l10n/app_zh.arb | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index edc54a9..b046826 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -234,34 +234,34 @@ "addBlacklist": "添加黑åå•", "urlNotValid": "URL 无效", "urlAbsolutePath": "URL 或ç»å¯¹è·¯å¾„", - "addingList": "正在添加列表...", - "listAdded": "列表已æˆåŠŸæ·»åŠ ã€‚å·²æ·»åŠ é¡¹ç›®ï¼š", - "listAlreadyAdded": "列表已添加", - "listUrlInvalid": "列表 URL 无效", - "listNotAdded": "无法添加列表", - "listDetails": "列表详细信æ¯", - "listType": "列表类型", + "addingList": "正在添加订阅规则...", + "listAdded": "订阅规则添加æˆåŠŸ 。已添加项目:", + "listAlreadyAdded": "订阅规则已被添加", + "listUrlInvalid": "订阅规则 URL 无效", + "listNotAdded": "无法添加订阅规则", + "listDetails": "订阅规则详细信æ¯", + "listType": "订阅规则类型", "whitelist": "白åå•", "blacklist": "黑åå•", "latestUpdate": "最近更新", "disable": "ç¦ç”¨", "enable": "å¯ç”¨", "currentStatus": "当å‰çжæ€", - "listDataUpdated": "列表数æ®å·²æˆåŠŸæ›´æ–°", - "listDataNotUpdated": "无法更新列表数æ®", - "updatingListData": "正在更新列表数æ®...", + "listDataUpdated": "订阅规则更新æˆåŠŸ", + "listDataNotUpdated": "无法更新订阅规则", + "updatingListData": "正在更新订阅规则...", "editWhitelist": "编辑白åå•", "editBlacklist": "编辑黑åå•", - "deletingList": "正在删除列表...", - "listDeleted": "列表已æˆåŠŸåˆ é™¤", - "listNotDeleted": "无法删除列表", - "deleteList": "删除列表", - "deleteListMessage": "您确定è¦åˆ é™¤æ­¤åˆ—表å—?此æ“作无法撤消。", + "deletingList": "正在删除订阅规则...", + "listDeleted": "订阅规则删除æˆåŠŸ", + "listNotDeleted": "无法删除订阅规则", + "deleteList": "删除订阅规则", + "deleteListMessage": "您确定è¦åˆ é™¤æ­¤è®¢é˜…规则å—?此æ“作无法撤消", "serverSettings": "æœåŠ¡å™¨è®¾ç½®", "serverInformation": "æœåŠ¡å™¨ä¿¡æ¯", "serverInformationDescription": "æœåŠ¡å™¨ä¿¡æ¯å’Œçжæ€", "loadingServerInfo": "正在加载æœåŠ¡å™¨ä¿¡æ¯...", - "serverInfoNotLoaded": "无法加载æœåŠ¡å™¨ä¿¡æ¯ã€‚", + "serverInfoNotLoaded": "无法加载æœåŠ¡å™¨ä¿¡æ¯", "dnsAddresses": "DNS 地å€", "seeDnsAddresses": "查看 DNS 地å€", "dnsPort": "DNS 端å£", From a9600783b702fe027d7145d26fbf96714d3cb857 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 19:06:15 +0800 Subject: [PATCH 268/676] Update app_zh.arb --- lib/l10n/app_zh.arb | 154 ++++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index b046826..2150f9d 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -279,24 +279,24 @@ "accessSettings": "访问设置", "accessSettingsDescription": "为æœåС噍é…置访问规则", "loadingClients": "正在加载客户端...", - "clientsNotLoaded": "无法加载客户端。", - "noAllowedClients": "æ— å·²å…许的客户端", - "allowedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†ä»…æŽ¥å—æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求。", - "blockedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†æ‹’ç»æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求。如果已å…许客户端中有æ¡ç›®ï¼Œåˆ™ä¼šå¿½ç•¥æ­¤å­—段。", - "disallowedDomainsDescription": "AdGuard Home 会丢弃与这些域å匹é…çš„ DNS 查询,这些查询甚至ä¸ä¼šå‡ºçŽ°åœ¨æŸ¥è¯¢æ—¥å¿—ä¸­ã€‚", - "addClientFieldDescription": "CIDRã€IP åœ°å€æˆ–客户端ID", + "clientsNotLoaded": "无法加载客户端", + "noAllowedClients": "没有已å…许的客户端", + "allowedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†ä»…æŽ¥å—æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求", + "blockedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†æ‹’ç»æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求。如果已å…许客户端中有æ¡ç›®ï¼Œåˆ™ä¼šå¿½ç•¥æ­¤å­—段", + "disallowedDomainsDescription": "AdGuard Home 会丢弃与这些域å匹é…çš„ DNS 查询,这些查询甚至ä¸ä¼šå‡ºçŽ°åœ¨æŸ¥è¯¢æ—¥å¿—ä¸­", + "addClientFieldDescription": "CIDRã€IP åœ°å€æˆ–客户端 ID", "clientIdentifier": "客户端标识符", "allowClient": "å…许客户端", "disallowClient": "ç¦æ­¢å®¢æˆ·ç«¯", "noDisallowedDomains": "æ— å·²ç¦æ­¢çš„域å", "domainNotAdded": "无法添加域å", "statusSelected": "已选择状æ€", - "updateLists": "更新列表", + "updateLists": "更新订阅规则", "checkHostFiltered": "检查域å", - "updatingLists": "正在更新列表...", - "listsUpdated": "已更新列表", - "listsNotUpdated": "无法更新列表", - "listsNotLoaded": "无法加载列表", + "updatingLists": "正在更新订阅规则...", + "listsUpdated": "已更新订阅规则", + "listsNotUpdated": "无法更新订阅规则", + "listsNotLoaded": "无法加载订阅规则", "domainNotValid": "åŸŸåæ— æ•ˆ", "check": "检查", "checkingHost": "正在检查域å...", @@ -307,19 +307,19 @@ "addImportant": "添加 $important", "howCreateRules": "如何创建自定义规则", "examples": "示例", - "example1": "拦截访问 example.org åŠå…¶æ‰€æœ‰å­åŸŸã€‚", - "example2": "解除对 example.org åŠå…¶æ‰€æœ‰å­åŸŸçš„访问é™åˆ¶ã€‚", - "example3": "添加注释。", - "example4": "拦截访问与指定正则表达å¼åŒ¹é…的域。", + "example1": "拦截访问 example.org åŠå…¶æ‰€æœ‰å­åŸŸ", + "example2": "解除对 example.org åŠå…¶æ‰€æœ‰å­åŸŸçš„访问é™åˆ¶", + "example3": "添加注释", + "example4": "拦截与指定正则表达å¼åŒ¹é…的域", "moreInformation": "更多信æ¯", "addingRule": "正在添加规则...", "deletingRule": "正在删除规则...", - "enablingList": "正在å¯ç”¨åˆ—表...", - "disablingList": "正在ç¦ç”¨åˆ—表...", + "enablingList": "正在å¯ç”¨è®¢é˜…规则...", + "disablingList": "正在ç¦ç”¨è®¢é˜…规则...", "disableFiltering": "ç¦ç”¨è¿‡æ»¤", "enablingFiltering": "正在å¯ç”¨è¿‡æ»¤...", "disablingFiltering": "正在ç¦ç”¨è¿‡æ»¤...", - "filteringStatusUpdated": "过滤状æ€å·²æˆåŠŸæ›´æ–°", + "filteringStatusUpdated": "è¿‡æ»¤çŠ¶æ€æ›´æ–°æˆåŠŸ", "filteringStatusNotUpdated": "无法更新过滤状æ€", "updateFrequency": "更新频率", "never": "从ä¸", @@ -332,9 +332,9 @@ "updateFrequencyChanged": "更新频率已æˆåŠŸæ›´æ”¹", "updateFrequencyNotChanged": "无法更改更新频率", "updating": "正在更新值...", - "blockedServicesUpdated": "å·²æˆåŠŸæ›´æ–°è¢«æ‹¦æˆªçš„æœåŠ¡", + "blockedServicesUpdated": "被拦截的æœåŠ¡æ›´æ–°æˆåŠŸ", "blockedServicesNotUpdated": "无法更新被拦截的æœåŠ¡", - "insertDomain": "è¾“å…¥è¦æ£€æŸ¥çš„域å以查看其状æ€ã€‚", + "insertDomain": "è¾“å…¥è¦æ£€æŸ¥çš„域å以查看其状æ€", "dhcpSettings": "DHCP 设置", "dhcpSettingsDescription": "é…ç½® DHCP æœåС噍", "dhcpSettingsNotLoaded": "无法加载 DHCP 设置", @@ -345,7 +345,7 @@ "gatewayIp": "网关 IP", "ipv4addresses": "IPv4 地å€", "ipv6addresses": "IPv6 地å€", - "neededSelectInterface": "您需è¦é€‰æ‹©ä¸€ä¸ªæŽ¥å£æ¥é…ç½® DHCP æœåŠ¡å™¨ã€‚", + "neededSelectInterface": "您需è¦é€‰æ‹©ä¸€ä¸ªæŽ¥å£æ¥é…ç½® DHCP æœåС噍", "ipv4settings": "IPv4 设置", "startOfRange": "起始范围", "endOfRange": "结æŸèŒƒå›´", @@ -358,21 +358,21 @@ "seconds": "{time} ç§’", "leaseTimeNotValid": "租期无效", "restoreConfiguration": "é‡ç½®é…ç½®", - "restoreConfigurationMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰é…置。此æ“作无法撤消。", + "restoreConfigurationMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰é…置。此æ“作无法撤消", "changeInterface": "更改接å£", "savingSettings": "正在ä¿å­˜è®¾ç½®...", - "settingsSaved": "设置已æˆåŠŸä¿å­˜", + "settingsSaved": "设置ä¿å­˜æˆåŠŸ", "settingsNotSaved": "无法ä¿å­˜è®¾ç½®", "restoringConfig": "正在还原é…ç½®...", - "configRestored": "é…置已æˆåŠŸé‡ç½®", - "configNotRestored": "é…置无法é‡ç½®", + "configRestored": "é…置还原æˆåŠŸ", + "configNotRestored": "无法还原é…ç½®", "dhcpStatic": "DHCP 陿€ç§Ÿç”¨", "noDhcpStaticLeases": "未找到 DHCP 陿€ç§Ÿç”¨", "deleting": "正在删除...", "staticLeaseDeleted": "DHCP 陿€ç§Ÿç”¨å·²æˆåŠŸåˆ é™¤", "staticLeaseNotDeleted": "无法删除 DHCP 陿€ç§Ÿç”¨", "deleteStaticLease": "åˆ é™¤é™æ€ç§Ÿç”¨", - "deleteStaticLeaseDescription": "DHCP 陿€ç§Ÿç”¨å°†è¢«åˆ é™¤ã€‚æ­¤æ“作无法撤消。", + "deleteStaticLeaseDescription": "DHCP 陿€ç§Ÿç”¨å°†è¢«åˆ é™¤ã€‚æ­¤æ“作无法撤消", "addStaticLease": "æ·»åŠ é™æ€ç§Ÿç”¨", "macAddress": "MAC 地å€", "macAddressNotValid": "MAC åœ°å€æ— æ•ˆ", @@ -384,7 +384,7 @@ "staticLeaseExists": "DHCP 陿€ç§Ÿç”¨å·²å­˜åœ¨", "serverNotConfigured": "未é…ç½®æœåС噍", "restoreLeases": "é‡ç½®ç§Ÿç”¨", - "restoreLeasesMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰çŽ°æœ‰ç§Ÿç”¨ã€‚æ­¤æ“作无法撤消。", + "restoreLeasesMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰çŽ°æœ‰ç§Ÿç”¨ã€‚æ­¤æ“作无法撤消", "restoringLeases": "正在é‡ç½®ç§Ÿç”¨...", "leasesRestored": "租用已æˆåŠŸé‡ç½®", "leasesNotRestored": "租用无法é‡ç½®", @@ -393,16 +393,16 @@ "dnsRewrites": "DNS é‡å†™", "dnsRewritesDescription": "é…置自定义 DNS 规则", "loadingRewriteRules": "正在加载é‡å†™è§„则...", - "rewriteRulesNotLoaded": "无法加载 DNS é‡å†™è§„则。", + "rewriteRulesNotLoaded": "无法加载 DNS é‡å†™è§„则", "noRewriteRules": "æ—  DNS é‡å†™è§„则", "answer": "回答", "deleteDnsRewrite": "删除 DNS é‡å†™", - "deleteDnsRewriteMessage": "您确定è¦åˆ é™¤æ­¤ DNS é‡å†™å—?此æ“作无法撤消。", - "dnsRewriteRuleDeleted": "DNS é‡å†™è§„则已æˆåŠŸåˆ é™¤", + "deleteDnsRewriteMessage": "您确定è¦åˆ é™¤æ­¤ DNS é‡å†™å—?此æ“作无法撤消", + "dnsRewriteRuleDeleted": "DNS é‡å†™è§„则删除æˆåŠŸ", "dnsRewriteRuleNotDeleted": "无法删除 DNS é‡å†™è§„则", "addDnsRewrite": "添加 DNS é‡å†™", "addingRewrite": "正在添加é‡å†™...", - "dnsRewriteRuleAdded": "DNS é‡å†™è§„则已æˆåŠŸæ·»åŠ ", + "dnsRewriteRuleAdded": "DNS é‡å†™è§„则添加æˆåŠŸ", "dnsRewriteRuleNotAdded": "无法添加 DNS é‡å†™è§„则", "logsSettings": "日志设置", "enableLog": "å¯ç”¨æ—¥å¿—", @@ -413,12 +413,12 @@ "days90": "90 天", "retentionTime": "ä¿ç•™æ—¶é—´", "selectOneItem": "选择一项", - "logSettingsNotLoaded": "无法加载日志设置。", + "logSettingsNotLoaded": "无法加载日志设置", "updatingSettings": "正在更新设置...", - "logsConfigUpdated": "日志设置已æˆåŠŸæ›´æ–°", + "logsConfigUpdated": "日志设置更新æˆåŠŸ", "logsConfigNotUpdated": "无法更新日志设置", "deletingLogs": "正在清除日志...", - "logsCleared": "日志已æˆåŠŸæ¸…é™¤", + "logsCleared": "日志清除æˆåŠŸ", "logsNotCleared": "无法清除日志", "runningHomeAssistant": "在 Home Assistant 上è¿è¡Œ", "serverError": "æœåŠ¡å™¨é”™è¯¯", @@ -433,55 +433,55 @@ "loadBalancing": "è´Ÿè½½å‡è¡¡", "parallelRequests": "并行请求", "fastestIpAddress": "最快的 IP 地å€", - "loadBalancingDescription": "æ¯æ¬¡æŸ¥è¯¢ä¸€ä¸ªä¸Šæ¸¸æœåŠ¡å™¨ã€‚AdGuard Home 使用其加æƒéšæœºç®—æ³•é€‰æ‹©æœåŠ¡å™¨ï¼Œä»¥ä¾¿æ›´é¢‘ç¹åœ°ä½¿ç”¨æœ€å¿«çš„æœåŠ¡å™¨ã€‚", - "parallelRequestsDescription": "ä½¿ç”¨å¹¶è¡ŒæŸ¥è¯¢åŒæ—¶åŠ é€Ÿè§£æžï¼ŒåŒæ—¶æŸ¥è¯¢æ‰€æœ‰ä¸Šæ¸¸æœåŠ¡å™¨ã€‚", - "fastestIpAddressDescription": "查询所有 DNS æœåŠ¡å™¨å¹¶è¿”å›žæ‰€æœ‰å“应中最快的 IP 地å€ã€‚è¿™ä¼šå‡æ…¢ DNS 查询,因为 AdGuard Home 必须等待所有 DNS æœåŠ¡å™¨çš„å“应,但å¯ä»¥æ”¹å–„整体连接性。", + "loadBalancingDescription": "æ¯æ¬¡æŸ¥è¯¢ä¸€ä¸ªä¸Šæ¸¸æœåŠ¡å™¨ã€‚AdGuard Home 使用其加æƒéšæœºç®—æ³•é€‰æ‹©æœåŠ¡å™¨ï¼Œä»¥ä¾¿æ›´é¢‘ç¹åœ°ä½¿ç”¨æœ€å¿«çš„æœåŠ¡å™¨", + "parallelRequestsDescription": "ä½¿ç”¨å¹¶è¡ŒæŸ¥è¯¢åŒæ—¶åŠ é€Ÿè§£æžï¼ŒåŒæ—¶æŸ¥è¯¢æ‰€æœ‰ä¸Šæ¸¸æœåС噍", + "fastestIpAddressDescription": "查询所有 DNS æœåŠ¡å™¨å¹¶è¿”å›žæ‰€æœ‰å“应中最快的 IP 地å€ã€‚è¿™ä¼šå‡æ…¢ DNS 查询,因为 AdGuard Home 必须等待所有 DNS æœåŠ¡å™¨çš„å“应,但å¯ä»¥æ”¹å–„整体连接性", "noBootstrapDns": "未添加引导 DNS æœåŠ¡å™¨ã€‚", "bootstrapDnsServersInfo": "引导 DNS æœåŠ¡å™¨ç”¨äºŽè§£æžæ‚¨æŒ‡å®šçš„上游 DoH/DoT è§£æžå™¨çš„ IP 地å€ã€‚", "privateReverseDnsServers": "ç§æœ‰åå‘ DNS æœåС噍", "privateReverseDnsServersDescription": "AdGuard Home 用于本地 PTR 查询的 DNS æœåŠ¡å™¨ã€‚è¿™äº›æœåŠ¡å™¨ç”¨äºŽè§£æžç§æœ‰ IP 范围内的地å€çš„ PTR 请求,例如 \"192.168.12.34\"。如果未设置,AdGuard Home 将使用æ“作系统的默认 DNS è§£æžå™¨åœ°å€ï¼Œä½†ä¸åŒ…括 AdGuard Home 本身的地å€ã€‚", "reverseDnsDefault": "默认情况下,AdGuard Home 使用以下默认åå‘ DNS è§£æžå™¨", "addItem": "添加项目", - "noServerAddressesAdded": "未添加æœåŠ¡å™¨åœ°å€ã€‚", + "noServerAddressesAdded": "未添加æœåŠ¡å™¨åœ°å€", "usePrivateReverseDnsResolvers": "ä½¿ç”¨ç§æœ‰åå‘ DNS è§£æžå™¨", - "usePrivateReverseDnsResolversDescription": "使用这些上游æœåŠ¡å™¨æ‰§è¡Œæœ¬åœ°æä¾›çš„地å€çš„åå‘ DNS 查询。如果ç¦ç”¨ï¼ŒAdGuard Home 会对所有此类 PTR 请求(除了æ¥è‡ª DHCPã€/etc/hosts 等已知客户端)å“应 NXDOMAIN。", + "usePrivateReverseDnsResolversDescription": "使用这些上游æœåŠ¡å™¨æ‰§è¡Œæœ¬åœ°æä¾›çš„地å€çš„åå‘ DNS 查询。如果ç¦ç”¨ï¼ŒAdGuard Home 会对所有此类 PTR 请求(除了æ¥è‡ª DHCPã€/etc/hosts 等已知客户端)å“应 NXDOMAIN", "enableReverseResolving": "å¯ç”¨å®¢æˆ·ç«¯ IP 地å€çš„åå‘è§£æž", - "enableReverseResolvingDescription": "通过å‘相应的解æžå™¨å‘é€ PTR 查询,将客户端 IP 地å€è¿›è¡Œåå‘è§£æžä¸ºä¸»æœºåï¼ˆå¯¹äºŽæœ¬åœ°å®¢æˆ·ç«¯ä½¿ç”¨ç§æœ‰ DNS æœåŠ¡å™¨ï¼Œå¯¹äºŽå…·æœ‰å…¬å…± IP 地å€çš„客户端使用上游æœåŠ¡å™¨ï¼‰ã€‚", + "enableReverseResolvingDescription": "通过å‘相应的解æžå™¨å‘é€ PTR 查询,将客户端 IP 地å€è¿›è¡Œåå‘è§£æžä¸ºä¸»æœºåï¼ˆå¯¹äºŽæœ¬åœ°å®¢æˆ·ç«¯ä½¿ç”¨ç§æœ‰ DNS æœåŠ¡å™¨ï¼Œå¯¹äºŽå…·æœ‰å…¬å…± IP 地å€çš„客户端使用上游æœåŠ¡å™¨ï¼‰", "dnsServerSettings": "AdGuard Home DNS æœåŠ¡å™¨è®¾ç½®", "limitRequestsSecond": "æ¯ç§’速率é™åˆ¶", "valueNotNumber": "值䏿˜¯æ•°å­—", "enableEdns": "å¯ç”¨ EDNS 客户å­ç½‘", - "enableEdnsDescription": "在上游请求中添加 EDNS 客户å­ç½‘选项(ECS),并在查询日志中记录客户端å‘é€çš„值。", + "enableEdnsDescription": "在上游请求中添加 EDNS 客户å­ç½‘选项(ECS),并在查询日志中记录客户端å‘é€çš„值", "enableDnssec": "å¯ç”¨ DNSSEC", - "enableDnssecDescription": "在传出的 DNS 查询中设置 DNSSEC 标志并检查结果(需è¦å¯ç”¨ DNSSEC 的解æžå™¨ï¼‰ã€‚", + "enableDnssecDescription": "在传出的 DNS 查询中设置 DNSSEC 标志并检查结果(需è¦å¯ç”¨ DNSSEC 的解æžå™¨ï¼‰", "disableResolvingIpv6": "ç¦ç”¨ IPv6 地å€è§£æž", - "disableResolvingIpv6Description": "丢弃所有用于 IPv6 地å€ï¼ˆç±»åž‹ AAAA)的 DNS 查询。", + "disableResolvingIpv6Description": "丢弃所有用于 IPv6 地å€ï¼ˆAAAA 记录)的 DNS 查询", "blockingMode": "拦截模å¼", "defaultMode": "默认", "defaultDescription": "当按照 Adblock æ ·å¼è§„则被拦截时,返回零 IP 地å€ï¼ˆ0.0.0.0 对应 Aï¼›:: 对应 AAAA);当按照 /etc/hosts æ ·å¼è§„则被拦截时,返回规则中指定的 IP 地å€", "refusedDescription": "返回 REFUSED 代ç ", "nxdomainDescription": "返回 NXDOMAIN 代ç ", "nullIp": "空 IP", - "nullIpDescription": "返回零 IP 地å€ï¼ˆ0.0.0.0 对应 Aï¼›:: 对应 AAAA)", + "nullIpDescription": "返回空 IP 地å€ï¼ˆ0.0.0.0 对应 Aï¼›:: 对应 AAAA)", "customIp": "自定义 IP", "customIpDescription": "返回手动设置的 IP 地å€", "dnsCacheConfig": "DNS 缓存é…ç½®", "cacheSize": "缓存大å°", "inBytes": "字节", "overrideMinimumTtl": "è¦†ç›–æœ€å° TTL", - "overrideMinimumTtlDescription": "在缓存 DNS å“应时,从上游æœåŠ¡å™¨æŽ¥æ”¶åˆ°çš„æœ€çŸ­çš„å­˜æ´»æ—¶é—´å€¼ï¼ˆç§’ï¼‰ã€‚", + "overrideMinimumTtlDescription": "在缓存 DNS å“应时,从上游æœåŠ¡å™¨æŽ¥æ”¶åˆ°çš„æœ€çŸ­çš„å­˜æ´»æ—¶é—´å€¼ï¼ˆç§’ï¼‰", "overrideMaximumTtl": "覆盖最大 TTL", - "overrideMaximumTtlDescription": "为 DNS 缓存æ¡ç›®è®¾ç½®æœ€å¤§å­˜æ´»æ—¶é—´å€¼ï¼ˆç§’)。", + "overrideMaximumTtlDescription": "为 DNS 缓存æ¡ç›®è®¾ç½®æœ€å¤§å­˜æ´»æ—¶é—´å€¼ï¼ˆç§’)", "optimisticCaching": "ä¹è§‚缓存", - "optimisticCachingDescription": "å³ä½¿æ¡ç›®å·²è¿‡æœŸï¼ŒAdGuard Home 也将从缓存中å“应,并å°è¯•刷新它们。", + "optimisticCachingDescription": "å³ä½¿æ¡ç›®å·²è¿‡æœŸï¼ŒAdGuard Home 也将从缓存中å“应,并å°è¯•刷新它们", "loadingDnsConfig": "正在加载 DNS é…ç½®...", - "dnsConfigNotLoaded": "无法加载 DNS é…置。", + "dnsConfigNotLoaded": "无法加载 DNS é…ç½®", "blockingIpv4": "拦截 IPv4", - "blockingIpv4Description": "当 A 请求被拦截时返回的 IP 地å€", + "blockingIpv4Description": "æ‹¦æˆªåŒ…å« A 记录的请求时返回的 IP 地å€", "blockingIpv6": "拦截 IPv6", - "blockingIpv6Description": "当 AAAA 请求被拦截时返回的 IP 地å€", + "blockingIpv6Description": "æ‹¦æˆªåŒ…å« AAAA 记录的请求时返回的 IP 地å€", "invalidIp": "无效的 IP 地å€", - "dnsConfigSaved": "DNS æœåС噍é…置已æˆåŠŸä¿å­˜", + "dnsConfigSaved": "DNS æœåС噍é…ç½®ä¿å­˜æˆåŠŸ", "dnsConfigNotSaved": "DNS æœåС噍é…置无法ä¿å­˜", "savingConfig": "正在ä¿å­˜é…ç½®...", "someValueNotValid": "æŸäº›å€¼æ— æ•ˆ", @@ -492,23 +492,23 @@ "dnsCacheConfigDescription": "é…ç½®æœåŠ¡å™¨å¦‚ä½•ç®¡ç† DNS 缓存", "comment": "注释", "address": "地å€", - "commentsDescription": "注释始终以 # 开头。您无需添加它,系统将自动添加。", + "commentsDescription": "注释始终以 # 开头。您无需添加它,系统将自动添加", "encryptionSettings": "加密设置", "encryptionSettingsDescription": "加密(HTTPS/QUIC/TLS)支æŒ", "loadingEncryptionSettings": "正在加载加密设置...", - "encryptionSettingsNotLoaded": "无法加载加密设置。", + "encryptionSettingsNotLoaded": "无法加载加密设置", "enableEncryption": "å¯ç”¨åР坆", "enableEncryptionTypes": "HTTPSã€DNS-over-HTTPS å’Œ DNS-over-TLS", - "enableEncryptionDescription": "如果å¯ç”¨åŠ å¯†ï¼ŒAdGuard Home 管ç†ç•Œé¢å°†é€šè¿‡ HTTPS è¿è¡Œï¼Œå¹¶ä¸” DNS æœåŠ¡å™¨å°†ç›‘å¬ DNS-over-HTTPS å’Œ DNS-over-TLS 请求。", + "enableEncryptionDescription": "如果å¯ç”¨åŠ å¯†ï¼ŒAdGuard Home 管ç†ç•Œé¢å°†é€šè¿‡ HTTPS è¿è¡Œï¼Œå¹¶ä¸” DNS æœåŠ¡å™¨å°†ç›‘å¬ DNS-over-HTTPS å’Œ DNS-over-TLS 请求", "serverConfiguration": "æœåС噍é…ç½®", "domainName": "域å", - "domainNameDescription": "如果设置,AdGuard Home 将检测 ClientIDã€å“应 DDR 查询并执行其他连接验è¯ã€‚如果未设置,这些功能将被ç¦ç”¨ã€‚必须与è¯ä¹¦ä¸­çš„ DNS å称之一匹é…。", + "domainNameDescription": "如果设置,AdGuard Home 将检测 ClientIDã€å“应 DDR 查询并执行其他连接验è¯ã€‚如果未设置,这些功能将被ç¦ç”¨ã€‚必须与è¯ä¹¦ä¸­çš„ DNS å称之一匹é…", "redirectHttps": "自动é‡å®šå‘到 HTTPS", "httpsPort": "HTTPS 端å£", "tlsPort": "DNS-over-TLS 端å£", "dnsOverQuicPort": "DNS-over-QUIC 端å£", "certificates": "è¯ä¹¦", - "certificatesDescription": "为了使用加密,您需è¦ä¸ºæ‚¨çš„域æä¾›æœ‰æ•ˆçš„ SSL è¯ä¹¦é“¾ã€‚您å¯ä»¥åœ¨ letsencrypt.org 上获得å…è´¹è¯ä¹¦ï¼Œä¹Ÿå¯ä»¥ä»Žå—信任的è¯ä¹¦é¢å‘机构购买。", + "certificatesDescription": "为了使用加密,您需è¦ä¸ºæ‚¨çš„域æä¾›æœ‰æ•ˆçš„ SSL è¯ä¹¦é“¾ã€‚您å¯ä»¥åœ¨ letsencrypt.org 上获得å…è´¹è¯ä¹¦ï¼Œä¹Ÿå¯ä»¥ä»Žå—信任的è¯ä¹¦é¢å‘机构购买", "certificateFilePath": "设置è¯ä¹¦æ–‡ä»¶è·¯å¾„", "pasteCertificateContent": "粘贴è¯ä¹¦å†…容", "certificatePath": "è¯ä¹¦è·¯å¾„", @@ -528,7 +528,7 @@ "configError": "é…置错误", "enterOnlyCertificate": "åªè¾“å…¥è¯ä¹¦ã€‚ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", "enterOnlyPrivateKey": "åªè¾“入密钥。ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", - "noItemsSearch": "没有匹é…的项目。", + "noItemsSearch": "没有匹é…的项目", "clearSearch": "清除æœç´¢", "exitSearch": "退出æœç´¢", "searchClients": "æœç´¢å®¢æˆ·ç«¯", @@ -557,7 +557,7 @@ "expires": "过期", "validPrivateKey": "有效的ç§é’¥", "expirationDate": "到期日期", - "keysNotMatch": "无效的è¯ä¹¦æˆ–密钥:tls: private key does not match public key", + "keysNotMatch": "无效的è¯ä¹¦æˆ–密钥:tls: ç§é’¥ä¸Žå…¬é’¥ä¸åŒ¹é…", "timeLogs": "日志时间", "timeLogsDescription": "åœ¨æ—¥å¿—åˆ—è¡¨ä¸­æ˜¾ç¤ºå¤„ç†æ—¶é—´", "hostNames": "主机å", @@ -572,13 +572,13 @@ "downloadingUpdate": "正在下载", "completed": "已完æˆ", "permissionNotGranted": "未授予æƒé™", - "inputSearchTerm": "输入æœç´¢è¯ã€‚", + "inputSearchTerm": "输入æœç´¢è¯", "answers": "回答", "copyClipboard": "å¤åˆ¶åˆ°å‰ªè´´æ¿", "domainCopiedClipboard": "域åå·²å¤åˆ¶åˆ°å‰ªè´´æ¿", "clearDnsCache": "清除 DNS 缓存", "clearDnsCacheMessage": "æ‚¨ç¡®å®šè¦æ¸…除 DNS 缓存å—?", - "dnsCacheCleared": "DNS 缓存已æˆåŠŸæ¸…é™¤", + "dnsCacheCleared": "DNS 缓存清除æˆåŠŸ", "clearingDnsCache": "正在清除缓存...", "dnsCacheNotCleared": "无法清除 DNS 缓存", "clientsSelected": "已选择客户端", @@ -590,15 +590,15 @@ "updatesDescription": "æ›´æ–° AdGuard Home ", "updateNow": "ç«‹å³æ›´æ–°", "currentVersion": "当å‰ç‰ˆæœ¬", - "requestStartUpdateFailed": "请求开始更新失败", - "requestStartUpdateSuccessful": "请求开始更新æˆåŠŸ", - "serverUpdated": "AdGuardHome 已是最新版", + "requestStartUpdateFailed": "请求å¯åŠ¨æ›´æ–°å¤±è´¥", + "requestStartUpdateSuccessful": "请求å¯åŠ¨æ›´æ–°æˆåŠŸ", + "serverUpdated": "AdGuard Home 已是最新版", "unknownStatus": "未知状æ€", "checkingUpdates": "正在检查更新...", "checkUpdates": "检查更新", - "requestingUpdate": "请求更新中...", + "requestingUpdate": "正在请求更新...", "autoupdateUnavailable": "自动更新ä¸å¯ç”¨", - "autoupdateUnavailableDescription": "æ­¤æœåС噍䏿”¯æŒè‡ªåŠ¨æ›´æ–°æœåŠ¡ã€‚è¿™å¯èƒ½æ˜¯å› ä¸ºæœåŠ¡å™¨æ­£åœ¨ Docker 容器中è¿è¡Œã€‚æ‚¨éœ€è¦æ‰‹åŠ¨æ›´æ–°æœåŠ¡å™¨ã€‚", + "autoupdateUnavailableDescription": "æ­¤æœåС噍䏿”¯æŒè‡ªåŠ¨æ›´æ–°æœåŠ¡ã€‚è¿™å¯èƒ½æ˜¯å› ä¸ºæœåŠ¡å™¨æ­£åœ¨ Docker 容器中è¿è¡Œã€‚æ‚¨éœ€è¦æ‰‹åŠ¨æ›´æ–°æœåС噍", "minute": "{time} 分钟", "minutes": "{time} 分钟", "hour": "{time} å°æ—¶", @@ -610,33 +610,33 @@ "loadingLogsSettings": "正在加载日志设置...", "selectOptionLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªé€‰é¡¹", "selectClientLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªå®¢æˆ·ç«¯", - "disableList": "ç¦ç”¨åˆ—表", - "enableList": "å¯ç”¨åˆ—表", + "disableList": "ç¦ç”¨è®¢é˜…规则", + "enableList": "å¯ç”¨è®¢é˜…规则", "screens": "å±å¹•", "copiedClipboard": "å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", "seeDetails": "查看详细信æ¯", - "listNotAvailable": "列表ä¸å¯ç”¨", - "copyListUrl": "å¤åˆ¶åˆ—表 URL", - "listUrlCopied": "列表 URL å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", + "listNotAvailable": "订阅规则ä¸å¯ç”¨", + "copyListUrl": "å¤åˆ¶è®¢é˜…规则 URL", + "listUrlCopied": "订阅规则 URL å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", "unsupportedVersion": "䏿”¯æŒçš„版本", - "unsupprtedVersionMessage": "对于您的æœåŠ¡å™¨ç‰ˆæœ¬ {version},ä¸ä¿è¯æ”¯æŒã€‚该应用程åºåœ¨ä½¿ç”¨è¯¥æœåŠ¡å™¨ç‰ˆæœ¬æ—¶å¯èƒ½ä¼šå‡ºçŽ°ä¸€äº›é—®é¢˜ã€‚\n\nAdGuard Home 管ç†å™¨è®¾è®¡ç”¨äºŽä¸Ž AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬é…åˆä½¿ç”¨ã€‚它å¯èƒ½ä¸Ž Alpha å’Œ Beta 版本一起工作,但ä¸ä¿è¯å…¼å®¹æ€§ï¼Œè¯¥ç‰ˆæœ¬çš„应用程åºå¯èƒ½åœ¨ä¸Žè¯¥ç‰ˆæœ¬ä¸€èµ·å·¥ä½œæ—¶ä¼šå‡ºçŽ°ä¸€äº›é—®é¢˜ã€‚", + "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\\n\\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ã€‚alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", "iUnderstand": "我了解", "appUpdates": "åº”ç”¨ç¨‹åºæ›´æ–°", "usingLatestVersion": "您正在使用最新版本", - "ipLogs": "日志中的 IP", + "ipLogs": "日志中显示 IP", "ipLogsDescription": "始终在日志中显示 IP 地å€ï¼Œè€Œä¸æ˜¯å®¢æˆ·ç«¯åç§°", "application": "应用程åº", "combinedChart": "åˆå¹¶å›¾è¡¨", "combinedChartDescription": "将所有图表åˆå¹¶ä¸ºä¸€ä¸ª", "statistics": "统计", - "errorLoadFilters": "加载过滤器时出错。", - "clientRemovedSuccessfully": "客户端已æˆåŠŸç§»é™¤ã€‚", + "errorLoadFilters": "加载过滤器时出错", + "clientRemovedSuccessfully": "客户端删除æˆåŠŸ", "editRewriteRule": "编辑é‡å†™è§„则", - "dnsRewriteRuleUpdated": "DNS é‡å†™è§„则已æˆåŠŸæ›´æ–°", + "dnsRewriteRuleUpdated": "DNS é‡å†™è§„则更新æˆåŠŸ", "dnsRewriteRuleNotUpdated": "无法更新 DNS é‡å†™è§„则", "updatingRule": "正在更新规则...", "serverUpdateNeeded": "éœ€è¦æ›´æ–°æœåС噍", - "updateYourServer": "å°† AdGuard Home æœåŠ¡å™¨æ›´æ–°åˆ° {version} 或更高版本以使用此功能。", + "updateYourServer": "å°† AdGuard Home æœåŠ¡å™¨æ›´æ–°åˆ° {version} 或更高版本以使用此功能", "january": "1月", "february": "2月", "march": "3月", @@ -649,7 +649,7 @@ "october": "10月", "november": "11月", "december": "12月", - "malwarePhising": "æ¶æ„软件/é’“é±¼", + "malwarePhising": "æ¶æ„/钓鱼网站", "queries": "查询", "adultSites": "æˆäººç½‘ç«™", "quickFilters": "快速过滤器", From 1f02e9bb61bb1f358c2a1096443f11425055aea1 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 19:07:49 +0800 Subject: [PATCH 269/676] Update and rename app_zh.arb to app_zh_CN.arb --- lib/l10n/{app_zh.arb => app_zh_CN.arb} | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) rename lib/l10n/{app_zh.arb => app_zh_CN.arb} (98%) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh_CN.arb similarity index 98% rename from lib/l10n/app_zh.arb rename to lib/l10n/app_zh_CN.arb index 2150f9d..b75c8e9 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh_CN.arb @@ -66,8 +66,8 @@ "dark": "暗夜", "systemDefined": "è·Ÿéšç³»ç»Ÿ", "close": "关闭", - "connectedTo": "连接到:", - "selectedServer": "选定的æœåŠ¡å™¨ï¼š", + "connectedTo": "连接到 :", + "selectedServer": "选择的æœåС噍 :", "noServerSelected": "未选择æœåС噍", "manageServer": "ç®¡ç†æœåС噍", "allProtections": "æ‰€æœ‰ä¿æŠ¤", @@ -219,12 +219,12 @@ "disabled": "å·²ç¦ç”¨", "rule": "规则", "addCustomRule": "添加自定义规则", - "removeCustomRule": "移除自定义规则", - "removeCustomRuleMessage": "您确定è¦ç§»é™¤æ­¤è‡ªå®šä¹‰è§„则å—?", + "removeCustomRule": "删除自定义规则", + "removeCustomRuleMessage": "您确定è¦åˆ é™¤æ­¤è‡ªå®šä¹‰è§„则å—?", "updatingRules": "正在更新自定义规则...", - "ruleRemovedSuccessfully": "规则已æˆåŠŸç§»é™¤", - "ruleNotRemoved": "无法移除规则", - "ruleAddedSuccessfully": "规则已æˆåŠŸæ·»åŠ ", + "ruleRemovedSuccessfully": "规则删除æˆåŠŸ", + "ruleNotRemoved": "无法删除规则", + "ruleAddedSuccessfully": "规则添加æˆåŠŸ", "ruleNotAdded": "无法添加规则", "noCustomFilters": "无自定义过滤器", "noBlockedClients": "无已拦截的客户端", @@ -369,7 +369,7 @@ "dhcpStatic": "DHCP 陿€ç§Ÿç”¨", "noDhcpStaticLeases": "未找到 DHCP 陿€ç§Ÿç”¨", "deleting": "正在删除...", - "staticLeaseDeleted": "DHCP 陿€ç§Ÿç”¨å·²æˆåŠŸåˆ é™¤", + "staticLeaseDeleted": "DHCP 陿€ç§Ÿç”¨åˆ é™¤æˆåŠŸ", "staticLeaseNotDeleted": "无法删除 DHCP 陿€ç§Ÿç”¨", "deleteStaticLease": "åˆ é™¤é™æ€ç§Ÿç”¨", "deleteStaticLeaseDescription": "DHCP 陿€ç§Ÿç”¨å°†è¢«åˆ é™¤ã€‚æ­¤æ“作无法撤消", @@ -379,15 +379,15 @@ "hostName": "主机å", "hostNameError": "主机åä¸èƒ½ä¸ºç©º", "creating": "正在创建...", - "staticLeaseCreated": "DHCP 陿€ç§Ÿç”¨å·²æˆåŠŸåˆ›å»º", + "staticLeaseCreated": "DHCP 陿€ç§Ÿç”¨åˆ›å»ºæˆåŠŸ", "staticLeaseNotCreated": "无法创建 DHCP 陿€ç§Ÿç”¨", "staticLeaseExists": "DHCP 陿€ç§Ÿç”¨å·²å­˜åœ¨", "serverNotConfigured": "未é…ç½®æœåС噍", "restoreLeases": "é‡ç½®ç§Ÿç”¨", "restoreLeasesMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰çŽ°æœ‰ç§Ÿç”¨ã€‚æ­¤æ“作无法撤消", "restoringLeases": "正在é‡ç½®ç§Ÿç”¨...", - "leasesRestored": "租用已æˆåŠŸé‡ç½®", - "leasesNotRestored": "租用无法é‡ç½®", + "leasesRestored": "租用é‡ç½®æˆåŠŸ", + "leasesNotRestored": "无法é‡ç½®ç§Ÿç”¨", "dhcpLeases": "DHCP 租用", "noLeases": "æ— å¯ç”¨çš„ DHCP 租用", "dnsRewrites": "DNS é‡å†™", From 6192ca33ecbcb74d4a9b49c2cddac4332be7c8f9 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 19:08:07 +0800 Subject: [PATCH 270/676] Update main.dart --- lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 20b94bb..e82684a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -227,7 +227,7 @@ class _MainState extends State
{ supportedLocales: const [ Locale('en', ''), Locale('es', ''), - Locale('zh', '') + Locale('zh', 'CN') ], scaffoldMessengerKey: scaffoldMessengerKey, builder: (context, child) { From 45a4de6750cca07defcc65b8709d1905093777b7 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 19:46:42 +0800 Subject: [PATCH 271/676] Update app_zh_CN.arb --- lib/l10n/app_zh_CN.arb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb index b75c8e9..f4b07b2 100644 --- a/lib/l10n/app_zh_CN.arb +++ b/lib/l10n/app_zh_CN.arb @@ -109,8 +109,8 @@ "restartAppTakeEffect": "釿–°å¯åŠ¨åº”ç”¨ç¨‹åº", "loadingLogs": "正在加载日志...", "logsNotLoaded": "无法加载日志列表", - "processed": "已处ç†\n无订阅规则拦截", - "processedRow": "已处ç†ï¼ˆæ— è®¢é˜…规则拦截)", + "processed": "已处ç†\n无拦截", + "processedRow": "已处ç†ï¼ˆæ— æ‹¦æˆªï¼‰", "blockedBlacklist": "已拦截\n黑åå•", "blockedBlacklistRow": "已拦截(黑åå•)", "blockedSafeBrowsing": "已拦截\n安全æµè§ˆ", @@ -214,7 +214,7 @@ "blacklists": "黑åå•", "rules": "规则", "customRules": "自定义规则", - "enabledRules": "å·²å¯ç”¨çš„规则", + "enabledRules": "æ¡è§„则已应用", "enabled": "å·²å¯ç”¨", "disabled": "å·²ç¦ç”¨", "rule": "规则", @@ -302,7 +302,7 @@ "checkingHost": "正在检查域å...", "errorCheckingHost": "无法检查域å", "block": "拦截", - "unblock": "解除拦截", + "unblock": "放行", "custom": "自定义", "addImportant": "添加 $important", "howCreateRules": "如何创建自定义规则", @@ -395,7 +395,7 @@ "loadingRewriteRules": "正在加载é‡å†™è§„则...", "rewriteRulesNotLoaded": "无法加载 DNS é‡å†™è§„则", "noRewriteRules": "æ—  DNS é‡å†™è§„则", - "answer": "回答", + "answer": "å“应", "deleteDnsRewrite": "删除 DNS é‡å†™", "deleteDnsRewriteMessage": "您确定è¦åˆ é™¤æ­¤ DNS é‡å†™å—?此æ“作无法撤消", "dnsRewriteRuleDeleted": "DNS é‡å†™è§„则删除æˆåŠŸ", @@ -558,7 +558,7 @@ "validPrivateKey": "有效的ç§é’¥", "expirationDate": "到期日期", "keysNotMatch": "无效的è¯ä¹¦æˆ–密钥:tls: ç§é’¥ä¸Žå…¬é’¥ä¸åŒ¹é…", - "timeLogs": "日志时间", + "timeLogs": "æ˜¾ç¤ºå¤„ç†æ—¶é—´", "timeLogsDescription": "åœ¨æ—¥å¿—åˆ—è¡¨ä¸­æ˜¾ç¤ºå¤„ç†æ—¶é—´", "hostNames": "主机å", "keyType": "密钥类型", @@ -573,7 +573,7 @@ "completed": "已完æˆ", "permissionNotGranted": "未授予æƒé™", "inputSearchTerm": "输入æœç´¢è¯", - "answers": "回答", + "answers": "å“应", "copyClipboard": "å¤åˆ¶åˆ°å‰ªè´´æ¿", "domainCopiedClipboard": "域åå·²å¤åˆ¶åˆ°å‰ªè´´æ¿", "clearDnsCache": "清除 DNS 缓存", @@ -623,7 +623,7 @@ "iUnderstand": "我了解", "appUpdates": "åº”ç”¨ç¨‹åºæ›´æ–°", "usingLatestVersion": "您正在使用最新版本", - "ipLogs": "日志中显示 IP", + "ipLogs": "显示客户端 IP", "ipLogsDescription": "始终在日志中显示 IP 地å€ï¼Œè€Œä¸æ˜¯å®¢æˆ·ç«¯åç§°", "application": "应用程åº", "combinedChart": "åˆå¹¶å›¾è¡¨", From 13fb0886a01148475bfa28aaaf943224986267d8 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 20:01:54 +0800 Subject: [PATCH 272/676] Update app_zh_CN.arb --- lib/l10n/app_zh_CN.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb index f4b07b2..5c0a77c 100644 --- a/lib/l10n/app_zh_CN.arb +++ b/lib/l10n/app_zh_CN.arb @@ -23,7 +23,7 @@ "invalidUsernamePassword": "ç”¨æˆ·åæˆ–密ç é”™è¯¯", "tooManyAttempts": "å°è¯•次数过多,请ç¨åŽå†è¯•", "cantReachServer": "无法连接æœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥è¿žæŽ¥ä¿¡æ¯æ˜¯å¦æ­£ç¡®", - "sslError": "SSL 错误。转到 设置 > 高级设置 å¹¶å¯ç”¨ 忽略 SSL 验è¯", + "sslError": "SSL 错误。转到 设置 > 高级设置 å¹¶å¯ç”¨ 䏿£€æŸ¥ SSL è¯ä¹¦", "unknownError": "未知错误", "connectionNotCreated": "连接无法创建", "connecting": "正在连接...", From 52d0afed395e0f05d1ff3acfb52c670a7247ded4 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Sun, 6 Aug 2023 20:16:00 +0800 Subject: [PATCH 273/676] Update app_zh_CN.arb --- lib/l10n/app_zh_CN.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb index 5c0a77c..2bc12e6 100644 --- a/lib/l10n/app_zh_CN.arb +++ b/lib/l10n/app_zh_CN.arb @@ -652,6 +652,6 @@ "malwarePhising": "æ¶æ„/钓鱼网站", "queries": "查询", "adultSites": "æˆäººç½‘ç«™", - "quickFilters": "快速过滤器", + "quickFilters": "状æ€è¿‡æ»¤å™¨", "searchDomainInternet": "在互è”网上æœç´¢è¯¥åŸŸå" } From 6794c4e4dc89ded1f0e7fc97025bc99ab7458013 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Mon, 7 Aug 2023 00:42:04 +0800 Subject: [PATCH 274/676] Update app_zh_CN.arb --- lib/l10n/app_zh_CN.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb index 2bc12e6..4cb5df5 100644 --- a/lib/l10n/app_zh_CN.arb +++ b/lib/l10n/app_zh_CN.arb @@ -214,7 +214,7 @@ "blacklists": "黑åå•", "rules": "规则", "customRules": "自定义规则", - "enabledRules": "æ¡è§„则已应用", + "enabledRules": "æ¡è§„则已应用", "enabled": "å·²å¯ç”¨", "disabled": "å·²ç¦ç”¨", "rule": "规则", From b19f2417ac6d8fa86d59ef652d0cf74f9d6908af Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Mon, 7 Aug 2023 07:25:42 +0800 Subject: [PATCH 275/676] Rename app_zh_CN.arb to app_zh.arb --- lib/l10n/{app_zh_CN.arb => app_zh.arb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/l10n/{app_zh_CN.arb => app_zh.arb} (100%) diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh.arb similarity index 100% rename from lib/l10n/app_zh_CN.arb rename to lib/l10n/app_zh.arb From a2505e9cf87fb69b512b1824805fef16dff3af66 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Mon, 7 Aug 2023 07:25:55 +0800 Subject: [PATCH 276/676] Update main.dart --- lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index e82684a..20b94bb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -227,7 +227,7 @@ class _MainState extends State
{ supportedLocales: const [ Locale('en', ''), Locale('es', ''), - Locale('zh', 'CN') + Locale('zh', '') ], scaffoldMessengerKey: scaffoldMessengerKey, builder: (context, child) { From 2effb7e764958e8be3fa30d4418cc86058c62717 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Mon, 7 Aug 2023 08:40:24 +0800 Subject: [PATCH 277/676] Update main.dart --- lib/main.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 20b94bb..6d2f1a3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -227,7 +227,8 @@ class _MainState extends State
{ supportedLocales: const [ Locale('en', ''), Locale('es', ''), - Locale('zh', '') + Locale('zh', ''), + Locale('zh', 'CN') ], scaffoldMessengerKey: scaffoldMessengerKey, builder: (context, child) { From 8111a3ce3fc05cfc10b58990b0d7dda87e711f6a Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Mon, 7 Aug 2023 08:41:32 +0800 Subject: [PATCH 278/676] Create app_zh_CN.arb --- lib/l10n/app_zh_CN.arb | 657 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 657 insertions(+) create mode 100644 lib/l10n/app_zh_CN.arb diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb new file mode 100644 index 0000000..4cb5df5 --- /dev/null +++ b/lib/l10n/app_zh_CN.arb @@ -0,0 +1,657 @@ +{ + "home": "主页", + "settings": "设置", + "connect": "连接", + "servers": "æœåС噍", + "createConnection": "创建连接", + "name": "åç§°", + "ipDomain": "IPåœ°å€æˆ–域å", + "path": "路径", + "port": "端å£", + "username": "用户å", + "password": "密ç ", + "defaultServer": "默认æœåС噍", + "general": "常规", + "connection": "连接", + "authentication": "身份验è¯", + "other": "其它", + "invalidPort": "ç«¯å£æ— æ•ˆ", + "invalidPath": "路径无效", + "invalidIpDomain": "IP åœ°å€æˆ–åŸŸåæ— æ•ˆ", + "ipDomainNotEmpty": "IP åœ°å€æˆ–域åä¸èƒ½ä¸ºç©º", + "nameNotEmpty": "åç§°ä¸èƒ½ä¸ºç©º", + "invalidUsernamePassword": "ç”¨æˆ·åæˆ–密ç é”™è¯¯", + "tooManyAttempts": "å°è¯•次数过多,请ç¨åŽå†è¯•", + "cantReachServer": "无法连接æœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥è¿žæŽ¥ä¿¡æ¯æ˜¯å¦æ­£ç¡®", + "sslError": "SSL 错误。转到 设置 > 高级设置 å¹¶å¯ç”¨ 䏿£€æŸ¥ SSL è¯ä¹¦", + "unknownError": "未知错误", + "connectionNotCreated": "连接无法创建", + "connecting": "正在连接...", + "connected": "已连接", + "selectedDisconnected": "已选择但未连接", + "connectionDefaultSuccessfully": "æˆåŠŸå°†è¿žæŽ¥è®¾ä¸ºé»˜è®¤", + "connectionDefaultFailed": "无法将连接设为默认", + "noSavedConnections": "连接为空", + "cannotConnect": "无法连接到æœåС噍", + "connectionRemoved": "连接删除æˆåŠŸ", + "connectionCannotBeRemoved": "无法删除连接", + "remove": "移除", + "removeWarning": "您确定è¦åˆ é™¤ä¸Žæ­¤ AdGuard Home æœåŠ¡å™¨çš„è¿žæŽ¥å—?", + "cancel": "å–æ¶ˆ", + "defaultConnection": "默认连接", + "setDefault": "设为默认", + "edit": "编辑", + "delete": "删除", + "save": "ä¿å­˜", + "serverStatus": "æœåŠ¡å™¨çŠ¶æ€", + "connectionNotUpdated": "没有更新连接é…ç½®", + "ruleFilteringWidget": "规则过滤", + "safeBrowsingWidget": "安全æµè§ˆ", + "parentalFilteringWidget": "家长过滤", + "safeSearchWidget": "安全æœç´¢", + "ruleFiltering": "规则过滤", + "safeBrowsing": "安全æµè§ˆ", + "parentalFiltering": "家长过滤", + "safeSearch": "安全æœç´¢", + "serverStatusNotRefreshed": "无法更新æœåŠ¡å™¨çŠ¶æ€", + "loadingStatus": "加载æœåŠ¡å™¨çŠ¶æ€...", + "errorLoadServerStatus": "无法加载æœåŠ¡å™¨çŠ¶æ€", + "topQueriedDomains": "è¯·æ±‚åŸŸåæŽ’行", + "viewMore": "查看更多", + "topClients": "客户端排行", + "topBlockedDomains": "è¢«æ‹¦æˆªåŸŸåæŽ’行", + "appSettings": "App 设置", + "theme": "主题", + "light": "明亮", + "dark": "暗夜", + "systemDefined": "è·Ÿéšç³»ç»Ÿ", + "close": "关闭", + "connectedTo": "连接到 :", + "selectedServer": "选择的æœåС噍 :", + "noServerSelected": "未选择æœåС噍", + "manageServer": "ç®¡ç†æœåС噍", + "allProtections": "æ‰€æœ‰ä¿æŠ¤", + "userNotEmpty": "用户åä¸èƒ½ä¸ºç©º", + "passwordNotEmpty": "密ç ä¸èƒ½ä¸ºç©º", + "examplePath": "例如: /adguard", + "helperPath": "如果使用åå‘代ç†ï¼Œå¯å¡«å†™è·¯å¾„", + "aboutApp": "关于本应用", + "appVersion": "App 版本", + "createdBy": "作者", + "clients": "客户端", + "allowed": "å…许", + "blocked": "拦截", + "noClientsList": "列表中没有客户端", + "activeClients": "活跃", + "removeClient": "删除客户端", + "removeClientMessage": "您确定è¦ä»Žåˆ—è¡¨ä¸­åˆ é™¤æ­¤å®¢æˆ·ç«¯å— ?", + "confirm": "确定", + "removingClient": "正在删除客户端...", + "clientNotRemoved": "无法从列表中删除客户端", + "addClient": "添加客户端", + "list": "列表", + "ipAddress": "IP 地å€", + "ipNotValid": "IP åœ°å€æ— æ•ˆ", + "clientAddedSuccessfully": "æˆåŠŸå°†å®¢æˆ·ç«¯æ·»åŠ åˆ°åˆ—è¡¨", + "addingClient": "正在添加客户端...", + "clientNotAdded": "无法将客户端添加到列表", + "clientAnotherList": "å…¶å®ƒåˆ—è¡¨é‡Œå·²ç»æœ‰è¿™ä¸ªå®¢æˆ·ç«¯äº†", + "noSavedLogs": "没有日志", + "logs": "日志", + "copyLogsClipboard": "将日志å¤åˆ¶åˆ°å‰ªè´´æ¿", + "logsCopiedClipboard": "日志已å¤åˆ¶åˆ°å‰ªè´´æ¿", + "advancedSettings": "高级设置", + "dontCheckCertificate": "䏿£€æŸ¥ SSL è¯ä¹¦", + "dontCheckCertificateDescription": "忽略æœåŠ¡å™¨çš„ SSL è¯ä¹¦éªŒè¯", + "advancedSetupDescription": "高级选项", + "settingsUpdatedSuccessfully": "设置更新æˆåŠŸ", + "cannotUpdateSettings": "无法更新设置", + "restartAppTakeEffect": "釿–°å¯åŠ¨åº”ç”¨ç¨‹åº", + "loadingLogs": "正在加载日志...", + "logsNotLoaded": "无法加载日志列表", + "processed": "已处ç†\n无拦截", + "processedRow": "已处ç†ï¼ˆæ— æ‹¦æˆªï¼‰", + "blockedBlacklist": "已拦截\n黑åå•", + "blockedBlacklistRow": "已拦截(黑åå•)", + "blockedSafeBrowsing": "已拦截\n安全æµè§ˆ", + "blockedSafeBrowsingRow": "已拦截(安全æµè§ˆï¼‰", + "blockedParental": "已拦截\n家长过滤", + "blockedParentalRow": "已拦截(家长过滤)", + "blockedInvalid": "已拦截\n无效", + "blockedInvalidRow": "已拦截(无效)", + "blockedSafeSearch": "已拦截\n安全æœç´¢", + "blockedSafeSearchRow": "已拦截(安全æœç´¢ï¼‰", + "blockedService": "已拦截\n已拦截的æœåŠ¡", + "blockedServiceRow": "已拦截(已拦截的æœåŠ¡ï¼‰", + "processedWhitelist": "已处ç†\n白åå•", + "processedWhitelistRow": "已处ç†ï¼ˆç™½åå•)", + "processedError": "已处ç†\n错误", + "processedErrorRow": "已处ç†ï¼ˆé”™è¯¯ï¼‰", + "rewrite": "é‡å†™", + "status": "状æ€", + "result": "结果", + "time": "æ—¶é—´", + "blocklist": "黑åå•列表", + "request": "请求", + "domain": "域å", + "type": "类型", + "clas": "类别", + "response": "å“应", + "dnsServer": "DNS æœåС噍", + "elapsedTime": "å¤„ç†æ—¶é—´", + "responseCode": "å“应代ç ", + "client": "客户端", + "deviceIp": "IP 地å€", + "deviceName": "åç§°", + "logDetails": "日志详情", + "blockingRule": "拦截规则", + "blockDomain": "拦截域å", + "couldntGetFilteringStatus": "无法获å–过滤状æ€", + "unblockDomain": "放行域å", + "userFilteringRulesNotUpdated": "无法更新用户过滤规则", + "userFilteringRulesUpdated": "æˆåŠŸæ›´æ–°ç”¨æˆ·è¿‡æ»¤è§„åˆ™", + "savingUserFilters": "正在ä¿å­˜ç”¨æˆ·è¿‡æ»¤å™¨...", + "filters": "过滤器", + "logsOlderThan": "日志早于", + "responseStatus": "å“应状æ€", + "selectTime": "选择时间", + "notSelected": "未选择", + "resetFilters": "é‡ç½®è¿‡æ»¤å™¨", + "noLogsDisplay": "æ— æ—¥å¿—å¯æ˜¾ç¤º", + "noLogsThatOld": "选择的时间段å¯èƒ½æ²¡æœ‰æ—¥å¿—。å°è¯•选择近期时间。", + "apply": "应用", + "selectAll": "全选", + "unselectAll": "å–æ¶ˆå…¨é€‰", + "all": "全部", + "filtered": "已筛选", + "checkAppLogs": "检查应用日志", + "refresh": "刷新", + "search": "æœç´¢", + "dnsQueries": "DNS 查询", + "average": "å¹³å‡å€¼", + "blockedFilters": "被过滤器拦截", + "malwarePhisingBlocked": "è¢«æ‹¦æˆªçš„æ¶æ„/钓鱼网站", + "blockedAdultWebsites": "被拦截的æˆäººç½‘ç«™", + "generalSettings": "常规设置", + "generalSettingsDescription": "å„ç§ä¸åŒçš„设置", + "hideZeroValues": "éšè—零值", + "hideZeroValuesDescription": "在主å±å¹•上éšè—零值å—", + "webAdminPanel": "Web 管ç†é¢æ¿", + "visitGooglePlay": "访问 Google Play 页é¢", + "gitHub": "å¼€æºä»£ç å¯åœ¨ GitHub 上获得", + "blockClient": "拦截客户端", + "selectTags": "选择标签", + "noTagsSelected": "未选择标签", + "tags": "标签", + "identifiers": "标识符", + "identifier": "标识符", + "identifierHelper": "IP 地å€ã€CIDRã€MAC åœ°å€æˆ–客户端 ID", + "noIdentifiers": "未添加标识符", + "useGlobalSettings": "使用全局设置", + "enableFiltering": "å¯ç”¨è¿‡æ»¤", + "enableSafeBrowsing": "å¯ç”¨å®‰å…¨æµè§ˆ", + "enableParentalControl": "å¯ç”¨å®¶é•¿æŽ§åˆ¶", + "enableSafeSearch": "å¯ç”¨å®‰å…¨æœç´¢", + "blockedServices": "被拦截的æœåŠ¡", + "selectBlockedServices": "é€‰æ‹©è¦æ‹¦æˆªçš„æœåŠ¡", + "noBlockedServicesSelected": "未选择被拦截的æœåŠ¡", + "services": "æœåŠ¡", + "servicesBlocked": "被拦截的æœåŠ¡", + "tagsSelected": "已选择标签", + "upstreamServers": "上游æœåС噍", + "serverAddress": "æœåŠ¡å™¨åœ°å€", + "noUpstreamServers": "无上游æœåС噍", + "willBeUsedGeneralServers": "将使用常规上游æœåС噍", + "added": "已添加", + "clientUpdatedSuccessfully": "客户端更新æˆåŠŸ", + "clientNotUpdated": "无法更新客户端", + "clientDeletedSuccessfully": "客户端删除æˆåŠŸ", + "clientNotDeleted": "无法删除客户端", + "options": "选项", + "loadingFilters": "正在加载过滤器...", + "filtersNotLoaded": "无法加载过滤器", + "whitelists": "白åå•", + "blacklists": "黑åå•", + "rules": "规则", + "customRules": "自定义规则", + "enabledRules": "æ¡è§„则已应用", + "enabled": "å·²å¯ç”¨", + "disabled": "å·²ç¦ç”¨", + "rule": "规则", + "addCustomRule": "添加自定义规则", + "removeCustomRule": "删除自定义规则", + "removeCustomRuleMessage": "您确定è¦åˆ é™¤æ­¤è‡ªå®šä¹‰è§„则å—?", + "updatingRules": "正在更新自定义规则...", + "ruleRemovedSuccessfully": "规则删除æˆåŠŸ", + "ruleNotRemoved": "无法删除规则", + "ruleAddedSuccessfully": "规则添加æˆåŠŸ", + "ruleNotAdded": "无法添加规则", + "noCustomFilters": "无自定义过滤器", + "noBlockedClients": "无已拦截的客户端", + "noBlackLists": "无黑åå•", + "noWhiteLists": "无白åå•", + "addWhitelist": "添加白åå•", + "addBlacklist": "添加黑åå•", + "urlNotValid": "URL 无效", + "urlAbsolutePath": "URL 或ç»å¯¹è·¯å¾„", + "addingList": "正在添加订阅规则...", + "listAdded": "订阅规则添加æˆåŠŸ 。已添加项目:", + "listAlreadyAdded": "订阅规则已被添加", + "listUrlInvalid": "订阅规则 URL 无效", + "listNotAdded": "无法添加订阅规则", + "listDetails": "订阅规则详细信æ¯", + "listType": "订阅规则类型", + "whitelist": "白åå•", + "blacklist": "黑åå•", + "latestUpdate": "最近更新", + "disable": "ç¦ç”¨", + "enable": "å¯ç”¨", + "currentStatus": "当å‰çжæ€", + "listDataUpdated": "订阅规则更新æˆåŠŸ", + "listDataNotUpdated": "无法更新订阅规则", + "updatingListData": "正在更新订阅规则...", + "editWhitelist": "编辑白åå•", + "editBlacklist": "编辑黑åå•", + "deletingList": "正在删除订阅规则...", + "listDeleted": "订阅规则删除æˆåŠŸ", + "listNotDeleted": "无法删除订阅规则", + "deleteList": "删除订阅规则", + "deleteListMessage": "您确定è¦åˆ é™¤æ­¤è®¢é˜…规则å—?此æ“作无法撤消", + "serverSettings": "æœåŠ¡å™¨è®¾ç½®", + "serverInformation": "æœåŠ¡å™¨ä¿¡æ¯", + "serverInformationDescription": "æœåŠ¡å™¨ä¿¡æ¯å’Œçжæ€", + "loadingServerInfo": "正在加载æœåŠ¡å™¨ä¿¡æ¯...", + "serverInfoNotLoaded": "无法加载æœåŠ¡å™¨ä¿¡æ¯", + "dnsAddresses": "DNS 地å€", + "seeDnsAddresses": "查看 DNS 地å€", + "dnsPort": "DNS 端å£", + "httpPort": "HTTP 端å£", + "protectionEnabled": "å·²å¯ç”¨ä¿æŠ¤", + "dhcpAvailable": "å¯ç”¨ DHCP", + "serverRunning": "æœåС噍è¿è¡Œä¸­", + "serverVersion": "æœåŠ¡å™¨ç‰ˆæœ¬", + "serverLanguage": "æœåŠ¡å™¨è¯­è¨€", + "yes": "是", + "no": "å¦", + "allowedClients": "å·²å…许的客户端", + "disallowedClients": "å·²ç¦æ­¢çš„客户端", + "disallowedDomains": "å·²ç¦æ­¢çš„域å", + "accessSettings": "访问设置", + "accessSettingsDescription": "为æœåС噍é…置访问规则", + "loadingClients": "正在加载客户端...", + "clientsNotLoaded": "无法加载客户端", + "noAllowedClients": "没有已å…许的客户端", + "allowedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†ä»…æŽ¥å—æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求", + "blockedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†æ‹’ç»æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求。如果已å…许客户端中有æ¡ç›®ï¼Œåˆ™ä¼šå¿½ç•¥æ­¤å­—段", + "disallowedDomainsDescription": "AdGuard Home 会丢弃与这些域å匹é…çš„ DNS 查询,这些查询甚至ä¸ä¼šå‡ºçŽ°åœ¨æŸ¥è¯¢æ—¥å¿—ä¸­", + "addClientFieldDescription": "CIDRã€IP åœ°å€æˆ–客户端 ID", + "clientIdentifier": "客户端标识符", + "allowClient": "å…许客户端", + "disallowClient": "ç¦æ­¢å®¢æˆ·ç«¯", + "noDisallowedDomains": "æ— å·²ç¦æ­¢çš„域å", + "domainNotAdded": "无法添加域å", + "statusSelected": "已选择状æ€", + "updateLists": "更新订阅规则", + "checkHostFiltered": "检查域å", + "updatingLists": "正在更新订阅规则...", + "listsUpdated": "已更新订阅规则", + "listsNotUpdated": "无法更新订阅规则", + "listsNotLoaded": "无法加载订阅规则", + "domainNotValid": "åŸŸåæ— æ•ˆ", + "check": "检查", + "checkingHost": "正在检查域å...", + "errorCheckingHost": "无法检查域å", + "block": "拦截", + "unblock": "放行", + "custom": "自定义", + "addImportant": "添加 $important", + "howCreateRules": "如何创建自定义规则", + "examples": "示例", + "example1": "拦截访问 example.org åŠå…¶æ‰€æœ‰å­åŸŸ", + "example2": "解除对 example.org åŠå…¶æ‰€æœ‰å­åŸŸçš„访问é™åˆ¶", + "example3": "添加注释", + "example4": "拦截与指定正则表达å¼åŒ¹é…的域", + "moreInformation": "更多信æ¯", + "addingRule": "正在添加规则...", + "deletingRule": "正在删除规则...", + "enablingList": "正在å¯ç”¨è®¢é˜…规则...", + "disablingList": "正在ç¦ç”¨è®¢é˜…规则...", + "disableFiltering": "ç¦ç”¨è¿‡æ»¤", + "enablingFiltering": "正在å¯ç”¨è¿‡æ»¤...", + "disablingFiltering": "正在ç¦ç”¨è¿‡æ»¤...", + "filteringStatusUpdated": "è¿‡æ»¤çŠ¶æ€æ›´æ–°æˆåŠŸ", + "filteringStatusNotUpdated": "无法更新过滤状æ€", + "updateFrequency": "更新频率", + "never": "从ä¸", + "hour1": "1 å°æ—¶", + "hours12": "12 å°æ—¶", + "hours24": "24 å°æ—¶", + "days3": "3 天", + "days7": "7 天", + "changingUpdateFrequency": "正在更改...", + "updateFrequencyChanged": "更新频率已æˆåŠŸæ›´æ”¹", + "updateFrequencyNotChanged": "无法更改更新频率", + "updating": "正在更新值...", + "blockedServicesUpdated": "被拦截的æœåŠ¡æ›´æ–°æˆåŠŸ", + "blockedServicesNotUpdated": "无法更新被拦截的æœåŠ¡", + "insertDomain": "è¾“å…¥è¦æ£€æŸ¥çš„域å以查看其状æ€", + "dhcpSettings": "DHCP 设置", + "dhcpSettingsDescription": "é…ç½® DHCP æœåС噍", + "dhcpSettingsNotLoaded": "无法加载 DHCP 设置", + "loadingDhcp": "正在加载 DHCP 设置...", + "enableDhcpServer": "å¯ç”¨ DHCP æœåС噍", + "selectInterface": "选择接å£", + "hardwareAddress": "硬件地å€", + "gatewayIp": "网关 IP", + "ipv4addresses": "IPv4 地å€", + "ipv6addresses": "IPv6 地å€", + "neededSelectInterface": "您需è¦é€‰æ‹©ä¸€ä¸ªæŽ¥å£æ¥é…ç½® DHCP æœåС噍", + "ipv4settings": "IPv4 设置", + "startOfRange": "起始范围", + "endOfRange": "结æŸèŒƒå›´", + "ipv6settings": "IPv6 设置", + "subnetMask": "å­ç½‘掩ç ", + "subnetMaskNotValid": "å­ç½‘æŽ©ç æ— æ•ˆ", + "gateway": "网关", + "gatewayNotValid": "网关无效", + "leaseTime": "租期", + "seconds": "{time} ç§’", + "leaseTimeNotValid": "租期无效", + "restoreConfiguration": "é‡ç½®é…ç½®", + "restoreConfigurationMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰é…置。此æ“作无法撤消", + "changeInterface": "更改接å£", + "savingSettings": "正在ä¿å­˜è®¾ç½®...", + "settingsSaved": "设置ä¿å­˜æˆåŠŸ", + "settingsNotSaved": "无法ä¿å­˜è®¾ç½®", + "restoringConfig": "正在还原é…ç½®...", + "configRestored": "é…置还原æˆåŠŸ", + "configNotRestored": "无法还原é…ç½®", + "dhcpStatic": "DHCP 陿€ç§Ÿç”¨", + "noDhcpStaticLeases": "未找到 DHCP 陿€ç§Ÿç”¨", + "deleting": "正在删除...", + "staticLeaseDeleted": "DHCP 陿€ç§Ÿç”¨åˆ é™¤æˆåŠŸ", + "staticLeaseNotDeleted": "无法删除 DHCP 陿€ç§Ÿç”¨", + "deleteStaticLease": "åˆ é™¤é™æ€ç§Ÿç”¨", + "deleteStaticLeaseDescription": "DHCP 陿€ç§Ÿç”¨å°†è¢«åˆ é™¤ã€‚æ­¤æ“作无法撤消", + "addStaticLease": "æ·»åŠ é™æ€ç§Ÿç”¨", + "macAddress": "MAC 地å€", + "macAddressNotValid": "MAC åœ°å€æ— æ•ˆ", + "hostName": "主机å", + "hostNameError": "主机åä¸èƒ½ä¸ºç©º", + "creating": "正在创建...", + "staticLeaseCreated": "DHCP 陿€ç§Ÿç”¨åˆ›å»ºæˆåŠŸ", + "staticLeaseNotCreated": "无法创建 DHCP 陿€ç§Ÿç”¨", + "staticLeaseExists": "DHCP 陿€ç§Ÿç”¨å·²å­˜åœ¨", + "serverNotConfigured": "未é…ç½®æœåС噍", + "restoreLeases": "é‡ç½®ç§Ÿç”¨", + "restoreLeasesMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰çŽ°æœ‰ç§Ÿç”¨ã€‚æ­¤æ“作无法撤消", + "restoringLeases": "正在é‡ç½®ç§Ÿç”¨...", + "leasesRestored": "租用é‡ç½®æˆåŠŸ", + "leasesNotRestored": "无法é‡ç½®ç§Ÿç”¨", + "dhcpLeases": "DHCP 租用", + "noLeases": "æ— å¯ç”¨çš„ DHCP 租用", + "dnsRewrites": "DNS é‡å†™", + "dnsRewritesDescription": "é…置自定义 DNS 规则", + "loadingRewriteRules": "正在加载é‡å†™è§„则...", + "rewriteRulesNotLoaded": "无法加载 DNS é‡å†™è§„则", + "noRewriteRules": "æ—  DNS é‡å†™è§„则", + "answer": "å“应", + "deleteDnsRewrite": "删除 DNS é‡å†™", + "deleteDnsRewriteMessage": "您确定è¦åˆ é™¤æ­¤ DNS é‡å†™å—?此æ“作无法撤消", + "dnsRewriteRuleDeleted": "DNS é‡å†™è§„则删除æˆåŠŸ", + "dnsRewriteRuleNotDeleted": "无法删除 DNS é‡å†™è§„则", + "addDnsRewrite": "添加 DNS é‡å†™", + "addingRewrite": "正在添加é‡å†™...", + "dnsRewriteRuleAdded": "DNS é‡å†™è§„则添加æˆåŠŸ", + "dnsRewriteRuleNotAdded": "无法添加 DNS é‡å†™è§„则", + "logsSettings": "日志设置", + "enableLog": "å¯ç”¨æ—¥å¿—", + "clearLogs": "清除日志", + "anonymizeClientIp": "匿å化客户端 IP", + "hours6": "6 å°æ—¶", + "days30": "30 天", + "days90": "90 天", + "retentionTime": "ä¿ç•™æ—¶é—´", + "selectOneItem": "选择一项", + "logSettingsNotLoaded": "无法加载日志设置", + "updatingSettings": "正在更新设置...", + "logsConfigUpdated": "日志设置更新æˆåŠŸ", + "logsConfigNotUpdated": "无法更新日志设置", + "deletingLogs": "正在清除日志...", + "logsCleared": "日志清除æˆåŠŸ", + "logsNotCleared": "无法清除日志", + "runningHomeAssistant": "在 Home Assistant 上è¿è¡Œ", + "serverError": "æœåŠ¡å™¨é”™è¯¯", + "noItems": "è¿™é‡Œæ²¡æœ‰è¦æ˜¾ç¤ºçš„项目", + "dnsSettings": "DNS 设置", + "dnsSettingsDescription": "é…置与 DNS æœåŠ¡å™¨çš„è¿žæŽ¥", + "upstreamDns": "上游 DNS æœåС噍", + "bootstrapDns": "引导 DNS æœåС噍", + "noUpstreamDns": "未添加上游 DNS æœåŠ¡å™¨ã€‚", + "dnsMode": "DNS 模å¼", + "noDnsMode": "未选择 DNS 模å¼", + "loadBalancing": "è´Ÿè½½å‡è¡¡", + "parallelRequests": "并行请求", + "fastestIpAddress": "最快的 IP 地å€", + "loadBalancingDescription": "æ¯æ¬¡æŸ¥è¯¢ä¸€ä¸ªä¸Šæ¸¸æœåŠ¡å™¨ã€‚AdGuard Home 使用其加æƒéšæœºç®—æ³•é€‰æ‹©æœåŠ¡å™¨ï¼Œä»¥ä¾¿æ›´é¢‘ç¹åœ°ä½¿ç”¨æœ€å¿«çš„æœåŠ¡å™¨", + "parallelRequestsDescription": "ä½¿ç”¨å¹¶è¡ŒæŸ¥è¯¢åŒæ—¶åŠ é€Ÿè§£æžï¼ŒåŒæ—¶æŸ¥è¯¢æ‰€æœ‰ä¸Šæ¸¸æœåС噍", + "fastestIpAddressDescription": "查询所有 DNS æœåŠ¡å™¨å¹¶è¿”å›žæ‰€æœ‰å“应中最快的 IP 地å€ã€‚è¿™ä¼šå‡æ…¢ DNS 查询,因为 AdGuard Home 必须等待所有 DNS æœåŠ¡å™¨çš„å“应,但å¯ä»¥æ”¹å–„整体连接性", + "noBootstrapDns": "未添加引导 DNS æœåŠ¡å™¨ã€‚", + "bootstrapDnsServersInfo": "引导 DNS æœåŠ¡å™¨ç”¨äºŽè§£æžæ‚¨æŒ‡å®šçš„上游 DoH/DoT è§£æžå™¨çš„ IP 地å€ã€‚", + "privateReverseDnsServers": "ç§æœ‰åå‘ DNS æœåС噍", + "privateReverseDnsServersDescription": "AdGuard Home 用于本地 PTR 查询的 DNS æœåŠ¡å™¨ã€‚è¿™äº›æœåŠ¡å™¨ç”¨äºŽè§£æžç§æœ‰ IP 范围内的地å€çš„ PTR 请求,例如 \"192.168.12.34\"。如果未设置,AdGuard Home 将使用æ“作系统的默认 DNS è§£æžå™¨åœ°å€ï¼Œä½†ä¸åŒ…括 AdGuard Home 本身的地å€ã€‚", + "reverseDnsDefault": "默认情况下,AdGuard Home 使用以下默认åå‘ DNS è§£æžå™¨", + "addItem": "添加项目", + "noServerAddressesAdded": "未添加æœåŠ¡å™¨åœ°å€", + "usePrivateReverseDnsResolvers": "ä½¿ç”¨ç§æœ‰åå‘ DNS è§£æžå™¨", + "usePrivateReverseDnsResolversDescription": "使用这些上游æœåŠ¡å™¨æ‰§è¡Œæœ¬åœ°æä¾›çš„地å€çš„åå‘ DNS 查询。如果ç¦ç”¨ï¼ŒAdGuard Home 会对所有此类 PTR 请求(除了æ¥è‡ª DHCPã€/etc/hosts 等已知客户端)å“应 NXDOMAIN", + "enableReverseResolving": "å¯ç”¨å®¢æˆ·ç«¯ IP 地å€çš„åå‘è§£æž", + "enableReverseResolvingDescription": "通过å‘相应的解æžå™¨å‘é€ PTR 查询,将客户端 IP 地å€è¿›è¡Œåå‘è§£æžä¸ºä¸»æœºåï¼ˆå¯¹äºŽæœ¬åœ°å®¢æˆ·ç«¯ä½¿ç”¨ç§æœ‰ DNS æœåŠ¡å™¨ï¼Œå¯¹äºŽå…·æœ‰å…¬å…± IP 地å€çš„客户端使用上游æœåŠ¡å™¨ï¼‰", + "dnsServerSettings": "AdGuard Home DNS æœåŠ¡å™¨è®¾ç½®", + "limitRequestsSecond": "æ¯ç§’速率é™åˆ¶", + "valueNotNumber": "值䏿˜¯æ•°å­—", + "enableEdns": "å¯ç”¨ EDNS 客户å­ç½‘", + "enableEdnsDescription": "在上游请求中添加 EDNS 客户å­ç½‘选项(ECS),并在查询日志中记录客户端å‘é€çš„值", + "enableDnssec": "å¯ç”¨ DNSSEC", + "enableDnssecDescription": "在传出的 DNS 查询中设置 DNSSEC 标志并检查结果(需è¦å¯ç”¨ DNSSEC 的解æžå™¨ï¼‰", + "disableResolvingIpv6": "ç¦ç”¨ IPv6 地å€è§£æž", + "disableResolvingIpv6Description": "丢弃所有用于 IPv6 地å€ï¼ˆAAAA 记录)的 DNS 查询", + "blockingMode": "拦截模å¼", + "defaultMode": "默认", + "defaultDescription": "当按照 Adblock æ ·å¼è§„则被拦截时,返回零 IP 地å€ï¼ˆ0.0.0.0 对应 Aï¼›:: 对应 AAAA);当按照 /etc/hosts æ ·å¼è§„则被拦截时,返回规则中指定的 IP 地å€", + "refusedDescription": "返回 REFUSED 代ç ", + "nxdomainDescription": "返回 NXDOMAIN 代ç ", + "nullIp": "空 IP", + "nullIpDescription": "返回空 IP 地å€ï¼ˆ0.0.0.0 对应 Aï¼›:: 对应 AAAA)", + "customIp": "自定义 IP", + "customIpDescription": "返回手动设置的 IP 地å€", + "dnsCacheConfig": "DNS 缓存é…ç½®", + "cacheSize": "缓存大å°", + "inBytes": "字节", + "overrideMinimumTtl": "è¦†ç›–æœ€å° TTL", + "overrideMinimumTtlDescription": "在缓存 DNS å“应时,从上游æœåŠ¡å™¨æŽ¥æ”¶åˆ°çš„æœ€çŸ­çš„å­˜æ´»æ—¶é—´å€¼ï¼ˆç§’ï¼‰", + "overrideMaximumTtl": "覆盖最大 TTL", + "overrideMaximumTtlDescription": "为 DNS 缓存æ¡ç›®è®¾ç½®æœ€å¤§å­˜æ´»æ—¶é—´å€¼ï¼ˆç§’)", + "optimisticCaching": "ä¹è§‚缓存", + "optimisticCachingDescription": "å³ä½¿æ¡ç›®å·²è¿‡æœŸï¼ŒAdGuard Home 也将从缓存中å“应,并å°è¯•刷新它们", + "loadingDnsConfig": "正在加载 DNS é…ç½®...", + "dnsConfigNotLoaded": "无法加载 DNS é…ç½®", + "blockingIpv4": "拦截 IPv4", + "blockingIpv4Description": "æ‹¦æˆªåŒ…å« A 记录的请求时返回的 IP 地å€", + "blockingIpv6": "拦截 IPv6", + "blockingIpv6Description": "æ‹¦æˆªåŒ…å« AAAA 记录的请求时返回的 IP 地å€", + "invalidIp": "无效的 IP 地å€", + "dnsConfigSaved": "DNS æœåС噍é…ç½®ä¿å­˜æˆåŠŸ", + "dnsConfigNotSaved": "DNS æœåС噍é…置无法ä¿å­˜", + "savingConfig": "正在ä¿å­˜é…ç½®...", + "someValueNotValid": "æŸäº›å€¼æ— æ•ˆ", + "upstreamDnsDescription": "é…置上游æœåŠ¡å™¨å’Œ DNS 模å¼", + "bootstrapDnsDescription": "é…置引导 DNS æœåС噍", + "privateReverseDnsDescription": "é…置自定义 DNS è§£æžå™¨å¹¶å¯ç”¨ç§æœ‰åå‘ DNS è§£æž", + "dnsServerSettingsDescription": "é…置速率é™åˆ¶ã€æ‹¦æˆªæ¨¡å¼ç­‰", + "dnsCacheConfigDescription": "é…ç½®æœåŠ¡å™¨å¦‚ä½•ç®¡ç† DNS 缓存", + "comment": "注释", + "address": "地å€", + "commentsDescription": "注释始终以 # 开头。您无需添加它,系统将自动添加", + "encryptionSettings": "加密设置", + "encryptionSettingsDescription": "加密(HTTPS/QUIC/TLS)支æŒ", + "loadingEncryptionSettings": "正在加载加密设置...", + "encryptionSettingsNotLoaded": "无法加载加密设置", + "enableEncryption": "å¯ç”¨åР坆", + "enableEncryptionTypes": "HTTPSã€DNS-over-HTTPS å’Œ DNS-over-TLS", + "enableEncryptionDescription": "如果å¯ç”¨åŠ å¯†ï¼ŒAdGuard Home 管ç†ç•Œé¢å°†é€šè¿‡ HTTPS è¿è¡Œï¼Œå¹¶ä¸” DNS æœåŠ¡å™¨å°†ç›‘å¬ DNS-over-HTTPS å’Œ DNS-over-TLS 请求", + "serverConfiguration": "æœåС噍é…ç½®", + "domainName": "域å", + "domainNameDescription": "如果设置,AdGuard Home 将检测 ClientIDã€å“应 DDR 查询并执行其他连接验è¯ã€‚如果未设置,这些功能将被ç¦ç”¨ã€‚必须与è¯ä¹¦ä¸­çš„ DNS å称之一匹é…", + "redirectHttps": "自动é‡å®šå‘到 HTTPS", + "httpsPort": "HTTPS 端å£", + "tlsPort": "DNS-over-TLS 端å£", + "dnsOverQuicPort": "DNS-over-QUIC 端å£", + "certificates": "è¯ä¹¦", + "certificatesDescription": "为了使用加密,您需è¦ä¸ºæ‚¨çš„域æä¾›æœ‰æ•ˆçš„ SSL è¯ä¹¦é“¾ã€‚您å¯ä»¥åœ¨ letsencrypt.org 上获得å…è´¹è¯ä¹¦ï¼Œä¹Ÿå¯ä»¥ä»Žå—信任的è¯ä¹¦é¢å‘机构购买", + "certificateFilePath": "设置è¯ä¹¦æ–‡ä»¶è·¯å¾„", + "pasteCertificateContent": "粘贴è¯ä¹¦å†…容", + "certificatePath": "è¯ä¹¦è·¯å¾„", + "certificateContent": "è¯ä¹¦å†…容", + "privateKey": "ç§é’¥", + "privateKeyFile": "设置ç§é’¥æ–‡ä»¶", + "pastePrivateKey": "粘贴ç§é’¥å†…容", + "usePreviousKey": "使用先å‰ä¿å­˜çš„密钥", + "privateKeyPath": "ç§é’¥è·¯å¾„", + "invalidCertificate": "无效的è¯ä¹¦", + "invalidPrivateKey": "无效的ç§é’¥", + "validatingData": "æ­£åœ¨éªŒè¯æ•°æ®", + "dataValid": "æ•°æ®æœ‰æ•ˆ", + "dataNotValid": "æ•°æ®æ— æ•ˆ", + "encryptionConfigSaved": "加密é…置已æˆåŠŸä¿å­˜", + "encryptionConfigNotSaved": "无法ä¿å­˜åР坆é…ç½®", + "configError": "é…置错误", + "enterOnlyCertificate": "åªè¾“å…¥è¯ä¹¦ã€‚ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", + "enterOnlyPrivateKey": "åªè¾“入密钥。ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", + "noItemsSearch": "没有匹é…的项目", + "clearSearch": "清除æœç´¢", + "exitSearch": "退出æœç´¢", + "searchClients": "æœç´¢å®¢æˆ·ç«¯", + "noClientsSearch": "没有匹é…的客户端。", + "customization": "定制", + "customizationDescription": "自定义此应用程åº", + "color": "颜色", + "useDynamicTheme": "使用动æ€ä¸»é¢˜", + "red": "红色", + "green": "绿色", + "blue": "è“色", + "yellow": "黄色", + "orange": "橙色", + "brown": "棕色", + "cyan": "é’色", + "purple": "紫色", + "pink": "粉色", + "deepOrange": "深橙色", + "indigo": "é›è“色", + "useThemeColorStatus": "使用主题颜色æ¥è¡¨ç¤ºçжæ€", + "useThemeColorStatusDescription": "用主题颜色和ç°è‰²æ›¿æ¢ç»¿è‰²å’Œçº¢è‰²çжæ€é¢œè‰²", + "invalidCertificateChain": "无效的è¯ä¹¦é“¾", + "validCertificateChain": "有效的è¯ä¹¦é“¾", + "subject": "主题", + "issuer": "å‘行人", + "expires": "过期", + "validPrivateKey": "有效的ç§é’¥", + "expirationDate": "到期日期", + "keysNotMatch": "无效的è¯ä¹¦æˆ–密钥:tls: ç§é’¥ä¸Žå…¬é’¥ä¸åŒ¹é…", + "timeLogs": "æ˜¾ç¤ºå¤„ç†æ—¶é—´", + "timeLogsDescription": "åœ¨æ—¥å¿—åˆ—è¡¨ä¸­æ˜¾ç¤ºå¤„ç†æ—¶é—´", + "hostNames": "主机å", + "keyType": "密钥类型", + "updateAvailable": "å¯ç”¨æ›´æ–°", + "installedVersion": "已安装版本", + "newVersion": "新版本", + "source": "æ¥æº", + "downloadUpdate": "下载更新", + "download": "下载", + "doNotRememberAgainUpdate": "ä¸è¦å†æ¬¡æé†’此版本", + "downloadingUpdate": "正在下载", + "completed": "已完æˆ", + "permissionNotGranted": "未授予æƒé™", + "inputSearchTerm": "输入æœç´¢è¯", + "answers": "å“应", + "copyClipboard": "å¤åˆ¶åˆ°å‰ªè´´æ¿", + "domainCopiedClipboard": "域åå·²å¤åˆ¶åˆ°å‰ªè´´æ¿", + "clearDnsCache": "清除 DNS 缓存", + "clearDnsCacheMessage": "æ‚¨ç¡®å®šè¦æ¸…除 DNS 缓存å—?", + "dnsCacheCleared": "DNS 缓存清除æˆåŠŸ", + "clearingDnsCache": "正在清除缓存...", + "dnsCacheNotCleared": "无法清除 DNS 缓存", + "clientsSelected": "已选择客户端", + "invalidDomain": "无效的域å", + "loadingBlockedServicesList": "正在加载已拦截的æœåŠ¡åˆ—è¡¨...", + "blockedServicesListNotLoaded": "无法加载已拦截的æœåŠ¡åˆ—è¡¨", + "error": "错误", + "updates": "æ›´æ–°", + "updatesDescription": "æ›´æ–° AdGuard Home ", + "updateNow": "ç«‹å³æ›´æ–°", + "currentVersion": "当å‰ç‰ˆæœ¬", + "requestStartUpdateFailed": "请求å¯åŠ¨æ›´æ–°å¤±è´¥", + "requestStartUpdateSuccessful": "请求å¯åŠ¨æ›´æ–°æˆåŠŸ", + "serverUpdated": "AdGuard Home 已是最新版", + "unknownStatus": "未知状æ€", + "checkingUpdates": "正在检查更新...", + "checkUpdates": "检查更新", + "requestingUpdate": "正在请求更新...", + "autoupdateUnavailable": "自动更新ä¸å¯ç”¨", + "autoupdateUnavailableDescription": "æ­¤æœåС噍䏿”¯æŒè‡ªåŠ¨æ›´æ–°æœåŠ¡ã€‚è¿™å¯èƒ½æ˜¯å› ä¸ºæœåŠ¡å™¨æ­£åœ¨ Docker 容器中è¿è¡Œã€‚æ‚¨éœ€è¦æ‰‹åŠ¨æ›´æ–°æœåС噍", + "minute": "{time} 分钟", + "minutes": "{time} 分钟", + "hour": "{time} å°æ—¶", + "hours": "{time} å°æ—¶", + "remainingTime": "剩余时间", + "safeSearchSettings": "安全æœç´¢è®¾ç½®", + "loadingSafeSearchSettings": "正在加载安全æœç´¢è®¾ç½®...", + "safeSearchSettingsNotLoaded": "加载安全æœç´¢è®¾ç½®æ—¶å‡ºé”™ã€‚", + "loadingLogsSettings": "正在加载日志设置...", + "selectOptionLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªé€‰é¡¹", + "selectClientLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªå®¢æˆ·ç«¯", + "disableList": "ç¦ç”¨è®¢é˜…规则", + "enableList": "å¯ç”¨è®¢é˜…规则", + "screens": "å±å¹•", + "copiedClipboard": "å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", + "seeDetails": "查看详细信æ¯", + "listNotAvailable": "订阅规则ä¸å¯ç”¨", + "copyListUrl": "å¤åˆ¶è®¢é˜…规则 URL", + "listUrlCopied": "订阅规则 URL å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", + "unsupportedVersion": "䏿”¯æŒçš„版本", + "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\\n\\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ã€‚alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", + "iUnderstand": "我了解", + "appUpdates": "åº”ç”¨ç¨‹åºæ›´æ–°", + "usingLatestVersion": "您正在使用最新版本", + "ipLogs": "显示客户端 IP", + "ipLogsDescription": "始终在日志中显示 IP 地å€ï¼Œè€Œä¸æ˜¯å®¢æˆ·ç«¯åç§°", + "application": "应用程åº", + "combinedChart": "åˆå¹¶å›¾è¡¨", + "combinedChartDescription": "将所有图表åˆå¹¶ä¸ºä¸€ä¸ª", + "statistics": "统计", + "errorLoadFilters": "加载过滤器时出错", + "clientRemovedSuccessfully": "客户端删除æˆåŠŸ", + "editRewriteRule": "编辑é‡å†™è§„则", + "dnsRewriteRuleUpdated": "DNS é‡å†™è§„则更新æˆåŠŸ", + "dnsRewriteRuleNotUpdated": "无法更新 DNS é‡å†™è§„则", + "updatingRule": "正在更新规则...", + "serverUpdateNeeded": "éœ€è¦æ›´æ–°æœåС噍", + "updateYourServer": "å°† AdGuard Home æœåŠ¡å™¨æ›´æ–°åˆ° {version} 或更高版本以使用此功能", + "january": "1月", + "february": "2月", + "march": "3月", + "april": "4月", + "may": "5月", + "june": "6月", + "july": "7月", + "august": "8月", + "september": "9月", + "october": "10月", + "november": "11月", + "december": "12月", + "malwarePhising": "æ¶æ„/钓鱼网站", + "queries": "查询", + "adultSites": "æˆäººç½‘ç«™", + "quickFilters": "状æ€è¿‡æ»¤å™¨", + "searchDomainInternet": "在互è”网上æœç´¢è¯¥åŸŸå" +} From 3d6a9530e6f40183f314eb3df50c7863ef014934 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 7 Aug 2023 02:53:00 +0200 Subject: [PATCH 279/676] Added apt update linux job --- .github/workflows/release-stable.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 382ebec..efcfaa9 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -102,7 +102,7 @@ jobs: - name: Update version in debian.yaml run: sed -i 's//${{ github.event.inputs.version }}/g' debian/debian.yaml - name: Install dependencies - run: sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev + run: sudo apt-get update && apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev - uses: subosito/flutter-action@v2 with: channel: "stable" From 36ba51a78da4e5bc23e7d3b723ea955bc5a95d90 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 7 Aug 2023 02:55:38 +0200 Subject: [PATCH 280/676] Updated workflow --- .github/workflows/release-stable.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index efcfaa9..cfebecd 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -101,8 +101,10 @@ jobs: run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml - name: Update version in debian.yaml run: sed -i 's//${{ github.event.inputs.version }}/g' debian/debian.yaml + - name: Update dependencies list + run: sudo apt-get update - name: Install dependencies - run: sudo apt-get update && apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev + run: sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev - uses: subosito/flutter-action@v2 with: channel: "stable" From 141cb9c5f62921acdbcc319ac397e0e1dc7737a3 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Mon, 7 Aug 2023 09:29:15 +0800 Subject: [PATCH 281/676] Update app_zh_CN.arb --- lib/l10n/app_zh_CN.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb index 4cb5df5..f6a5eaf 100644 --- a/lib/l10n/app_zh_CN.arb +++ b/lib/l10n/app_zh_CN.arb @@ -619,7 +619,7 @@ "copyListUrl": "å¤åˆ¶è®¢é˜…规则 URL", "listUrlCopied": "订阅规则 URL å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", "unsupportedVersion": "䏿”¯æŒçš„版本", - "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\\n\\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ã€‚alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", + "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\n\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ã€‚alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", "iUnderstand": "我了解", "appUpdates": "åº”ç”¨ç¨‹åºæ›´æ–°", "usingLatestVersion": "您正在使用最新版本", From 12fd317f4d7ba6b93c94e49e8191bada57bf2eb6 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Mon, 7 Aug 2023 09:29:40 +0800 Subject: [PATCH 282/676] Update app_zh.arb --- lib/l10n/app_zh.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 4cb5df5..f6a5eaf 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -619,7 +619,7 @@ "copyListUrl": "å¤åˆ¶è®¢é˜…规则 URL", "listUrlCopied": "订阅规则 URL å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", "unsupportedVersion": "䏿”¯æŒçš„版本", - "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\\n\\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ã€‚alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", + "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\n\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ã€‚alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", "iUnderstand": "我了解", "appUpdates": "åº”ç”¨ç¨‹åºæ›´æ–°", "usingLatestVersion": "您正在使用最新版本", From b90d838ebc5cac66a08c57cb8f42783ae7c19942 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 28 Aug 2023 20:19:49 +0200 Subject: [PATCH 283/676] Bug fixes --- lib/models/dhcp.dart | 8 ++++---- lib/models/dns_info.dart | 4 ++-- lib/models/encryption.dart | 2 +- lib/screens/settings/dhcp/dhcp.dart | 12 +++++++----- lib/screens/settings/general_settings.dart | 1 + lib/widgets/combined_line_chart.dart | 6 ++++-- lib/widgets/line_chart.dart | 6 ++++-- 7 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index 7bba2ca..aaf4a42 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -55,8 +55,8 @@ String dhcpStatusToJson(DhcpStatus data) => json.encode(data.toJson()); class DhcpStatus { String? interfaceName; - IpVersion v4; - IpVersion v6; + IpVersion? v4; + IpVersion? v6; List leases; List staticLeases; bool enabled; @@ -81,8 +81,8 @@ class DhcpStatus { Map toJson() => { "interface_name": interfaceName, - "v4": v4.toJson(), - "v6": v6.toJson(), + "v4": v4 != null ? v4!.toJson() : null, + "v6": v6 != null ? v6!.toJson() : null, "leases": List.from(leases.map((x) => x)), "static_leases": List.from(staticLeases.map((x) => x)), "enabled": enabled, diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 528ca5b..138efa3 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -10,8 +10,8 @@ class DnsInfo { bool disableIpv6; String? upstreamMode; int? cacheSize; - int cacheTtlMin; - int cacheTtlMax; + int? cacheTtlMin; + int? cacheTtlMax; bool cacheOptimistic; bool resolveClients; bool usePrivatePtrResolvers; diff --git a/lib/models/encryption.dart b/lib/models/encryption.dart index 3e2e230..8f8a3a0 100644 --- a/lib/models/encryption.dart +++ b/lib/models/encryption.dart @@ -32,7 +32,7 @@ class EncryptionData { final int? portDnsOverTls; final int? portDnsOverQuic; final int? portDnscrypt; - final String dnscryptConfigFile; + final String? dnscryptConfigFile; final bool allowUnencryptedDoh; final String certificateChain; final String privateKey; diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 402a063..a93a338 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -61,11 +61,13 @@ class _DhcpScreenState extends State { if (dhcpProvider.dhcp!.dhcpStatus.interfaceName != null && dhcpProvider.dhcp!.dhcpStatus.interfaceName != '') { try {selectedInterface = dhcpProvider.dhcp!.networkInterfaces.firstWhere((iface) => iface.name == dhcpProvider.dhcp!.dhcpStatus.interfaceName);} catch (_) {} enabled = dhcpProvider.dhcp!.dhcpStatus.enabled; - ipv4StartRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.rangeStart; - ipv4EndRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.rangeEnd ?? ''; - ipv4SubnetMaskController.text = dhcpProvider.dhcp!.dhcpStatus.v4.subnetMask ?? ''; - ipv4GatewayController.text = dhcpProvider.dhcp!.dhcpStatus.v4.gatewayIp ?? ''; - ipv4LeaseTimeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.leaseDuration.toString(); + if (dhcpProvider.dhcp!.dhcpStatus.v4 != null) { + ipv4StartRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.rangeStart; + ipv4EndRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.rangeEnd ?? ''; + ipv4SubnetMaskController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.subnetMask ?? ''; + ipv4GatewayController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.gatewayIp ?? ''; + ipv4LeaseTimeController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.leaseDuration.toString(); + } } }); } diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index e68aae3..1f73784 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -63,6 +63,7 @@ class _GeneralSettingsState extends State { isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), ); + if (!mounted) return; if (res != null) { setState(() => appUpdatesStatus = AppUpdatesStatus.available); } diff --git a/lib/widgets/combined_line_chart.dart b/lib/widgets/combined_line_chart.dart index 14d6d3e..3b82f1f 100644 --- a/lib/widgets/combined_line_chart.dart +++ b/lib/widgets/combined_line_chart.dart @@ -26,6 +26,8 @@ class CustomCombinedLineChart extends StatelessWidget { String chartDate(DateTime date) { String twoDigits(int number) => number.toString().padLeft(2, '0'); + String shortMonth(String month) => month.length > 3 ? month.substring(0, 3) : month; + String getMonth(int month) { final List months = [ AppLocalizations.of(context)!.january, @@ -45,10 +47,10 @@ class CustomCombinedLineChart extends StatelessWidget { } if (daysInterval == true) { - return "${date.day} ${getMonth(date.month).substring(0, 3)}"; + return "${date.day} ${shortMonth(getMonth(date.month))}"; } else { - return "${date.day} ${getMonth(date.month).substring(0, 3)} ${twoDigits(date.hour)}:00"; + return "${date.day} ${shortMonth(getMonth(date.month))} ${twoDigits(date.hour)}:00"; } } diff --git a/lib/widgets/line_chart.dart b/lib/widgets/line_chart.dart index 92814b1..c94ec5d 100644 --- a/lib/widgets/line_chart.dart +++ b/lib/widgets/line_chart.dart @@ -24,6 +24,8 @@ class CustomLineChart extends StatelessWidget { String chartDate(DateTime date) { String twoDigits(int number) => number.toString().padLeft(2, '0'); + String shortMonth(String month) => month.length > 3 ? month.substring(0, 3) : month; + String getMonth(int month) { final List months = [ AppLocalizations.of(context)!.january, @@ -44,10 +46,10 @@ class CustomLineChart extends StatelessWidget { } if (daysInterval == true) { - return "${date.day} ${getMonth(date.month).substring(0, 3)}"; + return "${date.day} ${shortMonth(getMonth(date.month))}"; } else { - return "${date.day} ${getMonth(date.month).substring(0, 3)} ${twoDigits(date.hour)}:00"; + return "${date.day} ${shortMonth(getMonth(date.month))} ${twoDigits(date.hour)}:00"; } } From f450e06a80c7c810bc7bf322d138c6ec8a8e2855 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 28 Aug 2023 20:23:07 +0200 Subject: [PATCH 284/676] Added create connection help button --- lib/constants/urls.dart | 1 + lib/widgets/add_server_modal.dart | 42 ++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart index 6626285..440c8d7 100644 --- a/lib/constants/urls.dart +++ b/lib/constants/urls.dart @@ -5,4 +5,5 @@ class Urls { static const String getReleasesGitHub = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases"; static const String adGuardHomeReleasesTags = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/tags"; static const String googleSearchUrl = "https://www.google.com/search"; + static const String connectionInstructions = "https://github.com/JGeek00/adguard-home-manager/wiki/Create-a-connection"; } \ No newline at end of file diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 3f384e8..362eee9 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -7,6 +7,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/urls.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/base64.dart'; @@ -648,20 +650,28 @@ class _AddServerModalState extends State { ), ], ), - IconButton( - tooltip: widget.server == null - ? AppLocalizations.of(context)!.connect - : AppLocalizations.of(context)!.save, - onPressed: allDataValid == true - ? widget.server == null - ? () => connect() - : () => edit() - : null, - icon: Icon( - widget.server == null - ? Icons.login_rounded - : Icons.save_rounded - ) + Row( + children: [ + IconButton( + onPressed: () => openUrl(Urls.connectionInstructions), + icon: const Icon(Icons.help_outline_outlined) + ), + IconButton( + tooltip: widget.server == null + ? AppLocalizations.of(context)!.connect + : AppLocalizations.of(context)!.save, + onPressed: allDataValid == true + ? widget.server == null + ? () => connect() + : () => edit() + : null, + icon: Icon( + widget.server == null + ? Icons.login_rounded + : Icons.save_rounded + ) + ), + ], ), ], ), @@ -683,6 +693,10 @@ class _AddServerModalState extends State { appBar: AppBar( title: Text(AppLocalizations.of(context)!.createConnection), actions: [ + IconButton( + onPressed: () => openUrl(Urls.connectionInstructions), + icon: const Icon(Icons.help_outline_outlined) + ), IconButton( tooltip: widget.server == null ? AppLocalizations.of(context)!.connect From 15fe0dec5fb9042bbbd769c024b8eb0a0a20155c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 28 Aug 2023 20:44:46 +0200 Subject: [PATCH 285/676] Updated dependencies --- macos/Podfile.lock | 14 +++++++------- pubspec.lock | 8 ++++---- pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index f8ac696..42c9fce 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -9,13 +9,13 @@ PODS: - FMDB/standard (2.7.5) - package_info_plus (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.7.1): - - SentryPrivate (= 8.7.1) + - Sentry/HybridSDK (8.9.1): + - SentryPrivate (= 8.9.1) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.7.1) - - SentryPrivate (8.7.1) + - Sentry/HybridSDK (= 8.9.1) + - SentryPrivate (8.9.1) - sqflite (0.0.2): - FlutterMacOS - FMDB (>= 2.7.5) @@ -83,9 +83,9 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - Sentry: 11776f6a25a128808d793d0d41bb7ad873b5ae4f - sentry_flutter: 886dbeb2674ba1232f540c54311a774bb50fda42 - SentryPrivate: b3c448eacdabe9eab7679a2e0af609c608f91572 + Sentry: e3203780941722a1fcfee99e351de14244c7f806 + sentry_flutter: 8f0ffd53088e6a4d50c095852c5cad9e4405025c + SentryPrivate: 5e3683390f66611fc7c6215e27645873adb55d13 sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea sqlite3: fd89671d969f3e73efe503ce203e28b016b58f68 sqlite3_flutter_libs: 00a50503d69f7ab0fe85a5ff25b33082f4df4ce9 diff --git a/pubspec.lock b/pubspec.lock index b1df451..6f2f566 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -498,18 +498,18 @@ packages: dependency: transitive description: name: sentry - sha256: "01f8fc950b6a5f3daf8c2d2b0ae5c38812e63d703c19c56cb68524c0597660bc" + sha256: "39c23342fc96105da449914f7774139a17a0ca8a4e70d9ad5200171f7e47d6ba" url: "https://pub.dev" source: hosted - version: "7.6.1" + version: "7.9.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "9583ebcdbbba6907e555a8eeaf42380021baff57db1e399a3a31e80ce1f1cbe5" + sha256: ff68ab31918690da004a42e20204242a3ad9ad57da7e2712da8487060ac9767f url: "https://pub.dev" source: hosted - version: "7.6.1" + version: "7.9.0" sky_engine: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 6f3b2dc..7b157f2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -70,7 +70,7 @@ dependencies: url_launcher: ^6.1.11 contextmenu: ^3.0.0 async: ^2.10.0 - sentry_flutter: ^7.5.2 + sentry_flutter: ^7.9.0 flutter_dotenv: ^5.0.2 dev_dependencies: From 7cddd75e46994a1420fa90c07334f7bd9803e42c Mon Sep 17 00:00:00 2001 From: Adrian English Lord Of The Manor Date: Sat, 2 Sep 2023 17:19:11 +0200 Subject: [PATCH 286/676] =?UTF-8?q?tworzenie=20j=C4=99zyka=20polskiego?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit w trakcie tÅ‚umaczenia kontynuować od lini 257 --- lib/l10n/app_pl.arb | 657 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 657 insertions(+) create mode 100644 lib/l10n/app_pl.arb diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb new file mode 100644 index 0000000..555e5a5 --- /dev/null +++ b/lib/l10n/app_pl.arb @@ -0,0 +1,657 @@ +{ + "home": "Dom", + "settings": "Ustawienia", + "connect": "Połączyć", + "servers": "Serwery", + "createConnection": "Utwórz połączenie", + "name": "Nazwa", + "ipDomain": "Adres IP lub domena", + "path": "Åšcieżka", + "port": "Port", + "username": "Nazwa użytkownika", + "password": "HasÅ‚o", + "defaultServer": "Serwer domyÅ›lny", + "general": "Ogólne", + "connection": "Połączenie", + "authentication": "Uwierzytelnianie", + "other": "Inne", + "invalidPort": "NieprawidÅ‚owy port", + "invalidPath": "NieprawidÅ‚owa Å›cieżka", + "invalidIpDomain": "NieprawidÅ‚owy adres IP lub domena", + "ipDomainNotEmpty": "Adres IP lub domena nie mogÄ… być puste", + "nameNotEmpty": "Nazwa nie może być pusta", + "invalidUsernamePassword": "NieprawidÅ‚owa nazwa użytkownika lub hasÅ‚o", + "tooManyAttempts": "Zbyt wiele prób, spróbuj ponownie później", + "cantReachServer": "Nie można połączyć siÄ™ z serwerem. Sprawdź dane połączenia.", + "sslError": "Błąd SSL. Przejdź do pozycji Ustawienia > Ustawienia zaawansowane i włącz opcjÄ™ ZastÄ…p sprawdzanie poprawnoÅ›ci SSL.", + "unknownError": "Nieznany błąd", + "connectionNotCreated": "Nie można utworzyć połączenia", + "connecting": "ÅÄ…czenie...", + "connected": "Połączony", + "selectedDisconnected": "Zaznaczone, ale rozłączone", + "connectionDefaultSuccessfully": "Połączenie ustawione jako domyÅ›lne pomyÅ›lnie.", + "connectionDefaultFailed": "Nie można ustawić połączenia jako domyÅ›lne.", + "noSavedConnections": "Brak zapisanych połączeÅ„", + "cannotConnect": "Nie można połączyć siÄ™ z serwerem", + "connectionRemoved": "Połączenie zostaÅ‚o pomyÅ›lnie usuniÄ™te.", + "connectionCannotBeRemoved": "Nie można usunąć połączenia.", + "remove": "UsuÅ„", + "removeWarning": "Czy na pewno chcesz usunąć połączenie z tym serwerem AdGuard Home?", + "cancel": "Anuluj", + "defaultConnection": "Połączenie domyÅ›lne", + "setDefault": "Ustaw jako domyÅ›lne", + "edit": "Edytuj", + "delete": "UsuÅ„", + "save": "Zapisz", + "serverStatus": "Stan serwera", + "connectionNotUpdated": "Połączenie nie zostaÅ‚o zaktualizowane", + "ruleFilteringWidget": "Widget ReguÅ‚ filtrowania", + "safeBrowsingWidget": "Widget Bezpieczne przeglÄ…danie", + "parentalFilteringWidget": "Widget Filtrowania rodzicielskiego", + "safeSearchWidget": "Widget Bezpiecznego wyszukiwania", + "ruleFiltering": "ReguÅ‚y filtrowania", + "safeBrowsing": "Bezpieczne przeglÄ…danie", + "parentalFiltering": "Filtrowanie rodzicielskie", + "safeSearch": "Bezpieczne wyszukiwanie", + "serverStatusNotRefreshed": "Nie można odÅ›wieżyć stanu serwera", + "loadingStatus": "Stan Å‚adowania...", + "errorLoadServerStatus": "Nie można zaÅ‚adować stanu serwera", + "topQueriedDomains": "Najczęściej wyszukiwane domeny", + "viewMore": "Zobacz wiÄ™cej", + "topClients": "Najlepsi klienci", + "topBlockedDomains": "Najczęściej blokowane domeny", + "appSettings": "Ustawienia aplikacji", + "theme": "Motyw", + "light": "Jasny", + "dark": "Ciemny", + "systemDefined": "Zdefiniowany przez system", + "close": "Zamknij", + "connectedTo": "Połączony z:", + "selectedServer": "Wybrany serwer:", + "noServerSelected": "Nie wybrano serwera", + "manageServer": "ZarzÄ…dzanie serwerem", + "allProtections": "Wszystkie zabezpieczenia", + "userNotEmpty": "Nazwa użytkownika nie może być pusta", + "passwordNotEmpty": "HasÅ‚o nie może być puste", + "examplePath": "PrzykÅ‚ad: /adguard", + "helperPath": "JeÅ›li używasz zwrotnego serwera proxy", + "aboutApp": "O aplikacji", + "appVersion": "Wersja aplikacji", + "createdBy": "Stworzone przez", + "clients": "Klienci", + "allowed": "Dozwolone", + "blocked": "Zablokowane", + "noClientsList": "Na tej liÅ›cie nie ma klientów", + "activeClients": "Aktywny", + "removeClient": "UsuÅ„ klienta", + "removeClientMessage": "Czy na pewno chcesz usunąć tego klienta z listy?", + "confirm": "Potwierdź", + "removingClient": "Usuwanie klienta...", + "clientNotRemoved": "Nie można usunąć klienta z listy", + "addClient": "Dodaj klienta", + "list": "Lista", + "ipAddress": "Adres IP", + "ipNotValid": "Adres IP jest nieprawidÅ‚owy", + "clientAddedSuccessfully": "Klient zostaÅ‚ pomyÅ›lnie dodany do listy.", + "addingClient": "Dodawanie klienta...", + "clientNotAdded": "Nie można dodać klienta do listy.", + "clientAnotherList": "Ten klient jest już na innej liÅ›cie.", + "noSavedLogs": "Brak zapisanych danych w dzienniku logów", + "logs": "Logi", + "copyLogsClipboard": "Kopiowanie dzienników logów do schowka", + "logsCopiedClipboard": "Dzienniki logów skopiowane do schowka", + "advancedSettings": "Ustawienia zaawansowane", + "dontCheckCertificate": "Nie sprawdzaj certyfikatu SSL", + "dontCheckCertificateDescription": "ZastÄ™puje sprawdzanie poprawnoÅ›ci certyfikatu SSL serwera", + "advancedSetupDescription": "Opcje zaawansowane", + "settingsUpdatedSuccessfully": "Ustawienia zostaÅ‚y pomyÅ›lnie zaktualizowane.", + "cannotUpdateSettings": "Nie można zaktualizować ustawieÅ„.", + "restartAppTakeEffect": "Uruchom ponownie aplikacjÄ™", + "loadingLogs": "Åadowanie logów dzienników...", + "logsNotLoaded": "Nie można zaÅ‚adować listy dzienników", + "processed": "Przetworzone\nBrak listy", + "processedRow": "Przetworzone (brak listy)", + "blockedBlacklist": "Zablokowane\nCzarna lista", + "blockedBlacklistRow": "Zablokowane (czarna lista)", + "blockedSafeBrowsing": "Zablokowane\nBezpieczne przeglÄ…danie", + "blockedSafeBrowsingRow": "Zablokowane (bezpieczne przeglÄ…danie)", + "blockedParental": "Zablokowane\nFiltrowanie rodzicielskie", + "blockedParentalRow": "Zablokowane (filtrowanie rodzicielskie)", + "blockedInvalid": "Zablokowany\nNieprawidÅ‚owy", + "blockedInvalidRow": "Zablokowane (nieprawidÅ‚owe)", + "blockedSafeSearch": "Zablokowane\nBezpieczne wyszukiwanie", + "blockedSafeSearchRow": "Zablokowane (bezpieczne wyszukiwanie)", + "blockedService": "Zablokowana\nZablokowana usÅ‚uga", + "blockedServiceRow": "Zablokowana (zablokowana usÅ‚uga)", + "processedWhitelist": "Przetworzone\nBiaÅ‚a lista", + "processedWhitelistRow": "Przetworzone (biaÅ‚a lista)", + "processedError": "Przetworzone\nBłąd", + "processedErrorRow": "Przetworzone (błąd)", + "rewrite": "Nadpisać", + "status": "Status", + "result": "Wynik", + "time": "Czas", + "blocklist": "Lista zablokowanych", + "request": "Żądanie", + "domain": "Domena", + "type": "Type", + "clas": "Klasa", + "response": "Odpowiedź", + "dnsServer": "DNS server", + "elapsedTime": "Czas, który upÅ‚ynÄ…Å‚", + "responseCode": "Kod odpowiedzi", + "client": "Klient", + "deviceIp": "Adres IP urzÄ…dzenia", + "deviceName": "Nazwa urzÄ…dzenia", + "logDetails": "Szczegóły dziennika logów", + "blockingRule": "ReguÅ‚a blokowania", + "blockDomain": "Blokowanie domeny", + "couldntGetFilteringStatus": "Nie można uzyskać stanu filtrowanias", + "unblockDomain": "Odblokuj domenÄ™", + "userFilteringRulesNotUpdated": "Nie można zaktualizować reguÅ‚ filtrowania użytkowników.", + "userFilteringRulesUpdated": "ReguÅ‚y filtrowania użytkowników zostaÅ‚y pomyÅ›lnie zaktualizowane", + "savingUserFilters": "Zapisywanie filtrów użytkownika...", + "filters": "Filtry", + "logsOlderThan": "Dzienniki logów starsze niż", + "responseStatus": "Stan odpowiedzi", + "selectTime": "Wybierz czas", + "notSelected": "Nie wybrano", + "resetFilters": "Resetowanie filtrów", + "noLogsDisplay": "Brak dzienników logów do wyÅ›wietlenia", + "noLogsThatOld": "Możliwe, że dla wybranego czasu nie zapisano żadnych dzienników logów. Spróbuj wybrać nowszÄ… godzinÄ™.", + "apply": "Zastosować", + "selectAll": "Zaznacz wszystko", + "unselectAll": "Odznacz wszystko", + "all": "Wszystko", + "filtered": "Przefiltrowano", + "checkAppLogs": "Sprawdź dzienniki logów aplikacji", + "refresh": "OdÅ›wież", + "search": "Szukaj", + "dnsQueries": "Zapytania DNS", + "average": "Åšrednia", + "blockedFilters": "Zablokowane przez filtry", + "malwarePhisingBlocked": "Zablokowane zÅ‚oÅ›liwe oprogramowanie/phishing", + "blockedAdultWebsites": "Zablokowane witryny dla dorosÅ‚ych", + "generalSettings": "Ustawienia główne", + "generalSettingsDescription": "Różne ustawienia", + "hideZeroValues": "Ukryj wartoÅ›ci zerowe", + "hideZeroValuesDescription": "Na ekranie głównym ukryj bloki o zerowej wartoÅ›ci", + "webAdminPanel": "Panel administracyjny WWW", + "visitGooglePlay": "Odwiedź stronÄ™ Google Play", + "gitHub": "Kod aplikacji dostÄ™pny na GitHub", + "blockClient": "Zablokuj klienta", + "selectTags": "Wybierz tagi", + "noTagsSelected": "Brak zaznaczonych tagów", + "tags": "Tagi", + "identifiers": "Identyfikatory", + "identifier": "Identyfikator", + "identifierHelper": "Adres IP , CIDR, Addres MAC, or ClientID", + "noIdentifiers": "Nie dodano identyfikatorów", + "useGlobalSettings": "Użyj ustawieÅ„ globalnych", + "enableFiltering": "Włącz filtrowanie", + "enableSafeBrowsing": "Włącz bezpieczne przeglÄ…danie", + "enableParentalControl": "Włącz kontrolÄ™ rodzicielskÄ…", + "enableSafeSearch": "Włącz bezpieczne wyszukiwanie", + "blockedServices": "Zablokowane usÅ‚ugi", + "selectBlockedServices": "Wybierz usÅ‚ugi do zablokowaniak", + "noBlockedServicesSelected": "Brak zablokowanych usÅ‚ug", + "services": "UsÅ‚ugi", + "servicesBlocked": "UsÅ‚ugi zablokowane", + "tagsSelected": "wybrane tagi", + "upstreamServers": "Serwery nadrzÄ™dne", + "serverAddress": " Adres servera", + "noUpstreamServers": "Brak serwerów nadrzÄ™dnych.", + "willBeUsedGeneralServers": "Wykorzystane zostanÄ… ogólne serwery nadrzÄ™dne.", + "added": "Dodane", + "clientUpdatedSuccessfully": "Klient zostaÅ‚ pomyÅ›lnie zaktualizowany", + "clientNotUpdated": "Nie można zaktualizować klienta", + "clientDeletedSuccessfully": "Klient zostaÅ‚ pomyÅ›lnie usuniÄ™ty", + "clientNotDeleted": "Nie można usunąć klienta", + "options": "Opcje", + "loadingFilters": "Åadowanie filtrów...", + "filtersNotLoaded": "Nie można zaÅ‚adować filtrów.", + "whitelists": "BiaÅ‚a lista", + "blacklists": "Czarna lista", + "rules": "Zasady", + "customRules": "ReguÅ‚y niestandardowe", + "enabledRules": "Włączone reguÅ‚y", + "enabled": "Włączone", + "disabled": "Wyłączone", + "rule": "ReguÅ‚a", + "addCustomRule": "Dodaj niestandardowÄ… regułę", + "removeCustomRule": "UsuÅ„ regułę niestandardowÄ…", + "removeCustomRuleMessage": "Czy na pewno chcesz usunąć tÄ™ regułę niestandardowÄ…?", + "updatingRules": "Aktualizowanie reguÅ‚ niestandardowych...", + "ruleRemovedSuccessfully": "ReguÅ‚a zostaÅ‚a pomyÅ›lnie usuniÄ™ta", + "ruleNotRemoved": "Nie można usunąć reguÅ‚y", + "ruleAddedSuccessfully": "ReguÅ‚a dodana pomyÅ›lnie", + "ruleNotAdded": "Nie można dodać reguÅ‚y", + "noCustomFilters": "Brak filtrów niestandardowych", + "noBlockedClients": "Brak zablokowanych klientów", + "noBlackLists": "Brak czarnych list", + "noWhiteLists": "Brak biaÅ‚ych list", + "addWhitelist": "Dodaj białą listÄ™", + "addBlacklist": "Dodaj czarnÄ… listÄ™", + "urlNotValid": "Adres URL jest nieprawidÅ‚owy", + "urlAbsolutePath": "Adres URL lub Å›cieżka bezwzglÄ™dna", + "addingList": "Dodawanie listy...", + "listAdded": "Lista zostaÅ‚a dodana pomyÅ›lnie. Dodane elementy:", + "listAlreadyAdded": "Lista zostaÅ‚a już dodana", + "listUrlInvalid": "Adres URL listy jest nieprawidÅ‚owy", + "listNotAdded": "Nie można dodać listy", + "listDetails": "Szczegóły listy", + "listType": "Typ listy", + "whitelist": "BiaÅ‚a lista", + "blacklist": "Czarna list", + "latestUpdate": "Najnowsza aktualizacja", + "disable": "Wyłączyć", + "enable": "Włączać", + "currentStatus": "Aktualny stan", + "listDataUpdated": "Dane listy zostaÅ‚y pomyÅ›lnie zaktualizowane", + "listDataNotUpdated": "Nie można zaktualizować danych listy", + "updatingListData": "Aktualizowanie danych listy...", + "editWhitelist": "Edytuj białą listÄ™", + "editBlacklist": "Edytuj czarnÄ… listÄ™", + "deletingList": "Usuwanie listy...", + "listDeleted": "Lista usuniÄ™ta pomyÅ›lnie", + "listNotDeleted": "Nie można usunąć listy", + "deleteList": "UsuÅ„ listÄ™", + "deleteListMessage": "Czy na pewno chcesz usunąć tÄ™ listÄ™? Tej akcji nie można cofnąć.", + "serverSettings": "Ustawienia serwera", + "serverInformation": "Informacje o serwerze", + "serverInformationDescription": "Informacje i status serwera", + "loadingServerInfo": "Åadowanie informacji o serwerze...", + "serverInfoNotLoaded": "Nie można zaÅ‚adować informacji o serwerze.", + "dnsAddresses": "Adresy DNS", + "seeDnsAddresses": "Zobacz adresy DNS", + "dnsPort": "Port DNS", + "httpPort": "Port HTTP", + "protectionEnabled": "Ochrona włączona", + "dhcpAvailable": "DostÄ™pne DHCP", + "serverRunning": "Serwer dziaÅ‚a", + "serverVersion": "Wersia Serwera", + "serverLanguage": "JÄ™zyk serwera", + "yes": "Tak", + "no": "Nie", + "allowedClients": "Dozwoleni klienci", + "disallowedClients": "Disallowed clients", + "disallowedDomains": "Disallowed domains", + "accessSettings": "Access settings", + "accessSettingsDescription": "Configure access rules for the server", + "loadingClients": "Loading clients...", + "clientsNotLoaded": "Clients couldn't be loaded.", + "noAllowedClients": "No allowed clients", + "allowedClientsDescription": "If this list has entries, AdGuard Home will accept requests only from these clients.", + "blockedClientsDescription": "If this list has entries, AdGuard Home will drop requests from these clients. This field is ignored if there are entries in Allowed clients.", + "disallowedDomainsDescription": "AdGuard Home drops DNS queries matching these domains, and these queries don't even appear in the query log.", + "addClientFieldDescription": "CIDRs, IP address, or ClientID", + "clientIdentifier": "Client identifier", + "allowClient": "Allow client", + "disallowClient": "Disallow client", + "noDisallowedDomains": "No disallowed domains", + "domainNotAdded": "The domain couldn't be added", + "statusSelected": "status selected", + "updateLists": "Update lists", + "checkHostFiltered": "Check host", + "updatingLists": "Updating lists...", + "listsUpdated": "lists updated", + "listsNotUpdated": "Couldn't update lists", + "listsNotLoaded": "Lists couldn't be loaded", + "domainNotValid": "Domain not valid", + "check": "Check", + "checkingHost": "Checking host...", + "errorCheckingHost": "Host couldn't be checked", + "block": "Block", + "unblock": "Unblock", + "custom": "Custom", + "addImportant": "Add $important", + "howCreateRules": "How to create custom rules", + "examples": "Examples", + "example1": "Block access to example.org and all its subdomains.", + "example2": "Unblocks access to example.org and all its subdomains.", + "example3": "Adds a comment.", + "example4": "Block access to domains matching the specified regular expression.", + "moreInformation": "More information", + "addingRule": "Adding rule...", + "deletingRule": "Deleting rule...", + "enablingList": "Enabling list...", + "disablingList": "Disabling list...", + "disableFiltering": "Disable filtering", + "enablingFiltering": "Enabling filtering...", + "disablingFiltering": "Disabling filtering...", + "filteringStatusUpdated": "Filtering status updated successfully", + "filteringStatusNotUpdated": "Filtering status couldn't be updated", + "updateFrequency": "Update frequency", + "never": "Never", + "hour1": "1 hour", + "hours12": "12 hours", + "hours24": "24 hours", + "days3": "3 days", + "days7": "7 days", + "changingUpdateFrequency": "Changing...", + "updateFrequencyChanged": "Update frequency changed successfully", + "updateFrequencyNotChanged": "Updare frecuency couldn't be changed", + "updating": "Updating values...", + "blockedServicesUpdated": "Blocked services updated successfully", + "blockedServicesNotUpdated": "Blocked services couldn't be updated", + "insertDomain": "Insert a domain to check it's stauts.", + "dhcpSettings": "DHCP settings", + "dhcpSettingsDescription": "Configure the DHCP server", + "dhcpSettingsNotLoaded": "DHCP settings could not be loaded", + "loadingDhcp": "Loading DHCP settings...", + "enableDhcpServer": "Enable DHCP server", + "selectInterface": "Select interface", + "hardwareAddress": "Hardware address", + "gatewayIp": "Gateway IP", + "ipv4addresses": "IPv4 addresses", + "ipv6addresses": "IPv6 addresses", + "neededSelectInterface": "You need to select an interface to configure the DHCP server.", + "ipv4settings": "IPv4 settings", + "startOfRange": "Start of range", + "endOfRange": "End of range", + "ipv6settings": "IPv6 settings", + "subnetMask": "Subnet mask", + "subnetMaskNotValid": "Subnet mask not valid", + "gateway": "Gateway", + "gatewayNotValid": "Gateway not valid", + "leaseTime": "Lease time", + "seconds": "{time} seconds", + "leaseTimeNotValid": "Lease time not valid", + "restoreConfiguration": "Reset configuration", + "restoreConfigurationMessage": "Are you sure you want to continue? This will reset all the configuration. This action cannot be undone.", + "changeInterface": "Change interface", + "savingSettings": "Saving settings...", + "settingsSaved": "Settings saved successfully", + "settingsNotSaved": "Settings couldn't be saved", + "restoringConfig": "Restoring configuration...", + "configRestored": "Configuration reseted successfully", + "configNotRestored": "The configuration couldn't be reseted", + "dhcpStatic": "DHCP static leases", + "noDhcpStaticLeases": "No DHCP static leases found", + "deleting": "Deleting...", + "staticLeaseDeleted": "DHCP static lease deleted successfully", + "staticLeaseNotDeleted": "The DHCP static lease could not be deleted", + "deleteStaticLease": "Delete static lease", + "deleteStaticLeaseDescription": "The DHCP static lease will be deleted. This action cannot be reverted.", + "addStaticLease": "Add static lease", + "macAddress": "MAC address", + "macAddressNotValid": "MAC address not valid", + "hostName": "Host name", + "hostNameError": "Host name cannot be empty", + "creating": "Creating...", + "staticLeaseCreated": "DHCP static lease created successfully", + "staticLeaseNotCreated": "The DHCP static lease couldn't be created", + "staticLeaseExists": "The DHCP static lease already exists", + "serverNotConfigured": "Server not configured", + "restoreLeases": "Reset leases", + "restoreLeasesMessage": "Are you sure you want to continue? This will reset all the existing leases. This action cannot be undone.", + "restoringLeases": "Resetting leases...", + "leasesRestored": "Leases reseted successfully", + "leasesNotRestored": "The leases couldn't be reseted", + "dhcpLeases": "DHCP leases", + "noLeases": "No DHCP leases available", + "dnsRewrites": "DNS rewrites", + "dnsRewritesDescription": "Configure custom DNS rules", + "loadingRewriteRules": "Loading rewrite rules...", + "rewriteRulesNotLoaded": "DNS rewrite rules could not be loaded.", + "noRewriteRules": "No DNS rewrite rules", + "answer": "Answer", + "deleteDnsRewrite": "Delete DNS rewrite", + "deleteDnsRewriteMessage": "Are you sure you want to delete this DNS rewrite? This action cannot be undone.", + "dnsRewriteRuleDeleted": "DNS rewrite rule deleted successfully", + "dnsRewriteRuleNotDeleted": "The DNS rewrite rule could not be deleted", + "addDnsRewrite": "Add DNS rewrite", + "addingRewrite": "Adding rewrite...", + "dnsRewriteRuleAdded": "DNS rewrite rule addded successfully", + "dnsRewriteRuleNotAdded": "DNS rewrite rule could not be added", + "logsSettings": "Logs settings", + "enableLog": "Enable log", + "clearLogs": "Clear logs", + "anonymizeClientIp": "Anonymize client IP", + "hours6": "6 hours", + "days30": "30 days", + "days90": "90 days", + "retentionTime": "Retention time", + "selectOneItem": "Select one item", + "logSettingsNotLoaded": "Log settings couldn't be loaded.", + "updatingSettings": "Updating settings...", + "logsConfigUpdated": "Logs settings updated successfully", + "logsConfigNotUpdated": "Logs settings couldn't be updated", + "deletingLogs": "Clearing logs...", + "logsCleared": "Logs cleared successfully", + "logsNotCleared": "Logs could not be cleared", + "runningHomeAssistant": "Running on Home Assistant", + "serverError": "Server error", + "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.", + "noBootstrapDns": "No bootstrap DNS servers added.", + "bootstrapDnsServersInfo": "Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams.", + "privateReverseDnsServers": "Private reverse DNS servers", + "privateReverseDnsServersDescription": "The DNS servers that AdGuard Home uses for local PTR queries. These servers are used to resolve PTR requests for addresses in private IP ranges, for example \"192.168.12.34\", using reverse DNS. If not set, AdGuard Home uses the addresses of the default DNS resolvers of your OS except for the addresses of AdGuard Home itself.", + "reverseDnsDefault": "By default, AdGuard Home uses the following reverse DNS resolvers", + "addItem": "Add item", + "noServerAddressesAdded": "No server addresses added.", + "usePrivateReverseDnsResolvers": "Use private reverse DNS resolvers", + "usePrivateReverseDnsResolversDescription": "Perform reverse DNS lookups for locally served addresses using these upstream servers. If disabled, AdGuard Home responds with NXDOMAIN to all such PTR requests except for clients known from DHCP, /etc/hosts, and so on.", + "enableReverseResolving": "Enable reverse resolving of clients' IP addresses", + "enableReverseResolvingDescription": "Reversely resolve clients' IP addresses into their hostnames by sending PTR queries to corresponding resolvers (private DNS servers for local clients, upstream servers for clients with public IP addresses).", + "dnsServerSettings": "AdGuard Home DNS server settings", + "limitRequestsSecond": "Rate limit per second", + "valueNotNumber": "Value is not a number", + "enableEdns": "Enable EDNS client subnet", + "enableEdnsDescription": "Add the EDNS Client Subnet option (ECS) to upstream requests and log the values sent by the clients in the query log.", + "enableDnssec": "Enable DNSSEC", + "enableDnssecDescription": "Set DNSSEC flag in the outcoming DNS queries and check the result (DNSSEC-enabled resolver is required).", + "disableResolvingIpv6": "Disable resolving of IPv6 addresses", + "disableResolvingIpv6Description": "Drop all DNS queries for IPv6 addresses (type AAAA).", + "blockingMode": "Blocking mode", + "defaultMode": "Default", + "defaultDescription": "Respond with zero IP address (0.0.0.0 for A; :: for AAAA) when blocked by Adblock-style rule; respond with the IP address specified in the rule when blocked by /etc/hosts-style rule", + "refusedDescription": "Respond with REFUSED code", + "nxdomainDescription": "Respond with NXDOMAIN code", + "nullIp": "Null IP", + "nullIpDescription": "Respond with zero IP address (0.0.0.0 for A; :: for AAAA)", + "customIp": "Custom IP", + "customIpDescription": "Respond with a manually set IP address", + "dnsCacheConfig": "DNS cache configuration", + "cacheSize": "Cache size", + "inBytes": "In bytes", + "overrideMinimumTtl": "Override minimum TTL", + "overrideMinimumTtlDescription": "Extend short time-to-live values (seconds) received from the upstream server when caching DNS responses.", + "overrideMaximumTtl": "Override maximum TTL", + "overrideMaximumTtlDescription": "Set a maximum time-to-live value (seconds) for entries in the DNS cache.", + "optimisticCaching": "Optimistic caching", + "optimisticCachingDescription": "Make AdGuard Home respond from the cache even when the entries are expired and also try to refresh them.", + "loadingDnsConfig": "Loading DNS configuration...", + "dnsConfigNotLoaded": "DNS config could not be loaded.", + "blockingIpv4": "Blocking IPv4", + "blockingIpv4Description": "IP address to be returned for a blocked A request", + "blockingIpv6": "Blocking IPv6", + "blockingIpv6Description": "IP address to be returned for a blocked AAAA request", + "invalidIp": "Invalid IP address", + "dnsConfigSaved": "DNS server configuration saved successfully", + "dnsConfigNotSaved": "The DNS server configuration could not be saved", + "savingConfig": "Saving configuration...", + "someValueNotValid": "Some value is not valid", + "upstreamDnsDescription": "Configure upstream servers and DNS mode", + "bootstrapDnsDescription": "Configure the bootstrap DNS servers", + "privateReverseDnsDescription": "Configure custom DNS resolvers and enable private reverse DNS resolving", + "dnsServerSettingsDescription": "Configure a rate limit, the blocking mode and more", + "dnsCacheConfigDescription": "Configure how the server should manage the DNS cache", + "comment": "Comment", + "address": "Address", + "commentsDescription": "Comments are always preceded by #. You don't have to add it, it will be added automatically.", + "encryptionSettings": "Encryption settings", + "encryptionSettingsDescription": "Encryption (HTTPS/QUIC/TLS) support", + "loadingEncryptionSettings": "Loading encryption settings...", + "encryptionSettingsNotLoaded": "Encryption settings couldn't be loaded.", + "enableEncryption": "Enable encryption", + "enableEncryptionTypes": "HTTPS, DNS-over-HTTPS, and DNS-over-TLS", + "enableEncryptionDescription": "If encryption is enabled, AdGuard Home admin interface will work over HTTPS, and the DNS server will listen for requests over DNS-over-HTTPS and DNS-over-TLS.", + "serverConfiguration": "Server configuration", + "domainName": "Domain name", + "domainNameDescription": "If set, AdGuard Home detects ClientIDs, responds to DDR queries, and performs additional connection validations. If not set, these features are disabled. Must match one of the DNS Names in the certificate.", + "redirectHttps": "Redirect to HTTPS automatically", + "httpsPort": "HTTPS port", + "tlsPort": "DNS-over-TLS port", + "dnsOverQuicPort": "DNS-over-QUIC port", + "certificates": "Certificates", + "certificatesDescription": "In order to use encryption, you need to provide a valid SSL certificates chain for your domain. You can get a free certificate on letsencrypt.org or you can buy it from one of the trusted Certificate Authorities.", + "certificateFilePath": "Set a certificates file path", + "pasteCertificateContent": "Paste the certificates contents", + "certificatePath": "Certificate path", + "certificateContent": "Certificate content", + "privateKey": "Private key", + "privateKeyFile": "Set a private key file", + "pastePrivateKey": "Paste the private key contents", + "usePreviousKey": "Use the previously saved key", + "privateKeyPath": "Private key path", + "invalidCertificate": "Invalid certificate", + "invalidPrivateKey": "Invalid private key", + "validatingData": "Validating data", + "dataValid": "Data is valid", + "dataNotValid": "Data not valid", + "encryptionConfigSaved": "Encryption configuration saved successfully", + "encryptionConfigNotSaved": "Encryption configuration could not be saved", + "configError": "Configuration error", + "enterOnlyCertificate": "Enter only the certificate. Do not input the ---BEGIN--- and ---END--- lines.", + "enterOnlyPrivateKey": "Enter only the key. Do not input the ---BEGIN--- and ---END--- lines.", + "noItemsSearch": "No items for that search.", + "clearSearch": "Clear search", + "exitSearch": "Exit search", + "searchClients": "Search clients", + "noClientsSearch": "No clients with that search.", + "customization": "Customization", + "customizationDescription": "Customize this application", + "color": "Color", + "useDynamicTheme": "Use dynamic theme", + "red": "Red", + "green": "Green", + "blue": "Blue", + "yellow": "Yellow", + "orange": "Orange", + "brown": "Brown", + "cyan": "Cyan", + "purple": "Purple", + "pink": "Pink", + "deepOrange": "Deep orange", + "indigo": "Indigo", + "useThemeColorStatus": "Use theme color for status", + "useThemeColorStatusDescription": "Replaces green and red status colors with theme color and grey", + "invalidCertificateChain": "Invalid certificate chain", + "validCertificateChain": "Valid certificate chain", + "subject": "Subject", + "issuer": "Issuer", + "expires": "Expires", + "validPrivateKey": "Valid private key", + "expirationDate": "Expiration date", + "keysNotMatch": "Invalid certificate or key: tls: private key does not match public key", + "timeLogs": "Time on logs", + "timeLogsDescription": "Show processing time on logs list", + "hostNames": "Host names", + "keyType": "Key type", + "updateAvailable": "Update available", + "installedVersion": "Installed version", + "newVersion": "New version", + "source": "Source", + "downloadUpdate": "Download update", + "download": "Download", + "doNotRememberAgainUpdate": "Do not remember again for this version", + "downloadingUpdate": "Downloading", + "completed": "completed", + "permissionNotGranted": "Permission not granted", + "inputSearchTerm": "Input a search term.", + "answers": "Answers", + "copyClipboard": "Copy to clipboard", + "domainCopiedClipboard": "Domain copied to the clipboard", + "clearDnsCache": "Clear DNS cache", + "clearDnsCacheMessage": "Are you sure you want to clear the DNS cache?", + "dnsCacheCleared": "DNS cache cleared successfully", + "clearingDnsCache": "Clearing cache...", + "dnsCacheNotCleared": "DNS cache couldn't be cleared", + "clientsSelected": "clients selected", + "invalidDomain": "Invalid domain", + "loadingBlockedServicesList": "Loading blocked services list...", + "blockedServicesListNotLoaded": "The blocked services list could not be loaded", + "error": "Error", + "updates": "Updates", + "updatesDescription": "Update the AdGuard Home server", + "updateNow": "Update now", + "currentVersion": "Current version", + "requestStartUpdateFailed": "Request to start update failed", + "requestStartUpdateSuccessful": "Request to start update successfull", + "serverUpdated": "Server is updated", + "unknownStatus": "Unknown status", + "checkingUpdates": "Checking updates...", + "checkUpdates": "Check updates", + "requestingUpdate": "Requesting update...", + "autoupdateUnavailable": "Autoupdate unavailable", + "autoupdateUnavailableDescription": "The autoupdate service is not available for this server. It could be because the server is running on a Docker container. You have to update your server manually.", + "minute": "{time} minute", + "minutes": "{time} minutes", + "hour": "{time} hour", + "hours": "{time} hours", + "remainingTime": "Remaining time", + "safeSearchSettings": "Safe search settings", + "loadingSafeSearchSettings": "Loading safe search settings...", + "safeSearchSettingsNotLoaded": "Error when loading safe search settings.", + "loadingLogsSettings": "Loading logs settings...", + "selectOptionLeftColumn": "Select an option of the left column", + "selectClientLeftColumn": "Select a client of the left column", + "disableList": "Disable list", + "enableList": "Enable list", + "screens": "Screens", + "copiedClipboard": "Copied to clipboard", + "seeDetails": "See details", + "listNotAvailable": "List not available", + "copyListUrl": "Copy list URL", + "listUrlCopied": "List URL copied to the clipboard", + "unsupportedVersion": "Unsupported version", + "unsupprtedVersionMessage": "The support for your server version {version} is not guaranteed. This application may have some issues working with that server version.\n\nAdGuard Home Manager is designed to work with the stable releases of the AdGuard Home server. It may work with alpha and beta releases, but the compatibility is not guaranteed and the app may have some issues working with that versions.", + "iUnderstand": "I understand", + "appUpdates": "Application updates", + "usingLatestVersion": "You are using the latest version", + "ipLogs": "IP on logs", + "ipLogsDescription": "Show always IP address on logs instead of client name", + "application": "Application", + "combinedChart": "Combined chart", + "combinedChartDescription": "Combine all charts into one", + "statistics": "Statistics", + "errorLoadFilters": "Error when loading filters.", + "clientRemovedSuccessfully": "Client removed successfully.", + "editRewriteRule": "Edit rewrite rule", + "dnsRewriteRuleUpdated": "DNS rewrite rule updated successfully", + "dnsRewriteRuleNotUpdated": "DNS rewrite rule could not be updated", + "updatingRule": "Updating rule...", + "serverUpdateNeeded": "Server update needed", + "updateYourServer": "Update your AdGuard Home server to {version} or greater to use this feature.", + "january": "January", + "february": "February", + "march": "March", + "april": "April", + "may": "May", + "june": "June", + "july": "July", + "august": "August", + "september": "September", + "october": "October", + "november": "November", + "december": "December", + "malwarePhising": "Malware/phising", + "queries": "Queries", + "adultSites": "Adult sites", + "quickFilters": "Quick filters", + "searchDomainInternet": "Search domain on the Internet" +} From 637d0fe6e9042a0751cbdff8f6fbfecd59153769 Mon Sep 17 00:00:00 2001 From: Adrian English Lord Of The Manor Date: Mon, 4 Sep 2023 21:33:49 +0200 Subject: [PATCH 287/676] Update app_pl.arb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kontynuować tÅ‚umaczenie od 361 --- lib/l10n/app_pl.arb | 170 ++++++++++++++++++++++---------------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 555e5a5..7587f8a 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -185,7 +185,7 @@ "tags": "Tagi", "identifiers": "Identyfikatory", "identifier": "Identyfikator", - "identifierHelper": "Adres IP , CIDR, Addres MAC, or ClientID", + "identifierHelper": "Adres IP , CIDR, Adres MAC, or ClientID", "noIdentifiers": "Nie dodano identyfikatorów", "useGlobalSettings": "Użyj ustawieÅ„ globalnych", "enableFiltering": "Włącz filtrowanie", @@ -274,90 +274,90 @@ "yes": "Tak", "no": "Nie", "allowedClients": "Dozwoleni klienci", - "disallowedClients": "Disallowed clients", - "disallowedDomains": "Disallowed domains", - "accessSettings": "Access settings", - "accessSettingsDescription": "Configure access rules for the server", - "loadingClients": "Loading clients...", - "clientsNotLoaded": "Clients couldn't be loaded.", - "noAllowedClients": "No allowed clients", - "allowedClientsDescription": "If this list has entries, AdGuard Home will accept requests only from these clients.", - "blockedClientsDescription": "If this list has entries, AdGuard Home will drop requests from these clients. This field is ignored if there are entries in Allowed clients.", - "disallowedDomainsDescription": "AdGuard Home drops DNS queries matching these domains, and these queries don't even appear in the query log.", - "addClientFieldDescription": "CIDRs, IP address, or ClientID", - "clientIdentifier": "Client identifier", - "allowClient": "Allow client", - "disallowClient": "Disallow client", - "noDisallowedDomains": "No disallowed domains", - "domainNotAdded": "The domain couldn't be added", - "statusSelected": "status selected", - "updateLists": "Update lists", - "checkHostFiltered": "Check host", - "updatingLists": "Updating lists...", - "listsUpdated": "lists updated", - "listsNotUpdated": "Couldn't update lists", - "listsNotLoaded": "Lists couldn't be loaded", - "domainNotValid": "Domain not valid", - "check": "Check", - "checkingHost": "Checking host...", - "errorCheckingHost": "Host couldn't be checked", - "block": "Block", - "unblock": "Unblock", - "custom": "Custom", - "addImportant": "Add $important", - "howCreateRules": "How to create custom rules", - "examples": "Examples", - "example1": "Block access to example.org and all its subdomains.", - "example2": "Unblocks access to example.org and all its subdomains.", - "example3": "Adds a comment.", - "example4": "Block access to domains matching the specified regular expression.", - "moreInformation": "More information", - "addingRule": "Adding rule...", - "deletingRule": "Deleting rule...", - "enablingList": "Enabling list...", - "disablingList": "Disabling list...", - "disableFiltering": "Disable filtering", - "enablingFiltering": "Enabling filtering...", - "disablingFiltering": "Disabling filtering...", - "filteringStatusUpdated": "Filtering status updated successfully", - "filteringStatusNotUpdated": "Filtering status couldn't be updated", - "updateFrequency": "Update frequency", - "never": "Never", - "hour1": "1 hour", - "hours12": "12 hours", - "hours24": "24 hours", - "days3": "3 days", - "days7": "7 days", - "changingUpdateFrequency": "Changing...", - "updateFrequencyChanged": "Update frequency changed successfully", - "updateFrequencyNotChanged": "Updare frecuency couldn't be changed", - "updating": "Updating values...", - "blockedServicesUpdated": "Blocked services updated successfully", - "blockedServicesNotUpdated": "Blocked services couldn't be updated", - "insertDomain": "Insert a domain to check it's stauts.", - "dhcpSettings": "DHCP settings", - "dhcpSettingsDescription": "Configure the DHCP server", - "dhcpSettingsNotLoaded": "DHCP settings could not be loaded", - "loadingDhcp": "Loading DHCP settings...", - "enableDhcpServer": "Enable DHCP server", - "selectInterface": "Select interface", - "hardwareAddress": "Hardware address", - "gatewayIp": "Gateway IP", - "ipv4addresses": "IPv4 addresses", - "ipv6addresses": "IPv6 addresses", - "neededSelectInterface": "You need to select an interface to configure the DHCP server.", - "ipv4settings": "IPv4 settings", - "startOfRange": "Start of range", - "endOfRange": "End of range", - "ipv6settings": "IPv6 settings", - "subnetMask": "Subnet mask", - "subnetMaskNotValid": "Subnet mask not valid", - "gateway": "Gateway", - "gatewayNotValid": "Gateway not valid", - "leaseTime": "Lease time", - "seconds": "{time} seconds", - "leaseTimeNotValid": "Lease time not valid", - "restoreConfiguration": "Reset configuration", + "disallowedClients": "Niedozwoloni klienci", + "disallowedDomains": "Niedozwolone domeny", + "accessSettings": "Ustawienia dostÄ™pu", + "accessSettingsDescription": "Konfigurowanie reguÅ‚ dostÄ™pu dla serwera", + "loadingClients": "Åadowanie klientów...", + "clientsNotLoaded": "Nie można zaÅ‚adować klientów.", + "noAllowedClients": "Brak dozwolonych klientów.", + "allowedClientsDescription": "JeÅ›li ta lista zawiera wpisy, AdGuard Home bÄ™dzie akceptować żądania tylko od tych klientów.", + "blockedClientsDescription": "JeÅ›li ta lista zawiera wpisy, AdGuard Home odrzuci żądania od tych klientów. To pole jest ignorowane, jeÅ›li w obszarze Dozwolone klienty znajdujÄ… siÄ™ wpisy", + "disallowedDomainsDescription": "AdGuard Home usuwa zapytania DNS pasujÄ…ce do tych domen, a zapytania te nawet nie pojawiajÄ… siÄ™ w dzienniku zapytaÅ„", + "addClientFieldDescription": "CIDRs, adres IP or ClientID", + "clientIdentifier": "Identyfikator klienta", + "allowClient": "Zezwól klientowi", + "disallowClient": "Nie zezwalaj klientowi", + "noDisallowedDomains": "Brak niedozwolonych domen", + "domainNotAdded": "Nie można dodać domeny", + "statusSelected": "Wybrany status", + "updateLists": "Aktualizuj listy", + "checkHostFiltered": "Sprawdź hosta", + "updatingLists": "Aktualizowanie list...", + "listsUpdated": "Zaktualizowano listy", + "listsNotUpdated": "Nie można zaktualizować list", + "listsNotLoaded": "Nie można zaÅ‚adować list", + "domainNotValid": "NieprawidÅ‚owa domena", + "check": "Sprawdź", + "checkingHost": "Sprawdzanie hosta...", + "errorCheckingHost": "Nie można sprawdzić hosta", + "block": "Zablokować", + "unblock": "Odblokować", + "custom": "Niestandardowy", + "addImportant": "Dodawaj $important", + "howCreateRules": "Jak tworzyć reguÅ‚y niestandardowe", + "examples": "PrzykÅ‚ady", + "example1": "Zablokuj dostÄ™p do example.org i wszystkich jej subdomen.", + "example2": "Odblokowuje dostÄ™p do example.org i wszystkich jego subdomen.", + "example3": "Dodaje komentarz.", + "example4": "Blokowanie dostÄ™pu do domen zgodnych z okreÅ›lonym wyrażeniem regularnym.", + "moreInformation": "WiÄ™cej informacji", + "addingRule": "Dodawanie reguÅ‚y...", + "deletingRule": "Usuwanie reguÅ‚y...", + "enablingList": "Włączanie listy...", + "disablingList": "Wyłączanie listy...", + "disableFiltering": "Wyłącz filtrowanie", + "enablingFiltering": "Włączanie filtrowania...", + "disablingFiltering": "Wyłączanie filtrowania...", + "filteringStatusUpdated": "Stan filtrowania zostaÅ‚ pomyÅ›lnie zaktualizowany", + "filteringStatusNotUpdated": "Nie można zaktualizować stanu filtrowania", + "updateFrequency": "CzÄ™stotliwość aktualizacji", + "never": "Nigdy", + "hour1": "Co 1 godzinÄ™", + "hours12": "Co 12 godzin", + "hours24": "Co 24 godziny", + "days3": "Co 3 dni", + "days7": "Co 7 dni", + "changingUpdateFrequency": "Zmieniam...", + "updateFrequencyChanged": "CzÄ™stotliwość aktualizacji zostaÅ‚a pomyÅ›lnie zmieniona", + "updateFrequencyNotChanged": "Nie można zmienić czÄ™stotliwoÅ›ci aktualizacji", + "updating": "Aktualizowanie wartoÅ›ci...", + "blockedServicesUpdated": "Zablokowane usÅ‚ugi zostaÅ‚y pomyÅ›lnie zaktualizowane", + "blockedServicesNotUpdated": "Nie można zaktualizować zablokowanych usÅ‚ug", + "insertDomain": "Wstaw domenÄ™, aby sprawdzić jej status.", + "dhcpSettings": "Ustawienia DHCP", + "dhcpSettingsDescription": "Konfigurowanie serwera DHCP", + "dhcpSettingsNotLoaded": "Nie można zaÅ‚adować ustawieÅ„ DHCP", + "loadingDhcp": "Åadowanie ustawieÅ„ DHCP...", + "enableDhcpServer": "Włącz serwer DHCP", + "selectInterface": "Wybierz interfejs", + "hardwareAddress": "Adres sprzÄ™towy", + "gatewayIp": "Adres IP bramy", + "ipv4addresses": "Adres IPv4", + "ipv6addresses": "Adres IPv6", + "neededSelectInterface": "Aby skonfigurować serwer DHCP, należy wybrać interfejs.", + "ipv4settings": "Ustawienia IPv4", + "startOfRange": "PoczÄ…tek zakresu", + "endOfRange": "Koniec zakresu", + "ipv6settings": "Ustawienia IPv6", + "subnetMask": "Maska podsieci", + "subnetMaskNotValid": "Maska podsieci jest nieprawidÅ‚owa", + "gateway": "Brama", + "gatewayNotValid": "Brama jest nieprawidÅ‚owa", + "leaseTime": "Czas dzierżawy", + "seconds": "{time} sekund", + "leaseTimeNotValid": "Czas dzierżawy jest nieaktualny", + "restoreConfiguration": "Zresetuj konfiguracjÄ™", "restoreConfigurationMessage": "Are you sure you want to continue? This will reset all the configuration. This action cannot be undone.", "changeInterface": "Change interface", "savingSettings": "Saving settings...", From 31f5e045c8457accb95f0a6cd39a372561bf01b9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 4 Sep 2023 23:32:48 +0200 Subject: [PATCH 288/676] Updated flutter version --- android/build.gradle | 2 +- pubspec.lock | 180 ++++++++++++++++++++++--------------------- 2 files changed, 95 insertions(+), 87 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index f546a89..09b245a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.6.10' + ext.kotlin_version = '1.8.20' repositories { google() mavenCentral() diff --git a/pubspec.lock b/pubspec.lock index 6f2f566..29e7ed3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,26 +13,26 @@ packages: dependency: "direct main" description: name: animations - sha256: fe8a6bdca435f718bb1dc8a11661b2c22504c6da40ef934cee8327ed77934164 + sha256: ef57563eed3620bd5d75ad96189846aca1e033c0c45fc9a7d26e80ab02b88a70 url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.0.8" archive: dependency: transitive description: name: archive - sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + sha256: "49b1fad315e57ab0bbc15bcbb874e83116a1d78f77ebd500a4af6c9407d6b28e" url: "https://pub.dev" source: hosted - version: "3.3.7" + version: "3.3.8" args: dependency: transitive description: name: args - sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" async: dependency: "direct main" description: @@ -85,10 +85,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" contextmenu: dependency: "direct main" description: @@ -117,26 +117,26 @@ packages: dependency: transitive description: name: csslib - sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f" url: "https://pub.dev" source: hosted - version: "0.17.2" + version: "0.17.3" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" device_info_plus: dependency: "direct main" description: name: device_info_plus - sha256: "499c61743e13909c13374a8c209075385858c614b9c0f2487b5f9995eeaf7369" + sha256: "86add5ef97215562d2e090535b0a16f197902b10c369c558a100e74ea06e8659" url: "https://pub.dev" source: hosted - version: "9.0.1" + version: "9.0.3" device_info_plus_platform_interface: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: "74dff1435a695887ca64899b8990004f8d1232b0e84bfc4faa1fdda7c6f57cc1" + sha256: de4798a7069121aee12d5895315680258415de9b00e717723a1bd73d58f0126d url: "https://pub.dev" source: hosted - version: "1.6.5" + version: "1.6.6" equatable: dependency: transitive description: @@ -181,18 +181,18 @@ packages: dependency: transitive description: name: ffi - sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.0" file: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.0.0" fl_chart: dependency: "direct main" description: @@ -218,18 +218,18 @@ packages: dependency: "direct main" description: name: flutter_dotenv - sha256: d9283d92059a22e9834bc0a31336658ffba77089fb6f3cc36751f1fc7c6661a3 + sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.1.0" flutter_html: dependency: "direct main" description: name: flutter_html - sha256: "850c07bc6c1ed060d3eb3e88469a598260a13eb45d8978b197c1348e0a2b101f" + sha256: "02ad69e813ecfc0728a455e4bf892b9379983e050722b1dce00192ee2e41d1ee" url: "https://pub.dev" source: hosted - version: "3.0.0-beta.1" + version: "3.0.0-beta.2" flutter_launcher_icons: dependency: "direct dev" description: @@ -242,10 +242,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.3" flutter_localizations: dependency: "direct main" description: flutter @@ -255,18 +255,18 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "7b25c10de1fea883f3c4f9b8389506b54053cd00807beab69fd65c8653a2711f" + sha256: d4a1cb250c4e059586af0235f32e02882860a508e189b61f2b31b8810c1e1330 url: "https://pub.dev" source: hosted - version: "0.6.14" + version: "0.6.17+2" flutter_native_splash: dependency: "direct dev" description: name: flutter_native_splash - sha256: "02df24aec455c26428dadc637f20d4c548bda23ee2179479a8e8c39f1ecb75b3" + sha256: ecff62b3b893f2f665de7e4ad3de89f738941fcfcaaba8ee601e749efafa4698 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.2" flutter_split_view: dependency: "direct main" description: @@ -306,18 +306,18 @@ packages: dependency: "direct main" description: name: html - sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" url: "https://pub.dev" source: hosted - version: "0.15.3" + version: "0.15.4" http: dependency: transitive description: name: http - sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.6" + version: "1.1.0" http_parser: dependency: transitive description: @@ -338,10 +338,10 @@ packages: dependency: "direct main" description: name: intl - sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.18.0" + version: "0.18.1" js: dependency: transitive description: @@ -362,10 +362,10 @@ packages: dependency: transitive description: name: lints - sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015" + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" list_counter: dependency: transitive description: @@ -378,26 +378,26 @@ packages: dependency: "direct main" description: name: markdown - sha256: "8e332924094383133cee218b676871f42db2514f1f6ac617b6cf6152a7faab8e" + sha256: acf35edccc0463a9d7384e437c015a3535772e09714cf60e07eeef3a15870dcd url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "7.1.1" matcher: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -418,10 +418,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "28386bbe89ab5a7919a47cea99cdd1128e5a6e0bbd7eaafe20440ead84a15de3" + sha256: "6ff267fcd9d48cb61c8df74a82680e8b82e940231bb5f68356672fde0397334a" url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.1.0" package_info_plus_platform_interface: dependency: transitive description: @@ -474,10 +474,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.6" pointycastle: dependency: transitive description: @@ -519,50 +519,50 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" sqflite: dependency: "direct main" description: name: sqflite - sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" url: "https://pub.dev" source: hosted - version: "2.2.8+4" + version: "2.3.0" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555 + sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.5.0" sqflite_common_ffi: dependency: "direct main" description: name: sqflite_common_ffi - sha256: f86de82d37403af491b21920a696b19f01465b596f545d1acd4d29a0a72418ad + sha256: "0d5cc1be2eb18400ac6701c31211d44164393aa75886093002ecdd947be04f93" url: "https://pub.dev" source: hosted - version: "2.2.5" + version: "2.3.0+2" sqlite3: dependency: transitive description: name: sqlite3 - sha256: "2cef47b59d310e56f8275b13734ee80a9cf4a48a43172020cb55a620121fbf66" + sha256: db65233e6b99e99b2548932f55a987961bc06d82a31a0665451fa0b4fff4c3fb url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "2.1.0" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: "1e20a88d5c7ae8400e009f38ddbe8b001800a6dffa37832481a86a219bc904c7" + sha256: fb115050b0c2589afe2085a62d77f5deda4db65db20a5c65a6e0c92fda89b45e url: "https://pub.dev" source: hosted - version: "0.5.15" + version: "0.5.16" stack_trace: dependency: transitive description: @@ -575,10 +575,10 @@ packages: dependency: "direct main" description: name: store_checker - sha256: "9a08c82715fc72b8ef3520b18be98715e95e623ca6dc9693451606c276062b63" + sha256: c9c1a93f11fa756fea23a2a08d7e54e84626a8d3c759cf49fc694a3a5afdc705 url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.4.0" stream_channel: dependency: transitive description: @@ -615,10 +615,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" typed_data: dependency: transitive description: @@ -631,74 +631,74 @@ packages: dependency: transitive description: name: universal_io - sha256: "06866290206d196064fd61df4c7aea1ffe9a4e7c4ccaa8fcded42dd41948005d" + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.2" url_launcher: dependency: "direct main" description: name: url_launcher - sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" url: "https://pub.dev" source: hosted - version: "6.1.11" + version: "6.1.14" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "1a5848f598acc5b7d8f7c18b8cb834ab667e59a13edc3c93e9d09cf38cc6bc87" + sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 url: "https://pub.dev" source: hosted - version: "6.0.34" + version: "6.1.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "6.1.5" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.7" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.5" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" + sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5" url: "https://pub.dev" source: hosted - version: "2.0.16" + version: "2.0.20" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" + sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.8" uuid: dependency: "direct main" description: @@ -715,14 +715,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" win32: dependency: transitive description: name: win32 - sha256: "6ca3aaab1790eeb1f5cad232e33d9c53ba66e884dd3e7686c4e730bffc45f1a3" + sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.0.7" win32_registry: dependency: transitive description: @@ -757,5 +765,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" - flutter: ">=3.4.0-17.0.pre" + dart: ">=3.1.0 <4.0.0" + flutter: ">=3.13.0" From a57a65f12abaaab9964338b56054672e76089d34 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 4 Sep 2023 23:32:55 +0200 Subject: [PATCH 289/676] Updated scroll screens --- lib/screens/logs/log_details_screen.dart | 297 ++++++----- lib/screens/logs/logs.dart | 611 ++++++++++++----------- 2 files changed, 490 insertions(+), 418 deletions(-) diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 96ac2bf..859d5e7 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -82,111 +82,15 @@ class LogDetailsScreen extends StatelessWidget { } } - Widget content() { - return ListView( - children: [ - SectionLabel(label: AppLocalizations.of(context)!.status), - LogListTile( - icon: Icons.shield_rounded, - title: AppLocalizations.of(context)!.result, - subtitleWidget: getResult(), - trailing: log.cached == true - ? Container( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5 - ), - decoration: BoxDecoration( - color: Theme.of(context).floatingActionButtonTheme.backgroundColor, - borderRadius: BorderRadius.circular(30) - ), - child: Text( - "CACHE", - style: TextStyle( - fontSize: 12, - color: Theme.of(context).floatingActionButtonTheme.foregroundColor, - fontWeight: FontWeight.w500 - ), - ), - ) - : null, - ), - if (log.rule != null) LogListTile( - icon: Icons.block, - title: AppLocalizations.of(context)!.blockingRule, - subtitle: log.rule - ), - LogListTile( - icon: Icons.schedule, - title: AppLocalizations.of(context)!.time, - subtitle: convertTimestampLocalTimezone(log.time, 'HH:mm:ss') - ), - SectionLabel(label: AppLocalizations.of(context)!.request), - LogListTile( - icon: Icons.domain_rounded, - title: AppLocalizations.of(context)!.domain, - subtitle: log.question.name - ), - LogListTile( - icon: Icons.category_rounded, - title: AppLocalizations.of(context)!.type, - subtitle: log.question.type - ), - LogListTile( - icon: Icons.class_rounded, - title: AppLocalizations.of(context)!.clas, - subtitle: log.question.questionClass - ), - SectionLabel(label: AppLocalizations.of(context)!.response), - if (log.upstream != null && log.upstream != '') LogListTile( - icon: Icons.dns_rounded, - title: AppLocalizations.of(context)!.dnsServer, - subtitle: log.upstream - ), - LogListTile( - icon: Icons.timer_rounded, - title: AppLocalizations.of(context)!.elapsedTime, - subtitle: "${double.parse(log.elapsedMs).toStringAsFixed(2)} ms" - ), - if (log.status != null) LogListTile( - icon: Icons.system_update_alt_rounded, - title: AppLocalizations.of(context)!.responseCode, - subtitle: log.status - ), - SectionLabel(label: AppLocalizations.of(context)!.client), - LogListTile( - icon: Icons.smartphone_rounded, - title: AppLocalizations.of(context)!.deviceIp, - subtitle: log.client - ), - if (log.clientInfo != null && log.clientInfo!.name != '') LogListTile( - icon: Icons.abc_rounded, - title: AppLocalizations.of(context)!.deviceName, - subtitle: log.clientInfo!.name - ), - if (log.rules.isNotEmpty) ...[ - SectionLabel(label: AppLocalizations.of(context)!.rules), - ...log.rules.map((rule) { - final Filter? list = getList(rule.filterListId); - if (list != null) { - return LogListTile( - icon: Icons.rule_rounded, - title: rule.text, - subtitle: list.name - ); - } - else { - return const SizedBox(); - } - }).toList() - ], - if (log.answer.isNotEmpty) ...[ - SectionLabel(label: AppLocalizations.of(context)!.answers), - ...log.answer.map((a) => LogListTile( - icon: Icons.download_rounded, - title: a.value, - subtitle: "TTL: ${a.ttl.toString()}", - trailing: Container( + List content() { + return [ + SectionLabel(label: AppLocalizations.of(context)!.status), + LogListTile( + icon: Icons.shield_rounded, + title: AppLocalizations.of(context)!.result, + subtitleWidget: getResult(), + trailing: log.cached == true + ? Container( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 5 @@ -196,7 +100,7 @@ class LogDetailsScreen extends StatelessWidget { borderRadius: BorderRadius.circular(30) ), child: Text( - a.type, + "CACHE", style: TextStyle( fontSize: 12, color: Theme.of(context).floatingActionButtonTheme.foregroundColor, @@ -204,10 +108,104 @@ class LogDetailsScreen extends StatelessWidget { ), ), ) - )).toList() - ] + : null, + ), + if (log.rule != null) LogListTile( + icon: Icons.block, + title: AppLocalizations.of(context)!.blockingRule, + subtitle: log.rule + ), + LogListTile( + icon: Icons.schedule, + title: AppLocalizations.of(context)!.time, + subtitle: convertTimestampLocalTimezone(log.time, 'HH:mm:ss') + ), + SectionLabel(label: AppLocalizations.of(context)!.request), + LogListTile( + icon: Icons.domain_rounded, + title: AppLocalizations.of(context)!.domain, + subtitle: log.question.name + ), + LogListTile( + icon: Icons.category_rounded, + title: AppLocalizations.of(context)!.type, + subtitle: log.question.type + ), + LogListTile( + icon: Icons.class_rounded, + title: AppLocalizations.of(context)!.clas, + subtitle: log.question.questionClass + ), + SectionLabel(label: AppLocalizations.of(context)!.response), + if (log.upstream != null && log.upstream != '') LogListTile( + icon: Icons.dns_rounded, + title: AppLocalizations.of(context)!.dnsServer, + subtitle: log.upstream + ), + LogListTile( + icon: Icons.timer_rounded, + title: AppLocalizations.of(context)!.elapsedTime, + subtitle: "${double.parse(log.elapsedMs).toStringAsFixed(2)} ms" + ), + if (log.status != null) LogListTile( + icon: Icons.system_update_alt_rounded, + title: AppLocalizations.of(context)!.responseCode, + subtitle: log.status + ), + SectionLabel(label: AppLocalizations.of(context)!.client), + LogListTile( + icon: Icons.smartphone_rounded, + title: AppLocalizations.of(context)!.deviceIp, + subtitle: log.client + ), + if (log.clientInfo != null && log.clientInfo!.name != '') LogListTile( + icon: Icons.abc_rounded, + title: AppLocalizations.of(context)!.deviceName, + subtitle: log.clientInfo!.name + ), + if (log.rules.isNotEmpty) ...[ + SectionLabel(label: AppLocalizations.of(context)!.rules), + ...log.rules.map((rule) { + final Filter? list = getList(rule.filterListId); + if (list != null) { + return LogListTile( + icon: Icons.rule_rounded, + title: rule.text, + subtitle: list.name + ); + } + else { + return const SizedBox(); + } + }).toList() ], - ); + if (log.answer.isNotEmpty) ...[ + SectionLabel(label: AppLocalizations.of(context)!.answers), + ...log.answer.map((a) => LogListTile( + icon: Icons.download_rounded, + title: a.value, + subtitle: "TTL: ${a.ttl.toString()}", + trailing: Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5 + ), + decoration: BoxDecoration( + color: Theme.of(context).floatingActionButtonTheme.backgroundColor, + borderRadius: BorderRadius.circular(30) + ), + child: Text( + a.type, + style: TextStyle( + fontSize: 12, + color: Theme.of(context).floatingActionButtonTheme.foregroundColor, + fontWeight: FontWeight.w500 + ), + ), + ) + )).toList() + ] + ]; } if (dialog) { @@ -269,7 +267,9 @@ class LogDetailsScreen extends StatelessWidget { Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8), - child: content(), + child: ListView( + children: content(), + ) ), ) ], @@ -279,35 +279,60 @@ class LogDetailsScreen extends StatelessWidget { } else { return Scaffold( - appBar: AppBar( - centerTitle: false, - title: Text(AppLocalizations.of(context)!.logDetails), - actions: [ - IconButton( - onPressed: () => openUrl("${Urls.googleSearchUrl}?q=${log.question.name}"), - icon: const Icon(Icons.travel_explore_rounded), - tooltip: AppLocalizations.of(context)!.searchDomainInternet - ), - if (statusProvider.filteringStatus != null) IconButton( - onPressed: log.question.name != null - ? () => blockUnblock( - log.question.name!, - getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' - ) - : null, - icon: Icon( - getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? Icons.check_circle_rounded - : Icons.block + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + title: Text(AppLocalizations.of(context)!.logDetails), + actions: [ + IconButton( + onPressed: () => openUrl("${Urls.googleSearchUrl}?q=${log.question.name}"), + icon: const Icon(Icons.travel_explore_rounded), + tooltip: AppLocalizations.of(context)!.searchDomainInternet + ), + if (statusProvider.filteringStatus != null) IconButton( + onPressed: log.question.name != null + ? () => blockUnblock( + log.question.name!, + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' + ) + : null, + icon: Icon( + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? Icons.check_circle_rounded + : Icons.block + ), + tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? AppLocalizations.of(context)!.unblockDomain + : AppLocalizations.of(context)!.blockDomain, + ), + const SizedBox(width: 10) + ], ), - tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? AppLocalizations.of(context)!.unblockDomain - : AppLocalizations.of(context)!.blockDomain, - ), - const SizedBox(width: 10) + ) ], + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: content() + ) + ], + ), + ) + ) ), - body: content(), ); } } diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index f44a760..9a3b5af 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -192,123 +192,158 @@ class _LogsState extends State { Widget generateBody() { switch (logsProvider.loadStatus) { case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingLogs, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), - ) - ], - ), + SliverFillRemaining( + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingLogs, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) + ) + ], + ), + ) ); case LoadStatus.loaded: - return RefreshIndicator( - onRefresh: () async { - await logsProvider.fetchLogs(inOffset: 0); - }, - child: logsProvider.logsData!.data.isNotEmpty - ? ListView.builder( - controller: scrollController, - padding: const EdgeInsets.only(top: 0), - itemCount: logsProvider.isLoadingMore == true - ? logsProvider.logsData!.data.length+1 - : logsProvider.logsData!.data.length, - itemBuilder: (context, index) { - if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { - return const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - else if (logsProvider.logsData!.data[index].question.name != null) { - return LogTile( - log: logsProvider.logsData!.data[index], - index: index, - length: logsProvider.logsData!.data.length, - isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index], - onLogTap: (log) { - if (width <= 1100) { - Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false, - ) - )); - } - setState(() => selectedLog = log); - } - ); - } - else { - return null; - } - } - ) - : Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - AppLocalizations.of(context)!.noLogsDisplay, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - if (logsProvider.logsOlderThan != null) Padding( - padding: const EdgeInsets.only( - top: 30, - left: 20, - right: 20 - ), - child: Text( - AppLocalizations.of(context)!.noLogsThatOld, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - ] + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), - ) + if (logsProvider.logsData!.data.isNotEmpty) SliverList.builder( + itemCount: logsProvider.logsData!.data.length, + itemBuilder: (context, index) { + if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else if (logsProvider.logsData!.data[index].question.name != null) { + return LogTile( + log: logsProvider.logsData!.data[index], + index: index, + length: logsProvider.logsData!.data.length, + isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index], + onLogTap: (log) { + if (width <= 1100) { + Navigator.push(context, MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + ) + )); + } + setState(() => selectedLog = log); + } + ); + } + else { + return null; + } + } + ), + if (logsProvider.logsData!.data.isEmpty) SliverFillRemaining( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context)!.noLogsDisplay, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + if (logsProvider.logsOlderThan != null) Padding( + padding: const EdgeInsets.only( + top: 30, + left: 20, + right: 20 + ), + child: Text( + AppLocalizations.of(context)!.noLogsThatOld, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ] + ), + ), + ) + ], + ), + ) ); case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.logsNotLoaded, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), - ) - ], - ), + SliverFillRemaining( + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.logsNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) + ) + ], + ), + ) ); default: @@ -318,183 +353,195 @@ class _LogsState extends State { Widget logsScreen() { return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.logs), - centerTitle: false, - actions: [ - if (!(Platform.isAndroid || Platform.isIOS)) IconButton( - onPressed: () => logsProvider.fetchLogs(inOffset: 0), - icon: const Icon(Icons.refresh_rounded), - tooltip: AppLocalizations.of(context)!.refresh, - ), - logsProvider.loadStatus == LoadStatus.loaded - ? IconButton( - onPressed: openFilersModal, - icon: const Icon(Icons.filter_list_rounded), - tooltip: AppLocalizations.of(context)!.filters, - ) - : const SizedBox(), - if (statusProvider.serverStatus != null) IconButton( - tooltip: AppLocalizations.of(context)!.settings, - onPressed: () => { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => LogsConfigModal( - onConfirm: updateConfig, - onClear: clearQueries, - dialog: true, - serverVersion: statusProvider.serverStatus!.serverVersion, - ), - barrierDismissible: false - ) - } - else { - showModalBottomSheet( - context: context, - builder: (context) => LogsConfigModal( - onConfirm: updateConfig, - onClear: clearQueries, - dialog: false, - serverVersion: statusProvider.serverStatus!.serverVersion, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ) - } - }, - icon: const Icon(Icons.settings) - ), - const SizedBox(width: 5), - ], - bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null - ? PreferredSize( - preferredSize: const Size(double.maxFinite, 50), - child: Container( - height: 50, - width: double.maxFinite, - padding: const EdgeInsets.only(bottom: 10), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: showDivider == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.1) - : Colors.transparent, + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + title: Text(AppLocalizations.of(context)!.logs), + expandedHeight: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + ? 170 : null, + actions: [ + if (!(Platform.isAndroid || Platform.isIOS)) IconButton( + onPressed: () => logsProvider.fetchLogs(inOffset: 0), + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ), + logsProvider.loadStatus == LoadStatus.loaded + ? IconButton( + onPressed: openFilersModal, + icon: const Icon(Icons.filter_list_rounded), + tooltip: AppLocalizations.of(context)!.filters, + ) + : const SizedBox(), + if (statusProvider.serverStatus != null) IconButton( + tooltip: AppLocalizations.of(context)!.settings, + onPressed: () => { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => LogsConfigModal( + onConfirm: updateConfig, + onClear: clearQueries, + dialog: true, + serverVersion: statusProvider.serverStatus!.serverVersion, + ), + barrierDismissible: false + ) + } + else { + showModalBottomSheet( + context: context, + builder: (context) => LogsConfigModal( + onConfirm: updateConfig, + onClear: clearQueries, + dialog: false, + serverVersion: statusProvider.serverStatus!.serverVersion, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ) + } + }, + icon: const Icon(Icons.settings) + ), + const SizedBox(width: 5), + ], + bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + ? PreferredSize( + preferredSize: const Size(double.maxFinite, 70), + child: Container( + height: 50, + width: double.maxFinite, + padding: const EdgeInsets.only(bottom: 10), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: showDivider == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.1) + : Colors.transparent, + ) + ) + ), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + if (logsProvider.appliedFilters.searchText != null) ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.search_rounded, + ), + label: Row( + children: [ + Text( + logsProvider.appliedFilters.searchText!, + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: null, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.setSearchText(null); + logsProvider.fetchLogs( + inOffset: 0, + searchText: '' + ); + }, + ), + ], + if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.shield_rounded, + ), + label: Row( + children: [ + Text( + translatedString[logsProvider.appliedFilters.selectedResultStatus]!, + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: logsProvider.appliedFilters.searchText, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.setSelectedResultStatus('all'); + logsProvider.fetchLogs( + inOffset: 0, + responseStatus: 'all' + ); + }, + ), + ], + if (logsProvider.appliedFilters.clients != null) ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.smartphone_rounded, + ), + label: Row( + children: [ + Text( + logsProvider.appliedFilters.clients!.length == 1 + ? logsProvider.appliedFilters.clients![0] + : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: logsProvider.appliedFilters.searchText, + clients: null + ) + ); + logsProvider.setSelectedClients(null); + logsProvider.fetchLogs( + inOffset: 0, + responseStatus: logsProvider.appliedFilters.selectedResultStatus + ); + }, + ), + ], + const SizedBox(width: 15), + ], + ), ) ) - ), - child: ListView( - scrollDirection: Axis.horizontal, - children: [ - if (logsProvider.appliedFilters.searchText != null) ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.search_rounded, - ), - label: Row( - children: [ - Text( - logsProvider.appliedFilters.searchText!, - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: null, - clients: logsProvider.appliedFilters.clients - ) - ); - logsProvider.setSearchText(null); - logsProvider.fetchLogs( - inOffset: 0, - searchText: '' - ); - }, - ), - ], - if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.shield_rounded, - ), - label: Row( - children: [ - Text( - translatedString[logsProvider.appliedFilters.selectedResultStatus]!, - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: logsProvider.appliedFilters.searchText, - clients: logsProvider.appliedFilters.clients - ) - ); - logsProvider.setSelectedResultStatus('all'); - logsProvider.fetchLogs( - inOffset: 0, - responseStatus: 'all' - ); - }, - ), - ], - if (logsProvider.appliedFilters.clients != null) ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.smartphone_rounded, - ), - label: Row( - children: [ - Text( - logsProvider.appliedFilters.clients!.length == 1 - ? logsProvider.appliedFilters.clients![0] - : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: logsProvider.appliedFilters.searchText, - clients: null - ) - ); - logsProvider.setSelectedClients(null); - logsProvider.fetchLogs( - inOffset: 0, - responseStatus: logsProvider.appliedFilters.selectedResultStatus - ); - }, - ), - ], - const SizedBox(width: 15), - ], - ), - ) - ) - : null, + : null, + ), + ) + ], + body: generateBody() ), - body: generateBody() ); } From 551273b5285be26ef8797157d93ba2c9556691fc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 4 Sep 2023 23:34:10 +0200 Subject: [PATCH 290/676] Fix tooltip charts --- lib/widgets/combined_line_chart.dart | 1 + lib/widgets/line_chart.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/widgets/combined_line_chart.dart b/lib/widgets/combined_line_chart.dart index 3b82f1f..d22b2cc 100644 --- a/lib/widgets/combined_line_chart.dart +++ b/lib/widgets/combined_line_chart.dart @@ -85,6 +85,7 @@ class CustomCombinedLineChart extends StatelessWidget { lineTouchData: LineTouchData( enabled: true, touchTooltipData: LineTouchTooltipData( + fitInsideHorizontally: true, tooltipBgColor: selectedTheme == ThemeMode.light ? const Color.fromRGBO(220, 220, 220, 0.9) : const Color.fromRGBO(35, 35, 35, 0.9), diff --git a/lib/widgets/line_chart.dart b/lib/widgets/line_chart.dart index c94ec5d..5a5e181 100644 --- a/lib/widgets/line_chart.dart +++ b/lib/widgets/line_chart.dart @@ -90,6 +90,7 @@ class CustomLineChart extends StatelessWidget { lineTouchData: LineTouchData( enabled: true, touchTooltipData: LineTouchTooltipData( + fitInsideHorizontally: true, tooltipBgColor: selectedTheme == ThemeMode.light ? const Color.fromRGBO(220, 220, 220, 0.9) : const Color.fromRGBO(35, 35, 35, 0.9), From 6bdaedfee23b0784608aa25f149db74c0c4ca7c8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 4 Sep 2023 23:44:53 +0200 Subject: [PATCH 291/676] Updated some versions --- macos/Podfile.lock | 20 +++++++++---------- macos/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- pubspec.yaml | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 42c9fce..b38b083 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -19,18 +19,18 @@ PODS: - sqflite (0.0.2): - FlutterMacOS - FMDB (>= 2.7.5) - - sqlite3 (3.41.2): - - sqlite3/common (= 3.41.2) - - sqlite3/common (3.41.2) - - sqlite3/fts5 (3.41.2): + - sqlite3 (3.43.0): + - sqlite3/common (= 3.43.0) + - sqlite3/common (3.43.0) + - sqlite3/fts5 (3.43.0): - sqlite3/common - - sqlite3/perf-threadsafe (3.41.2): + - sqlite3/perf-threadsafe (3.43.0): - sqlite3/common - - sqlite3/rtree (3.41.2): + - sqlite3/rtree (3.43.0): - sqlite3/common - sqlite3_flutter_libs (0.0.1): - FlutterMacOS - - sqlite3 (~> 3.41.2) + - sqlite3 (~> 3.43.0) - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree @@ -87,9 +87,9 @@ SPEC CHECKSUMS: sentry_flutter: 8f0ffd53088e6a4d50c095852c5cad9e4405025c SentryPrivate: 5e3683390f66611fc7c6215e27645873adb55d13 sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea - sqlite3: fd89671d969f3e73efe503ce203e28b016b58f68 - sqlite3_flutter_libs: 00a50503d69f7ab0fe85a5ff25b33082f4df4ce9 - url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451 + sqlite3: 7afcf055d3700254769a4dcba56f27d26b5515c9 + sqlite3_flutter_libs: 03613b0558ba0bb5544aa3ba3d0862c09c7a19b3 + url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 03d00fd..cb14ee0 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -202,7 +202,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 0a0b302..b1bc689 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Date: Mon, 4 Sep 2023 23:44:59 +0200 Subject: [PATCH 292/676] Fixed home charts --- lib/screens/home/chart.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/home/chart.dart b/lib/screens/home/chart.dart index f69f59d..682d5b9 100644 --- a/lib/screens/home/chart.dart +++ b/lib/screens/home/chart.dart @@ -27,7 +27,7 @@ class HomeChart extends StatelessWidget { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - final bool isEmpty = data.any((i) => i == 0); + final bool isEmpty = data.every((i) => i == 0); if (!(appConfigProvider.hideZeroValues == true && isEmpty == true)) { List dateTimes = []; From 67ab96e105d8dda718d21bc0c5fd1a8e088dfe83 Mon Sep 17 00:00:00 2001 From: Adrian English Lord Of The Manor Date: Tue, 5 Sep 2023 17:58:46 +0200 Subject: [PATCH 293/676] Update app_pl.arb kontynuowac od lini 497 --- lib/l10n/app_pl.arb | 270 ++++++++++++++++++++++---------------------- 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 7587f8a..17ddc34 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -358,142 +358,142 @@ "seconds": "{time} sekund", "leaseTimeNotValid": "Czas dzierżawy jest nieaktualny", "restoreConfiguration": "Zresetuj konfiguracjÄ™", - "restoreConfigurationMessage": "Are you sure you want to continue? This will reset all the configuration. This action cannot be undone.", - "changeInterface": "Change interface", - "savingSettings": "Saving settings...", - "settingsSaved": "Settings saved successfully", - "settingsNotSaved": "Settings couldn't be saved", - "restoringConfig": "Restoring configuration...", - "configRestored": "Configuration reseted successfully", - "configNotRestored": "The configuration couldn't be reseted", - "dhcpStatic": "DHCP static leases", - "noDhcpStaticLeases": "No DHCP static leases found", - "deleting": "Deleting...", - "staticLeaseDeleted": "DHCP static lease deleted successfully", - "staticLeaseNotDeleted": "The DHCP static lease could not be deleted", - "deleteStaticLease": "Delete static lease", - "deleteStaticLeaseDescription": "The DHCP static lease will be deleted. This action cannot be reverted.", - "addStaticLease": "Add static lease", - "macAddress": "MAC address", - "macAddressNotValid": "MAC address not valid", - "hostName": "Host name", - "hostNameError": "Host name cannot be empty", - "creating": "Creating...", - "staticLeaseCreated": "DHCP static lease created successfully", - "staticLeaseNotCreated": "The DHCP static lease couldn't be created", - "staticLeaseExists": "The DHCP static lease already exists", - "serverNotConfigured": "Server not configured", - "restoreLeases": "Reset leases", - "restoreLeasesMessage": "Are you sure you want to continue? This will reset all the existing leases. This action cannot be undone.", - "restoringLeases": "Resetting leases...", - "leasesRestored": "Leases reseted successfully", - "leasesNotRestored": "The leases couldn't be reseted", - "dhcpLeases": "DHCP leases", - "noLeases": "No DHCP leases available", - "dnsRewrites": "DNS rewrites", - "dnsRewritesDescription": "Configure custom DNS rules", - "loadingRewriteRules": "Loading rewrite rules...", - "rewriteRulesNotLoaded": "DNS rewrite rules could not be loaded.", - "noRewriteRules": "No DNS rewrite rules", - "answer": "Answer", - "deleteDnsRewrite": "Delete DNS rewrite", - "deleteDnsRewriteMessage": "Are you sure you want to delete this DNS rewrite? This action cannot be undone.", - "dnsRewriteRuleDeleted": "DNS rewrite rule deleted successfully", - "dnsRewriteRuleNotDeleted": "The DNS rewrite rule could not be deleted", - "addDnsRewrite": "Add DNS rewrite", - "addingRewrite": "Adding rewrite...", - "dnsRewriteRuleAdded": "DNS rewrite rule addded successfully", - "dnsRewriteRuleNotAdded": "DNS rewrite rule could not be added", - "logsSettings": "Logs settings", - "enableLog": "Enable log", - "clearLogs": "Clear logs", - "anonymizeClientIp": "Anonymize client IP", - "hours6": "6 hours", - "days30": "30 days", - "days90": "90 days", - "retentionTime": "Retention time", - "selectOneItem": "Select one item", - "logSettingsNotLoaded": "Log settings couldn't be loaded.", - "updatingSettings": "Updating settings...", - "logsConfigUpdated": "Logs settings updated successfully", - "logsConfigNotUpdated": "Logs settings couldn't be updated", - "deletingLogs": "Clearing logs...", - "logsCleared": "Logs cleared successfully", - "logsNotCleared": "Logs could not be cleared", - "runningHomeAssistant": "Running on Home Assistant", - "serverError": "Server error", - "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.", - "noBootstrapDns": "No bootstrap DNS servers added.", - "bootstrapDnsServersInfo": "Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams.", - "privateReverseDnsServers": "Private reverse DNS servers", - "privateReverseDnsServersDescription": "The DNS servers that AdGuard Home uses for local PTR queries. These servers are used to resolve PTR requests for addresses in private IP ranges, for example \"192.168.12.34\", using reverse DNS. If not set, AdGuard Home uses the addresses of the default DNS resolvers of your OS except for the addresses of AdGuard Home itself.", - "reverseDnsDefault": "By default, AdGuard Home uses the following reverse DNS resolvers", - "addItem": "Add item", - "noServerAddressesAdded": "No server addresses added.", - "usePrivateReverseDnsResolvers": "Use private reverse DNS resolvers", - "usePrivateReverseDnsResolversDescription": "Perform reverse DNS lookups for locally served addresses using these upstream servers. If disabled, AdGuard Home responds with NXDOMAIN to all such PTR requests except for clients known from DHCP, /etc/hosts, and so on.", - "enableReverseResolving": "Enable reverse resolving of clients' IP addresses", - "enableReverseResolvingDescription": "Reversely resolve clients' IP addresses into their hostnames by sending PTR queries to corresponding resolvers (private DNS servers for local clients, upstream servers for clients with public IP addresses).", - "dnsServerSettings": "AdGuard Home DNS server settings", - "limitRequestsSecond": "Rate limit per second", - "valueNotNumber": "Value is not a number", - "enableEdns": "Enable EDNS client subnet", - "enableEdnsDescription": "Add the EDNS Client Subnet option (ECS) to upstream requests and log the values sent by the clients in the query log.", - "enableDnssec": "Enable DNSSEC", - "enableDnssecDescription": "Set DNSSEC flag in the outcoming DNS queries and check the result (DNSSEC-enabled resolver is required).", - "disableResolvingIpv6": "Disable resolving of IPv6 addresses", - "disableResolvingIpv6Description": "Drop all DNS queries for IPv6 addresses (type AAAA).", - "blockingMode": "Blocking mode", - "defaultMode": "Default", - "defaultDescription": "Respond with zero IP address (0.0.0.0 for A; :: for AAAA) when blocked by Adblock-style rule; respond with the IP address specified in the rule when blocked by /etc/hosts-style rule", - "refusedDescription": "Respond with REFUSED code", - "nxdomainDescription": "Respond with NXDOMAIN code", + "restoreConfigurationMessage": "Czy na pewno chcesz kontynuować? Spowoduje to zresetowanie caÅ‚ej konfiguracji. Tej czynnoÅ›ci nie można cofnąć.", + "changeInterface": "ZmieÅ„ interfejs", + "savingSettings": "Zapisywanie ustawieÅ„...", + "settingsSaved": "Ustawienia zapisane pomyÅ›lnie", + "settingsNotSaved": "Nie można zapisać ustawieÅ„", + "restoringConfig": "Przywracanie konfiguracji...", + "configRestored": "Konfiguracja zostaÅ‚a zresetowana pomyÅ›lnie", + "configNotRestored": "Nie można zresetować konfiguracji", + "dhcpStatic": "Dzierżawy statyczne DHCP", + "noDhcpStaticLeases": "Nie znaleziono dzierżaw statycznych DHCP", + "deleting": "Usuwanie...", + "staticLeaseDeleted": "Dzierżawa statyczna DHCP zostaÅ‚a pomyÅ›lnie usuniÄ™ta", + "staticLeaseNotDeleted": "Nie można usunąć dzierżawy statycznej DHCP", + "deleteStaticLease": "Usuwanie dzierżawy statycznej...", + "deleteStaticLeaseDescription": "Dzierżawa statyczna DHCP zostanie usuniÄ™ta. Tej akcji nie można cofnąć.", + "addStaticLease": "Dodawanie dzierżawy statycznej", + "macAddress": "Adres MAC", + "macAddressNotValid": "NieprawidÅ‚owy adres MAC", + "hostName": "Nazwa hosta", + "hostNameError": "Nazwa hosta nie może być pusta", + "creating": "Tworzenie...", + "staticLeaseCreated": "Dzierżawa statyczna DHCP utworzona pomyÅ›lnie", + "staticLeaseNotCreated": "Nie można utworzyć dzierżawy statycznej DHCP", + "staticLeaseExists": "Dzierżawa statyczna DHCP już istnieje", + "serverNotConfigured": "Serwer nie jest skonfigurowany", + "restoreLeases": "Resetowanie dzierżaw", + "restoreLeasesMessage": "Czy na pewno chcesz kontynuować? Spowoduje to zresetowanie wszystkich istniejÄ…cych dzierżaw. Tej czynnoÅ›ci nie można cofnąć.", + "restoringLeases": "Resetowanie dzierżaw...", + "leasesRestored": "Dzierżawy zostaÅ‚y pomyÅ›lnie zresetowane", + "leasesNotRestored": "Nie można zresetować dzierżaw", + "dhcpLeases": "Dzierżawy DHCP", + "noLeases": "Brak dostÄ™pnych dzierżaw DHCP", + "dnsRewrites": "Przepisywanie DNS", + "dnsRewritesDescription": "Konfigurowanie niestandardowych reguÅ‚ DNS", + "loadingRewriteRules": "Wczytywanie reguÅ‚ przepisywania...", + "rewriteRulesNotLoaded": "Nie można zaÅ‚adować reguÅ‚ przepisywania DNS.", + "noRewriteRules": "Brak reguÅ‚ przepisywania DNS.", + "answer": "Odpowiedź", + "deleteDnsRewrite": "UsuÅ„ przepisywanie DNS", + "deleteDnsRewriteMessage": "Czy na pewno chcesz usunąć to przepisanie DNS? Tej akcji nie można cofnąć.", + "dnsRewriteRuleDeleted": "ReguÅ‚a przepisywania DNS zostaÅ‚a pomyÅ›lnie usuniÄ™ta", + "dnsRewriteRuleNotDeleted": "Nie można usunąć reguÅ‚y przepisywania DNS", + "addDnsRewrite": "Dodaj przepisywanie DNS", + "addingRewrite": "Dodawanie przepisywania...", + "dnsRewriteRuleAdded": "PomyÅ›lnie dodano regułę przepisywania DNS", + "dnsRewriteRuleNotAdded": "Nie można dodać reguÅ‚y przepisywania DNS", + "logsSettings": "Ustawienia dzienników logów", + "enableLog": "Włącz dziennik logów", + "clearLogs": "Czyszczenie dzienników logów", + "anonymizeClientIp": "Anonimizuj adres IP klienta", + "hours6": "co 6 godzin", + "days30": "co 30 dni", + "days90": "co 90 dni", + "retentionTime": "Czas retencji", + "selectOneItem": "Wybierz jeden element", + "logSettingsNotLoaded": "Nie można zaÅ‚adować ustawieÅ„ dziennika logów.", + "updatingSettings": "Aktualizowanie ustawieÅ„...", + "logsConfigUpdated": "Ustawienia dzienników logów zostaÅ‚y pomyÅ›lnie zaktualizowane", + "logsConfigNotUpdated": "Nie można zaktualizować ustawieÅ„ dzienników logów", + "deletingLogs": "Czyszczenie dzienników logów...", + "logsCleared": "Dzienniki logów wyczyszczone pomyÅ›lnie", + "logsNotCleared": "Nie można wyczyÅ›cić dzienników logów", + "runningHomeAssistant": "DziaÅ‚a na Home Assistant", + "serverError": "Błąd serwera", + "noItems": "Brak elementów do pokazania w tym miejscu", + "dnsSettings": "Ustawienia DNS", + "dnsSettingsDescription": "Konfigurowanie połączenia z serwerami DNS", + "upstreamDns": "NadrzÄ™dne serwery DNS", + "bootstrapDns": "Serwery DNS Bootstrap", + "noUpstreamDns": "Nie dodano nadrzÄ™dnych serwerów DNS.", + "dnsMode": "Tryb DNS", + "noDnsMode": "Nie wybrano trybu DNS", + "loadBalancing": "Równoważenie obciążenia", + "parallelRequests": "RównolegÅ‚e żądania", + "fastestIpAddress": "Najszybszy adres IP", + "loadBalancingDescription": "WysyÅ‚aj zapytania do jednego serwera nadrzÄ™dnego naraz. AdGuard Home wykorzystuje ważony algorytm losowy, aby wybrać serwer, dziÄ™ki czemu najszybszy serwer jest używany częściej.", + "parallelRequestsDescription": "Użyj zapytaÅ„ równolegÅ‚ych, aby przyspieszyć rozwiÄ…zywanie problemów, wysyÅ‚ajÄ…c jednoczeÅ›nie zapytania do wszystkich serwerów nadrzÄ™dnych.", + "fastestIpAddressDescription": "Odpytuj wszystkie serwery DNS i zwracaj najszybszy adres IP spoÅ›ród wszystkich odpowiedzi. Spowalnia to zapytania DNS, ponieważ AdGuard Home musi czekać na odpowiedzi ze wszystkich serwerów DNS, ale poprawia ogólnÄ… łączność.", + "noBootstrapDns": "Nie dodano żadnych serwerów Bootstrap DNS.", + "bootstrapDnsServersInfo": "Serwery DNS Bootstrap sÅ‚użą do rozpoznawania adresów IP programów rozpoznawania nazw DoH/DoT okreÅ›lonych jako nadrzÄ™dne.", + "privateReverseDnsServers": "Prywatne zwrotne serwery DNS", + "privateReverseDnsServersDescription": "Serwery DNS, których AdGuard Home używa do lokalnych zapytaÅ„ PST. Serwery te sÄ… używane na przykÅ‚ad do rozwiÄ…zywania żądaÅ„ PST dotyczÄ…cych adresów w prywatnych zakresach adresów IP \"192.168.12.34\", przy użyciu odwrotnego DNS. JeÅ›li nie jest ustawiony, AdGuard Home używa adresów domyÅ›lnych programów rozpoznawania nazw DNS systemu operacyjnego, z wyjÄ…tkiem adresów samego AdGuard Home.", + "reverseDnsDefault": "DomyÅ›lnie AdGuard Home używa nastÄ™pujÄ…cych programów do rozpoznawania odwrotnych nazw DNS", + "addItem": "Dodaj element", + "noServerAddressesAdded": "Nie dodano adresów serwerów.", + "usePrivateReverseDnsResolvers": "Użyj prywatnych programów do rozpoznawania nazw zwrotnych DNS", + "usePrivateReverseDnsResolversDescription": "Wykonaj odwrotne wyszukiwanie DNS dla adresów obsÅ‚ugiwanych lokalnie przy użyciu tych serwerów nadrzÄ™dnych. JeÅ›li jest wyłączona, AdGuard Home odpowiada NXDOMAIN na wszystkie takie żądania PST, z wyjÄ…tkiem klientów znanych z DHCP, /etc/hosts itd.", + "enableReverseResolving": "Włącz odwrotne rozpoznawanie adresów IP klientów", + "enableReverseResolvingDescription": "Odwrotne rozpoznawanie adresów IP klientów w ich nazwach hostów przez wysyÅ‚anie zapytaÅ„ PTR do odpowiednich programów rozpoznawania nazw (prywatne serwery DNS dla klientów lokalnych, serwery nadrzÄ™dne dla klientów z publicznymi adresami IP).", + "dnsServerSettings": "Ustawienia serwera DNS AdGuard Home", + "limitRequestsSecond": "Limit szybkoÅ›ci na sekundÄ™", + "valueNotNumber": "Wartość nie jest liczbÄ…", + "enableEdns": "Włączanie podsieci klienta EDNS", + "enableEdnsDescription": "Dodaj opcjÄ™ podsieci klienta EDNS (ECS) do żądaÅ„ nadrzÄ™dnych i rejestruj wartoÅ›ci wysyÅ‚ane przez klientów w dzienniku zapytaÅ„.", + "enableDnssec": "Włącz usÅ‚ugÄ™ DNSSEC", + "enableDnssecDescription": "Ustaw flagÄ™ DNSSEC w wychodzÄ…cych zapytaniach DNS i sprawdź wynik (wymagany jest moduÅ‚ rozpoznawania nazw obsÅ‚ugujÄ…cy DNSSEC).", + "disableResolvingIpv6": "Wyłączanie rozpoznawania adresów IPv6", + "disableResolvingIpv6Description": "UsuÅ„ wszystkie zapytania DNS dotyczÄ…ce adresów IPv6 (typ AAAA).", + "blockingMode": "Tryb blokowania", + "defaultMode": "DomyÅ›lny", + "defaultDescription": "Odpowiedz zerowym adresem IP (0.0.0.0 dla A; :: dla AAAA), gdy zostanie zablokowany przez regułę w stylu Adblock; odpowiedz adresem IP okreÅ›lonym w regule, jeÅ›li zostanie zablokowany przez regułę w stylu /etc/hosts", + "refusedDescription": "Odpowiedz kodem REFUSED", + "nxdomainDescription": "Odpowiadanie za pomocÄ… kodu NXDOMAIN", "nullIp": "Null IP", - "nullIpDescription": "Respond with zero IP address (0.0.0.0 for A; :: for AAAA)", - "customIp": "Custom IP", - "customIpDescription": "Respond with a manually set IP address", - "dnsCacheConfig": "DNS cache configuration", - "cacheSize": "Cache size", - "inBytes": "In bytes", - "overrideMinimumTtl": "Override minimum TTL", - "overrideMinimumTtlDescription": "Extend short time-to-live values (seconds) received from the upstream server when caching DNS responses.", - "overrideMaximumTtl": "Override maximum TTL", - "overrideMaximumTtlDescription": "Set a maximum time-to-live value (seconds) for entries in the DNS cache.", - "optimisticCaching": "Optimistic caching", - "optimisticCachingDescription": "Make AdGuard Home respond from the cache even when the entries are expired and also try to refresh them.", - "loadingDnsConfig": "Loading DNS configuration...", - "dnsConfigNotLoaded": "DNS config could not be loaded.", - "blockingIpv4": "Blocking IPv4", - "blockingIpv4Description": "IP address to be returned for a blocked A request", - "blockingIpv6": "Blocking IPv6", - "blockingIpv6Description": "IP address to be returned for a blocked AAAA request", - "invalidIp": "Invalid IP address", - "dnsConfigSaved": "DNS server configuration saved successfully", - "dnsConfigNotSaved": "The DNS server configuration could not be saved", - "savingConfig": "Saving configuration...", - "someValueNotValid": "Some value is not valid", - "upstreamDnsDescription": "Configure upstream servers and DNS mode", - "bootstrapDnsDescription": "Configure the bootstrap DNS servers", - "privateReverseDnsDescription": "Configure custom DNS resolvers and enable private reverse DNS resolving", - "dnsServerSettingsDescription": "Configure a rate limit, the blocking mode and more", - "dnsCacheConfigDescription": "Configure how the server should manage the DNS cache", - "comment": "Comment", - "address": "Address", - "commentsDescription": "Comments are always preceded by #. You don't have to add it, it will be added automatically.", - "encryptionSettings": "Encryption settings", + "nullIpDescription": "Odpowiedz, podajÄ…c zerowy adres IP (0.0.0.0 dla A; :: dla AAAA)", + "customIp": "Niestandardowy adres IP", + "customIpDescription": "Odpowiadanie przy użyciu rÄ™cznie ustawionego adresu IP", + "dnsCacheConfig": "Konfiguracja pamiÄ™ci podrÄ™cznej DNS", + "cacheSize": "Rozmiar pamiÄ™ci podrÄ™cznej", + "inBytes": "W bajtach", + "overrideMinimumTtl": "ZastÄ…p minimalny czas TTL", + "overrideMinimumTtlDescription": "WydÅ‚użanie wartoÅ›ci krótkiego czasu wygaÅ›niÄ™cia (sekund) odbieranych z serwera nadrzÄ™dnego podczas buforowania odpowiedzi DNS.", + "overrideMaximumTtl": "ZastÄ…p maksymalne ustawienie TTL", + "overrideMaximumTtlDescription": "Ustaw maksymalnÄ… wartość czasu wygaÅ›niÄ™cia (sekundy) dla wpisów w pamiÄ™ci podrÄ™cznej DNS.", + "optimisticCaching": "Optymistyczne buforowanie", + "optimisticCachingDescription": "Spraw, aby AdGuard Home odpowiadaÅ‚ z pamiÄ™ci podrÄ™cznej, nawet gdy wpisy wygasÅ‚y, a także spróbuj je odÅ›wieżyć.", + "loadingDnsConfig": "Åadowanie konfiguracji DNS...", + "dnsConfigNotLoaded": "Nie można zaÅ‚adować konfiguracji DNS.", + "blockingIpv4": "Blokowanie protokoÅ‚u IPv4", + "blockingIpv4Description": "Adres IP do zwrócenia w przypadku zablokowanego żądania A", + "blockingIpv6": "Blokowanie protokoÅ‚u IPv6", + "blockingIpv6Description": "Adres IP, który ma zostać zwrócony w przypadku zablokowanego żądania AAAA", + "invalidIp": "NieprawidÅ‚owy adres IP", + "dnsConfigSaved": "Konfiguracja serwera DNS zapisana pomyÅ›lnie", + "dnsConfigNotSaved": "Nie można zapisać konfiguracji serwera DNS", + "savingConfig": "Zapisywanie konfiguracji...", + "someValueNotValid": "Niektóre wartoÅ›ci sÄ… nieprawidÅ‚owe", + "upstreamDnsDescription": "Konfigurowanie serwerów nadrzÄ™dnych i trybu DNS", + "bootstrapDnsDescription": "Konfigurowanie serwerów DNS Å‚adowania poczÄ…tkowego", + "privateReverseDnsDescription": "Konfigurowanie niestandardowych programów rozpoznawania nazw DNS i włączanie prywatnego rozpoznawania zwrotnej domeny DNS", + "dnsServerSettingsDescription": "Konfigurowanie limitu szybkoÅ›ci, trybu blokowania i innych funkcji", + "dnsCacheConfigDescription": "Konfigurowanie sposobu zarzÄ…dzania pamiÄ™ciÄ… podrÄ™cznÄ… DNS przez serwer", + "comment": "Komentarz", + "address": "Adres", + "commentsDescription": "Komentarze sÄ… zawsze poprzedzone znakiem #. Nie musisz go dodawać, zostanie dodany automatycznie.", + "encryptionSettings": "Ustawienia szyfrowania", "encryptionSettingsDescription": "Encryption (HTTPS/QUIC/TLS) support", "loadingEncryptionSettings": "Loading encryption settings...", "encryptionSettingsNotLoaded": "Encryption settings couldn't be loaded.", From 2e2308027658bad87239466bed64fb8a7ea89fc4 Mon Sep 17 00:00:00 2001 From: Adrian English Lord Of The Manor Date: Thu, 7 Sep 2023 16:45:16 +0200 Subject: [PATCH 294/676] Update app_pl.arb kontynuowac od 586 --- lib/l10n/app_pl.arb | 176 ++++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 17ddc34..d689e19 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -494,94 +494,94 @@ "address": "Adres", "commentsDescription": "Komentarze sÄ… zawsze poprzedzone znakiem #. Nie musisz go dodawać, zostanie dodany automatycznie.", "encryptionSettings": "Ustawienia szyfrowania", - "encryptionSettingsDescription": "Encryption (HTTPS/QUIC/TLS) support", - "loadingEncryptionSettings": "Loading encryption settings...", - "encryptionSettingsNotLoaded": "Encryption settings couldn't be loaded.", - "enableEncryption": "Enable encryption", - "enableEncryptionTypes": "HTTPS, DNS-over-HTTPS, and DNS-over-TLS", - "enableEncryptionDescription": "If encryption is enabled, AdGuard Home admin interface will work over HTTPS, and the DNS server will listen for requests over DNS-over-HTTPS and DNS-over-TLS.", - "serverConfiguration": "Server configuration", - "domainName": "Domain name", - "domainNameDescription": "If set, AdGuard Home detects ClientIDs, responds to DDR queries, and performs additional connection validations. If not set, these features are disabled. Must match one of the DNS Names in the certificate.", - "redirectHttps": "Redirect to HTTPS automatically", - "httpsPort": "HTTPS port", - "tlsPort": "DNS-over-TLS port", - "dnsOverQuicPort": "DNS-over-QUIC port", - "certificates": "Certificates", - "certificatesDescription": "In order to use encryption, you need to provide a valid SSL certificates chain for your domain. You can get a free certificate on letsencrypt.org or you can buy it from one of the trusted Certificate Authorities.", - "certificateFilePath": "Set a certificates file path", - "pasteCertificateContent": "Paste the certificates contents", - "certificatePath": "Certificate path", - "certificateContent": "Certificate content", - "privateKey": "Private key", - "privateKeyFile": "Set a private key file", - "pastePrivateKey": "Paste the private key contents", - "usePreviousKey": "Use the previously saved key", - "privateKeyPath": "Private key path", - "invalidCertificate": "Invalid certificate", - "invalidPrivateKey": "Invalid private key", - "validatingData": "Validating data", - "dataValid": "Data is valid", - "dataNotValid": "Data not valid", - "encryptionConfigSaved": "Encryption configuration saved successfully", - "encryptionConfigNotSaved": "Encryption configuration could not be saved", - "configError": "Configuration error", - "enterOnlyCertificate": "Enter only the certificate. Do not input the ---BEGIN--- and ---END--- lines.", - "enterOnlyPrivateKey": "Enter only the key. Do not input the ---BEGIN--- and ---END--- lines.", - "noItemsSearch": "No items for that search.", - "clearSearch": "Clear search", - "exitSearch": "Exit search", - "searchClients": "Search clients", - "noClientsSearch": "No clients with that search.", - "customization": "Customization", - "customizationDescription": "Customize this application", - "color": "Color", - "useDynamicTheme": "Use dynamic theme", - "red": "Red", - "green": "Green", - "blue": "Blue", - "yellow": "Yellow", - "orange": "Orange", - "brown": "Brown", - "cyan": "Cyan", - "purple": "Purple", - "pink": "Pink", - "deepOrange": "Deep orange", - "indigo": "Indigo", - "useThemeColorStatus": "Use theme color for status", - "useThemeColorStatusDescription": "Replaces green and red status colors with theme color and grey", - "invalidCertificateChain": "Invalid certificate chain", - "validCertificateChain": "Valid certificate chain", - "subject": "Subject", - "issuer": "Issuer", - "expires": "Expires", - "validPrivateKey": "Valid private key", - "expirationDate": "Expiration date", - "keysNotMatch": "Invalid certificate or key: tls: private key does not match public key", - "timeLogs": "Time on logs", - "timeLogsDescription": "Show processing time on logs list", - "hostNames": "Host names", - "keyType": "Key type", - "updateAvailable": "Update available", - "installedVersion": "Installed version", - "newVersion": "New version", - "source": "Source", - "downloadUpdate": "Download update", - "download": "Download", - "doNotRememberAgainUpdate": "Do not remember again for this version", - "downloadingUpdate": "Downloading", - "completed": "completed", - "permissionNotGranted": "Permission not granted", - "inputSearchTerm": "Input a search term.", - "answers": "Answers", - "copyClipboard": "Copy to clipboard", - "domainCopiedClipboard": "Domain copied to the clipboard", - "clearDnsCache": "Clear DNS cache", - "clearDnsCacheMessage": "Are you sure you want to clear the DNS cache?", - "dnsCacheCleared": "DNS cache cleared successfully", - "clearingDnsCache": "Clearing cache...", - "dnsCacheNotCleared": "DNS cache couldn't be cleared", - "clientsSelected": "clients selected", + "encryptionSettingsDescription": "ObsÅ‚uga szyfrowania (HTTPS/QUIC/TLS)", + "loadingEncryptionSettings": "Åadowanie ustawieÅ„ szyfrowania...", + "encryptionSettingsNotLoaded": "Nie można zaÅ‚adować ustawieÅ„ szyfrowania.", + "enableEncryption": "Włącz szyfrowanie", + "enableEncryptionTypes": "HTTPS, DNS przez HTTPS i DNS przez TLS", + "enableEncryptionDescription": "JeÅ›li szyfrowanie jest włączone, interfejs administratora AdGuard Home bÄ™dzie dziaÅ‚aÅ‚ przez HTTPS, a serwer DNS bÄ™dzie nasÅ‚uchiwaÅ‚ żądaÅ„ przez DNS przez HTTPS i DNS przez TLS.", + "serverConfiguration": "Konfiguracja serwera", + "domainName": "Nazwa domeny", + "domainNameDescription": "JeÅ›li jest ustawiony, AdGuard Home wykrywa identyfikatory klientów, odpowiada na zapytania DDR i wykonuje dodatkowe walidacje połączeÅ„. JeÅ›li te funkcje nie sÄ… ustawione, sÄ… wyłączone. Musi być zgodna z jednÄ… z nazw DNS w certyfikacie.", + "redirectHttps": "Automatyczne przekierowywanie do protokoÅ‚u HTTPS", + "httpsPort": "Port HTTPS", + "tlsPort": "DNS przez port TLS", + "dnsOverQuicPort": "DNS przez port QUIC", + "certificates": "Certifikaty", + "certificatesDescription": "Aby korzystać z szyfrowania, musisz podać prawidÅ‚owy Å‚aÅ„cuch certyfikatów SSL dla swojej domeny. Możesz uzyskać bezpÅ‚atny certyfikat na letsencrypt.org lub kupić go w jednym z zaufanych urzÄ™dów certyfikacji.", + "certificateFilePath": "Ustaw Å›cieżkÄ™ pliku certyfikatów", + "pasteCertificateContent": "Wklejanie zawartoÅ›ci certyfikatów", + "certificatePath": "Åšcieżka certyfikatu", + "certificateContent": "Zawartość certyfikatu", + "privateKey": "Klucz prywatny", + "privateKeyFile": "Ustaw plik klucza prywatnego", + "pastePrivateKey": "Wklejanie zawartoÅ›ci klucza prywatnego", + "usePreviousKey": "Użyj wczeÅ›niej zapisanego klucza", + "privateKeyPath": "Åšcieżka klucza prywatnego", + "invalidCertificate": "NieprawidÅ‚owy certyfikat", + "invalidPrivateKey": "NieprawidÅ‚owy klucz prywatny", + "validatingData": "Sprawdzanie poprawnoÅ›ci danych", + "dataValid": "Dane prawidÅ‚owe", + "dataNotValid": "Dane nieprawidÅ‚owe", + "encryptionConfigSaved": "Konfiguracja szyfrowania zapisana pomyÅ›lnie", + "encryptionConfigNotSaved": "Nie można zapisać konfiguracji szyfrowania", + "configError": "Błąd konfiguracji", + "enterOnlyCertificate": "Wprowadź tylko certyfikat. Nie wpisuj linii ---BEGIN--- i ---END---.", + "enterOnlyPrivateKey": "Wprowadź tylko klucz. Nie wpisuj linii ---BEGIN--- i ---END---.", + "noItemsSearch": "Brak elementów dla tego wyszukiwania.", + "clearSearch": "Wyczyść wyszukiwanie", + "exitSearch": "ZakoÅ„cz wyszukiwanie", + "searchClients": "Wyszukaj klientów", + "noClientsSearch": "Brak klientów dla tego wyszukiwania.", + "customization": "Personalizacja", + "customizationDescription": Dostosuj tÄ™ aplikacjÄ™", + "color": "Kolor", + "useDynamicTheme": "Użyj motywu dynamicznego", + "red": "Czerwony", + "green": "Zielony", + "blue": "Niebieski", + "yellow": "Żółty", + "orange": "PomaraÅ„czowy", + "brown": "BrÄ…zowy", + "cyan": "Błękitny", + "purple": "Fioletowy", + "pink": "Różowy", + "deepOrange": "Głęboki pomaraÅ„czowy", + "indigo": "Indygo", + "useThemeColorStatus": "Użyj koloru motywu dla statusu", + "useThemeColorStatusDescription": "ZastÄ™puje zielone i czerwone kolory statusu kolorami motywu i szaroÅ›ciÄ…", + "invalidCertificateChain": "NieprawidÅ‚owy Å‚aÅ„cuch certyfikatów", + "validCertificateChain": "PrawidÅ‚owy Å‚aÅ„cuch certyfikatów", + "subject": "Temat", + "issuer": "Wydawca", + "expires": "Wygasa", + "validPrivateKey": "PrawidÅ‚owy klucz prywatny", + "expirationDate": "Data ważnoÅ›ci", + "keysNotMatch": "NieprawidÅ‚owy certyfikat lub klucz: TLS: klucz prywatny nie jest zgodny z kluczem publicznym, + "timeLogs": "Czas w dziennikach logów", + "timeLogsDescription": "Pokaż czas przetwarzania na liÅ›cie dzienników logów", + "hostNames": "Nazwy hostów", + "keyType": "Typ klucza", + "updateAvailable": "DostÄ™pna aktualizacja", + "installedVersion": "Zainstalowana wersja", + "newVersion": "Nowa wersja", + "source": "ŹródÅ‚o", + "downloadUpdate": "Pobierz aktualizacjÄ™", + "download": "Pobierz", + "doNotRememberAgainUpdate": "Nie pamiÄ™tam ponownie dla tej wersji", + "downloadingUpdate": "Pobieranie aktualizacji", + "completed": "ukoÅ„czone", + "permissionNotGranted": "Pozwolenie nie zostaÅ‚o udzielone", + "inputSearchTerm": "Wprowadź wyszukiwany termin.", + "answers": "Odpowiedzi", + "copyClipboard": "Kopiuj do schowka", + "domainCopiedClipboard": "Domena skopiowana do schowka", + "clearDnsCache": "Wyczyść pamięć podrÄ™cznÄ… DNS", + "clearDnsCacheMessage": "Czy na pewno chcesz wyczyÅ›cić pamięć podrÄ™cznÄ… DNS?", + "dnsCacheCleared": "Pamięć podrÄ™czna DNS zostaÅ‚a pomyÅ›lnie wyczyszczona", + "clearingDnsCache": "Czyszczenie pamiÄ™ci podrÄ™cznej...", + "dnsCacheNotCleared": "Nie można wyczyÅ›cić pamiÄ™ci podrÄ™cznej DNS", + "clientsSelected": "Wybrani klienci", "invalidDomain": "Invalid domain", "loadingBlockedServicesList": "Loading blocked services list...", "blockedServicesListNotLoaded": "The blocked services list could not be loaded", From 100099ad5f230bb025b85a83963b2ea25e6c333e Mon Sep 17 00:00:00 2001 From: Adrian English Lord Of The Manor Date: Fri, 8 Sep 2023 16:00:38 +0200 Subject: [PATCH 295/676] Update app_pl.arb ostateczna wersja --- lib/l10n/app_pl.arb | 144 ++++++++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index d689e19..7562da8 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -582,76 +582,76 @@ "clearingDnsCache": "Czyszczenie pamiÄ™ci podrÄ™cznej...", "dnsCacheNotCleared": "Nie można wyczyÅ›cić pamiÄ™ci podrÄ™cznej DNS", "clientsSelected": "Wybrani klienci", - "invalidDomain": "Invalid domain", - "loadingBlockedServicesList": "Loading blocked services list...", - "blockedServicesListNotLoaded": "The blocked services list could not be loaded", - "error": "Error", - "updates": "Updates", - "updatesDescription": "Update the AdGuard Home server", - "updateNow": "Update now", - "currentVersion": "Current version", - "requestStartUpdateFailed": "Request to start update failed", - "requestStartUpdateSuccessful": "Request to start update successfull", - "serverUpdated": "Server is updated", - "unknownStatus": "Unknown status", - "checkingUpdates": "Checking updates...", - "checkUpdates": "Check updates", - "requestingUpdate": "Requesting update...", - "autoupdateUnavailable": "Autoupdate unavailable", - "autoupdateUnavailableDescription": "The autoupdate service is not available for this server. It could be because the server is running on a Docker container. You have to update your server manually.", - "minute": "{time} minute", - "minutes": "{time} minutes", - "hour": "{time} hour", - "hours": "{time} hours", - "remainingTime": "Remaining time", - "safeSearchSettings": "Safe search settings", - "loadingSafeSearchSettings": "Loading safe search settings...", - "safeSearchSettingsNotLoaded": "Error when loading safe search settings.", - "loadingLogsSettings": "Loading logs settings...", - "selectOptionLeftColumn": "Select an option of the left column", - "selectClientLeftColumn": "Select a client of the left column", - "disableList": "Disable list", - "enableList": "Enable list", - "screens": "Screens", - "copiedClipboard": "Copied to clipboard", - "seeDetails": "See details", - "listNotAvailable": "List not available", - "copyListUrl": "Copy list URL", - "listUrlCopied": "List URL copied to the clipboard", - "unsupportedVersion": "Unsupported version", - "unsupprtedVersionMessage": "The support for your server version {version} is not guaranteed. This application may have some issues working with that server version.\n\nAdGuard Home Manager is designed to work with the stable releases of the AdGuard Home server. It may work with alpha and beta releases, but the compatibility is not guaranteed and the app may have some issues working with that versions.", - "iUnderstand": "I understand", - "appUpdates": "Application updates", - "usingLatestVersion": "You are using the latest version", - "ipLogs": "IP on logs", - "ipLogsDescription": "Show always IP address on logs instead of client name", - "application": "Application", - "combinedChart": "Combined chart", - "combinedChartDescription": "Combine all charts into one", - "statistics": "Statistics", - "errorLoadFilters": "Error when loading filters.", - "clientRemovedSuccessfully": "Client removed successfully.", - "editRewriteRule": "Edit rewrite rule", - "dnsRewriteRuleUpdated": "DNS rewrite rule updated successfully", - "dnsRewriteRuleNotUpdated": "DNS rewrite rule could not be updated", - "updatingRule": "Updating rule...", - "serverUpdateNeeded": "Server update needed", - "updateYourServer": "Update your AdGuard Home server to {version} or greater to use this feature.", - "january": "January", - "february": "February", - "march": "March", - "april": "April", - "may": "May", - "june": "June", - "july": "July", - "august": "August", - "september": "September", - "october": "October", - "november": "November", - "december": "December", - "malwarePhising": "Malware/phising", - "queries": "Queries", - "adultSites": "Adult sites", - "quickFilters": "Quick filters", - "searchDomainInternet": "Search domain on the Internet" + "invalidDomain": "NieprawidÅ‚owa domena", + "loadingBlockedServicesList": "Åadowanie listy zablokowanych usÅ‚ug...", + "blockedServicesListNotLoaded": "Nie można zaÅ‚adować listy zablokowanych usÅ‚ug", + "error": "Błąd", + "updates": "Aktualizacje", + "updatesDescription": "Zaktualizuj serwer AdGuard Home", + "updateNow": "Aktualizuj teraz", + "currentVersion": "Aktualna wersja", + "requestStartUpdateFailed": "Żądanie rozpoczÄ™cia aktualizacji nie powiodÅ‚o siÄ™", + "requestStartUpdateSuccessful": "Żądanie rozpoczÄ™cia aktualizacji powiodÅ‚o siÄ™", + "serverUpdated": "Serwer jest aktualizowany", + "unknownStatus": "Status nieznany", + "checkingUpdates": "Sprawdzanie aktualizacji...", + "checkUpdates": "Sprawdź aktualizacje", + "requestingUpdate": "Żądanie aktualizacji...", + "autoupdateUnavailable": "Automatyczna aktualizacja jest niedostÄ™pna", + "autoupdateUnavailableDescription": "UsÅ‚uga automatycznej aktualizacji nie jest dostÄ™pna dla tego serwera. Może to być spowodowane tym, że serwer dziaÅ‚a w kontenerze Docker. Musisz zaktualizować serwer rÄ™cznie.", + "minute": "{time} minut", + "minutes": "{time} minut", + "hour": "{time} godzina", + "hours": "{time} godzin", + "remainingTime": "PozostaÅ‚y czas", + "safeSearchSettings": "Ustawienia bezpiecznego wyszukiwania", + "loadingSafeSearchSettings": "Åadowanie ustawieÅ„ bezpiecznego wyszukiwania...", + "safeSearchSettingsNotLoaded": "Błąd podczas Å‚adowania ustawieÅ„ bezpiecznego wyszukiwania.", + "loadingLogsSettings": "Åadowanie ustawieÅ„ dzienników logów...", + "selectOptionLeftColumn": "Wybierz opcjÄ™ lewej kolumny", + "selectClientLeftColumn": "Wybierz klienta z lewej kolumny", + "disableList": "Wyłącz listÄ™", + "enableList": "Włącz listÄ™", + "screens": "Ekrany", + "copiedClipboard": "Skopiowane do schowka", + "seeDetails": "Zobacz szczegóły", + "listNotAvailable": "Lista niedostÄ™pna", + "copyListUrl": "Skopiuj adres URL listy", + "listUrlCopied": "Adres URL listy skopiowany do schowka", + "unsupportedVersion": "NieobsÅ‚ugiwana wersja", + "unsupprtedVersionMessage": "Nie gwarantuje siÄ™ wsparcia dla wersji serwera {version}. Ta aplikacja może mieć pewne problemy z dziaÅ‚aniem na tej wersji serwera.\n\nAdGuard Home Manager zostaÅ‚ zaprojektowany do współpracy ze stabilnymi wersjami serwera AdGuard Home. Może dziaÅ‚ać z wersjami alfa i beta, ale kompatybilność nie jest gwarantowana, a aplikacja może mieć pewne problemy z dziaÅ‚aniem w tych wersjach.", + "iUnderstand": "Rozumiem", + "appUpdates": "Aktualizacje aplikacji", + "usingLatestVersion": "Używasz najnowszej wersji", + "ipLogs": "IP w dziennikach logów", + "ipLogsDescription": "Pokaż zawsze adres IP w dziennikach logów zamiast nazwy klienta", + "application": "Aplikacja", + "combinedChart": "Wykres łączony", + "combinedChartDescription": "Połącz wszystkie wykresy w jeden", + "statistics": "Statystyka", + "errorLoadFilters": "Błąd podczas Å‚adowania filtrów.", + "clientRemovedSuccessfully": "Klient zostaÅ‚ pomyÅ›lnie usuniÄ™ty.", + "editRewriteRule": "Edytowanie reguÅ‚y przepisywania", + "dnsRewriteRuleUpdated": "ReguÅ‚a przepisywania DNS zostaÅ‚a pomyÅ›lnie zaktualizowana", + "dnsRewriteRuleNotUpdated": "Nie można zaktualizować reguÅ‚y przepisywania DNS", + "updatingRule": "AktualizujÄ™ regułę...", + "serverUpdateNeeded": "Wymagana aktualizacja serwera", + "updateYourServer": "Aby móc korzystać z tej funkcji, zaktualizuj serwer AdGuard Home do wersji {version} lub nowszej.", + "january": "StyczeÅ„", + "february": "Luty", + "march": "Mrzec", + "april": "KwiecieÅ„", + "may": "Maj", + "june": "Czerwiec", + "july": "Lipiec", + "august": "SierpieÅ„", + "september": "WrzesieÅ„", + "october": "Październik", + "november": "Listopad", + "december": "GrudzieÅ„", + "malwarePhising": "ZÅ‚oÅ›liwe oprogramowanie / wyÅ‚udzanie informacji", + "queries": "Zapytania", + "adultSites": "Strony dla dorosÅ‚ych", + "quickFilters": "Szybkie filtry", + "searchDomainInternet": "Wyszukaj domenÄ™ w Internecie" } From 2f40415ada89ec4ca91967774efc653b5ce706ce Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Sep 2023 20:51:05 +0200 Subject: [PATCH 296/676] Added polish language --- lib/l10n/app_pl.arb | 4 ++-- lib/main.dart | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 7562da8..a3dabaa 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -534,7 +534,7 @@ "searchClients": "Wyszukaj klientów", "noClientsSearch": "Brak klientów dla tego wyszukiwania.", "customization": "Personalizacja", - "customizationDescription": Dostosuj tÄ™ aplikacjÄ™", + "customizationDescription": "Dostosuj tÄ™ aplikacjÄ™", "color": "Kolor", "useDynamicTheme": "Użyj motywu dynamicznego", "red": "Czerwony", @@ -557,7 +557,7 @@ "expires": "Wygasa", "validPrivateKey": "PrawidÅ‚owy klucz prywatny", "expirationDate": "Data ważnoÅ›ci", - "keysNotMatch": "NieprawidÅ‚owy certyfikat lub klucz: TLS: klucz prywatny nie jest zgodny z kluczem publicznym, + "keysNotMatch": "NieprawidÅ‚owy certyfikat lub klucz: TLS: klucz prywatny nie jest zgodny z kluczem publicznym", "timeLogs": "Czas w dziennikach logów", "timeLogsDescription": "Pokaż czas przetwarzania na liÅ›cie dzienników logów", "hostNames": "Nazwy hostów", diff --git a/lib/main.dart b/lib/main.dart index 6d2f1a3..a894dc6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -228,7 +228,8 @@ class _MainState extends State
{ Locale('en', ''), Locale('es', ''), Locale('zh', ''), - Locale('zh', 'CN') + Locale('zh', 'CN'), + Locale('pl', '') ], scaffoldMessengerKey: scaffoldMessengerKey, builder: (context, child) { From a38c9bf4b0252ffdbf7c20292ba1b3d32fcdca40 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Sep 2023 21:17:01 +0200 Subject: [PATCH 297/676] Database preparations for new features --- lib/config/home_top_items_default_order.dart | 11 +++++ lib/constants/enums.dart | 3 +- lib/providers/app_config_provider.dart | 51 ++++++++++++++++++++ lib/services/db/database.dart | 30 ++++++++++-- 4 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 lib/config/home_top_items_default_order.dart diff --git a/lib/config/home_top_items_default_order.dart b/lib/config/home_top_items_default_order.dart new file mode 100644 index 0000000..1f49093 --- /dev/null +++ b/lib/config/home_top_items_default_order.dart @@ -0,0 +1,11 @@ +import 'dart:convert'; + +import 'package:adguard_home_manager/constants/enums.dart'; + +final List homeTopItemsDefaultOrder = [ + HomeTopItems.queriedDomains, + HomeTopItems.blockedDomains, + HomeTopItems.recurrentClients +]; + +final String homeTopItemsDefaultOrderString = jsonEncode(homeTopItemsDefaultOrder); \ No newline at end of file diff --git a/lib/constants/enums.dart b/lib/constants/enums.dart index 58f5509..fed648e 100644 --- a/lib/constants/enums.dart +++ b/lib/constants/enums.dart @@ -1 +1,2 @@ -enum LoadStatus { loading, loaded, error } \ No newline at end of file +enum LoadStatus { loading, loaded, error } +enum HomeTopItems { queriedDomains, blockedDomains, recurrentClients } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 7aeb917..eefab88 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -1,10 +1,15 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/scheduler.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:store_checker/store_checker.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sqflite/sqlite_api.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/config/home_top_items_default_order.dart'; import 'package:adguard_home_manager/models/github_release.dart'; import 'package:adguard_home_manager/services/db/queries.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; @@ -31,6 +36,8 @@ class AppConfigProvider with ChangeNotifier { int _selectedClientsTab = 0; int _selectedFiltersTab = 0; + List _homeTopItemsOrder = homeTopItemsDefaultOrder; + final List _logs = []; int _overrideSslCheck = 0; @@ -151,6 +158,10 @@ class AppConfigProvider with ChangeNotifier { return _installationSource; } + List get homeTopItemsOrder { + return _homeTopItemsOrder; + } + void setDbInstance(Database db) { _dbInstance = db; } @@ -353,6 +364,22 @@ class AppConfigProvider with ChangeNotifier { } } + Future setHomeTopItemsOrder(List order) async { + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'homeTopItemsOrder', + value: jsonEncode(order) + ); + if (updated == true) { + _homeTopItemsOrder = order; + notifyListeners(); + return true; + } + else { + return false; + } + } + Future setDoNotRememberVersion(String value) async { final updated = await updateConfigQuery( db: _dbInstance!, @@ -373,6 +400,30 @@ class AppConfigProvider with ChangeNotifier { _doNotRememberVersion = dbData['doNotRememberVersion']; _showIpLogs = dbData['showIpLogs'] ?? 0; _combinedChartHome = dbData['combinedChart'] ?? 0; + if (dbData['homeTopItemsOrder'] != null) { + try { + _homeTopItemsOrder = List.from( + List.from(jsonDecode(dbData['homeTopItemsOrder'])).map((e) { + switch (e) { + case 'queriedDomains': + return HomeTopItems.queriedDomains; + + case 'blockedDomains': + return HomeTopItems.blockedDomains; + + case 'recurrentClients': + return HomeTopItems.recurrentClients; + + default: + return null; + } + }).where((e) => e != null).toList() + ); + } catch (e) { + Sentry.captureException(e); + _homeTopItemsOrder = homeTopItemsDefaultOrder; + } + } _dbInstance = dbInstance; notifyListeners(); diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index 9a9ac18..66bd269 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -1,5 +1,7 @@ import 'package:sqflite/sqflite.dart'; +import 'package:adguard_home_manager/config/home_top_items_default_order.dart'; + Future> loadDb(bool acceptsDynamicTheme) async { List>? servers; List>? appConfig; @@ -102,13 +104,25 @@ Future> loadDb(bool acceptsDynamicTheme) async { } } + Future upgradeDbToV9(Database db) async { + await db.execute("ALTER TABLE appConfig ADD COLUMN hideServerAddress NUMERIC"); + await db.execute("ALTER TABLE appConfig ADD COLUMN homeTopItemsOrder TEXT"); + await db.execute("UPDATE appConfig SET hideServerAddress = 0, homeTopItemsOrder = '$homeTopItemsDefaultOrderString'"); + + await db.transaction((txn) async{ + await txn.rawQuery( + 'SELECT * FROM appConfig', + ); + }); + } + Database db = await openDatabase( 'adguard_home_manager.db', - version: 8, + version: 9, onCreate: (Database db, int version) async { await db.execute("CREATE TABLE servers (id TEXT PRIMARY KEY, name TEXT, connectionMethod TEXT, domain TEXT, path TEXT, port INTEGER, user TEXT, password TEXT, defaultServer INTEGER, authToken TEXT, runningOnHa INTEGER)"); - await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showTimeLogs NUMERIC, showIpLogs NUMERIC, combinedChart NUMERIC, doNotRememberVersion TEXT)"); - await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs, combinedChart) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0, 0)"); + await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showTimeLogs NUMERIC, showIpLogs NUMERIC, combinedChart NUMERIC, doNotRememberVersion TEXT, hideServerAddress NUMERIC, homeTopItemsOrder TEXT)"); + await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs, combinedChart, hideServerAddress, homeTopItemsOrder) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0, 0, 0, $homeTopItemsDefaultOrderString)"); }, onUpgrade: (Database db, int oldVersion, int newVersion) async { if (oldVersion == 1) { @@ -119,6 +133,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV6(db); await upgradeDbToV7(db); await upgradeDbToV8(db); + await upgradeDbToV9(db); } if (oldVersion == 2) { await upgradeDbToV3(db); @@ -127,6 +142,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV6(db); await upgradeDbToV7(db); await upgradeDbToV8(db); + await upgradeDbToV9(db); } if (oldVersion == 3) { await upgradeDbToV4(db); @@ -134,24 +150,32 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV6(db); await upgradeDbToV7(db); await upgradeDbToV8(db); + await upgradeDbToV9(db); } if (oldVersion == 4) { await upgradeDbToV5(db); await upgradeDbToV6(db); await upgradeDbToV7(db); await upgradeDbToV8(db); + await upgradeDbToV9(db); } if (oldVersion == 5) { await upgradeDbToV6(db); await upgradeDbToV7(db); await upgradeDbToV8(db); + await upgradeDbToV9(db); } if (oldVersion == 6) { await upgradeDbToV7(db); await upgradeDbToV8(db); + await upgradeDbToV9(db); } if (oldVersion == 7) { await upgradeDbToV8(db); + await upgradeDbToV9(db); + } + if (oldVersion == 8) { + await upgradeDbToV9(db); } }, onOpen: (Database db) async { From d967399b64d768b341c656971724b90ba3767beb Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Sep 2023 21:25:21 +0200 Subject: [PATCH 298/676] Added hide server address feature --- lib/l10n/app_en.arb | 4 +++- lib/l10n/app_es.arb | 4 +++- lib/providers/app_config_provider.dart | 24 ++++++++++++++++++++++ lib/screens/home/appbar.dart | 22 +++++++++++--------- lib/screens/settings/general_settings.dart | 22 ++++++++++++++++++++ 5 files changed, 64 insertions(+), 12 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f203286..38526a3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -653,5 +653,7 @@ "queries": "Queries", "adultSites": "Adult sites", "quickFilters": "Quick filters", - "searchDomainInternet": "Search domain on the Internet" + "searchDomainInternet": "Search domain on the Internet", + "hideServerAddress": "Hide server address", + "hideServerAddressDescription": "Hides the server address on the home screen" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index ab71f10..383a4b0 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -653,5 +653,7 @@ "queries": "Peticiones", "adultSites": "Sitios de adultos", "quickFilters": "Filtros rápidos", - "searchDomainInternet": "Buscar dominio en internet" + "searchDomainInternet": "Buscar dominio en internet", + "hideServerAddress": "Ocultar dirección del servidor", + "hideServerAddressDescription": "Oculta la dirección del servidor en la pantalla de inicio" } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index eefab88..cf4fc0e 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -38,6 +38,8 @@ class AppConfigProvider with ChangeNotifier { List _homeTopItemsOrder = homeTopItemsDefaultOrder; + int _hideServerAddress = 0; + final List _logs = []; int _overrideSslCheck = 0; @@ -162,6 +164,10 @@ class AppConfigProvider with ChangeNotifier { return _homeTopItemsOrder; } + bool get hideServerAddress { + return _hideServerAddress == 1 ? true : false; + } + void setDbInstance(Database db) { _dbInstance = db; } @@ -380,6 +386,23 @@ class AppConfigProvider with ChangeNotifier { } } + Future setHideServerAddress(bool value) async { + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'hideServerAddress', + value: value == true ? 1 : 0 + ); + if (updated == true) { + _hideServerAddress = value == true ? 1 : 0; + notifyListeners(); + return true; + } + else { + return false; + } + } + + Future setDoNotRememberVersion(String value) async { final updated = await updateConfigQuery( db: _dbInstance!, @@ -400,6 +423,7 @@ class AppConfigProvider with ChangeNotifier { _doNotRememberVersion = dbData['doNotRememberVersion']; _showIpLogs = dbData['showIpLogs'] ?? 0; _combinedChartHome = dbData['combinedChart'] ?? 0; + _hideServerAddress = dbData['hideServerAddress']; if (dbData['homeTopItemsOrder'] != null) { try { _homeTopItemsOrder = List.from( diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 675dafd..8660f54 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -90,18 +90,20 @@ class HomeAppBar extends StatelessWidget { if (serversProvider.selectedServer != null) ...[ Text( server!.name, - style: const TextStyle( + style: !appConfigProvider.hideServerAddress ? const TextStyle( fontSize: 20 - ), + ) : null, ), - const SizedBox(height: 5), - Text( - "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).listTileTheme.textColor - ), - ) + if (!appConfigProvider.hideServerAddress) ...[ + const SizedBox(height: 5), + Text( + "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).listTileTheme.textColor + ), + ) + ] ], if (serversProvider.selectedServer == null) Text( AppLocalizations.of(context)!.noServerSelected, diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index 1f73784..fe1e59b 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -159,6 +159,28 @@ class _GeneralSettingsState extends State { right: 10 ) ), + CustomListTile( + icon: Icons.remove_red_eye_rounded, + title: AppLocalizations.of(context)!.hideServerAddress, + subtitle: AppLocalizations.of(context)!.hideServerAddressDescription, + trailing: Switch( + value: appConfigProvider.hideServerAddress, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setHideServerAddress + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.hideServerAddress, + function: appConfigProvider.setHideServerAddress + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), SectionLabel(label: AppLocalizations.of(context)!.logs), CustomListTile( icon: Icons.timer_rounded, From 520a14fcdaf18fc276faa909cbeed05142d33662 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Sep 2023 23:30:53 +0200 Subject: [PATCH 299/676] Created home top items reorder screen --- lib/l10n/app_en.arb | 7 +- lib/l10n/app_es.arb | 7 +- lib/providers/app_config_provider.dart | 2 +- .../general_settings.dart | 10 + .../reorderable_top_items_home.dart | 280 ++++++++++++++++++ lib/screens/settings/settings.dart | 2 +- pubspec.lock | 8 + pubspec.yaml | 1 + 8 files changed, 313 insertions(+), 4 deletions(-) rename lib/screens/settings/{ => general_settings}/general_settings.dart (94%) create mode 100644 lib/screens/settings/general_settings/reorderable_top_items_home.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 38526a3..37e0acb 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -655,5 +655,10 @@ "quickFilters": "Quick filters", "searchDomainInternet": "Search domain on the Internet", "hideServerAddress": "Hide server address", - "hideServerAddressDescription": "Hides the server address on the home screen" + "hideServerAddressDescription": "Hides the server address on the home screen", + "topItemsOrder": "Top items order", + "topItemsOrderDescription": "Order the home screen top items lists", + "topItemsReorderInfo": "Hold and swipe an item to reorder it.", + "discardChanges": "Discard changes", + "discardChangesDescription": "Are you sure you want to discard the changes?" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 383a4b0..4b2af05 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -655,5 +655,10 @@ "quickFilters": "Filtros rápidos", "searchDomainInternet": "Buscar dominio en internet", "hideServerAddress": "Ocultar dirección del servidor", - "hideServerAddressDescription": "Oculta la dirección del servidor en la pantalla de inicio" + "hideServerAddressDescription": "Oculta la dirección del servidor en la pantalla de inicio", + "topItemsOrder": "Orden de los top", + "topItemsOrderDescription": "Ordena las listas de top de elementos en la pantalla de inicio", + "topItemsReorderInfo": "Mantén presionado y desliza un elemento para reordenarlo.", + "discardChanges": "Descartar cambios", + "discardChangesDescription": "¿Estás seguro de que deseas descartar los cambios realizados?" } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index cf4fc0e..3522edc 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -374,7 +374,7 @@ class AppConfigProvider with ChangeNotifier { final updated = await updateConfigQuery( db: _dbInstance!, column: 'homeTopItemsOrder', - value: jsonEncode(order) + value: jsonEncode(List.from(order.map((e) => e.name))) ); if (updated == true) { _homeTopItemsOrder = order; diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart similarity index 94% rename from lib/screens/settings/general_settings.dart rename to lib/screens/settings/general_settings/general_settings.dart index fe1e59b..c5ba7cb 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -7,6 +7,8 @@ import 'package:provider/provider.dart'; import 'package:store_checker/store_checker.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/settings/general_settings/reorderable_top_items_home.dart'; + import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; @@ -181,6 +183,14 @@ class _GeneralSettingsState extends State { right: 10 ) ), + CustomListTile( + icon: Icons.reorder_rounded, + title: AppLocalizations.of(context)!.topItemsOrder, + subtitle: AppLocalizations.of(context)!.topItemsOrderDescription, + onTap: () => Navigator.push(context, MaterialPageRoute( + builder: (context) => const ReorderableTopItemsHome() + )), + ), SectionLabel(label: AppLocalizations.of(context)!.logs), CustomListTile( icon: Icons.timer_rounded, diff --git a/lib/screens/settings/general_settings/reorderable_top_items_home.dart b/lib/screens/settings/general_settings/reorderable_top_items_home.dart new file mode 100644 index 0000000..17e8a34 --- /dev/null +++ b/lib/screens/settings/general_settings/reorderable_top_items_home.dart @@ -0,0 +1,280 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_reorderable_list/flutter_reorderable_list.dart' as reorderable_list_library; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; + +class ItemData { + final HomeTopItems title; + final Key key; + + const ItemData({ + required this.title, + required this.key + }); +} + +enum DraggingMode { + iOS, + android, +} + +class ReorderableTopItemsHome extends StatefulWidget { + const ReorderableTopItemsHome({Key? key}) : super(key: key); + + @override + State createState() => _ReorderableTopItemsHomeState(); +} + +class _ReorderableTopItemsHomeState extends State { + List homeTopItemsList = []; + List persistHomeTopItemsList = []; + List renderItems = []; + + int _indexOfKey(Key key) { + return renderItems.indexWhere((ItemData d) => d.key == key); + } + + bool _reorderCallback(Key item, Key newPosition) { + int draggingIndex = _indexOfKey(item); + int newPositionIndex = _indexOfKey(newPosition); + + final draggedItem = renderItems[draggingIndex]; + + final List reorderedItems = reorderEnumItems(draggingIndex, newPositionIndex); + + setState(() { + renderItems.removeAt(draggingIndex); + renderItems.insert(newPositionIndex, draggedItem); + homeTopItemsList = reorderedItems; + }); + + return true; + } + + void _reorderDone(Key item) { + renderItems[_indexOfKey(item)]; + setState(() => persistHomeTopItemsList = homeTopItemsList); + } + + List reorderEnumItems(int oldIndex, int newIndex) { + final List list = [...homeTopItemsList]; + final HomeTopItems item = list.removeAt(oldIndex); + list.insert(newIndex, item); + return list; + } + + @override + void initState() { + final appConfigProvider = Provider.of(context, listen: false); + homeTopItemsList = appConfigProvider.homeTopItemsOrder; + persistHomeTopItemsList = appConfigProvider.homeTopItemsOrder; + renderItems = appConfigProvider.homeTopItemsOrder.asMap().entries.map( + (e) => ItemData( + key: ValueKey(e.key), + title: e.value, + ) + ).toList(); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + + Widget tile(HomeTopItems title) { + switch (title) { + case HomeTopItems.queriedDomains: + return CustomListTile( + title: AppLocalizations.of(context)!.topQueriedDomains, + icon: Icons.install_desktop_outlined, + padding: const EdgeInsets.all(16) + ); + + case HomeTopItems.blockedDomains: + return CustomListTile( + title: AppLocalizations.of(context)!.topBlockedDomains, + icon: Icons.block_rounded, + padding: const EdgeInsets.all(16) + ); + + case HomeTopItems.recurrentClients: + return CustomListTile( + title: AppLocalizations.of(context)!.topClients, + icon: Icons.smartphone_rounded, + padding: const EdgeInsets.all(16) + ); + + default: + return const SizedBox(); + } + } + + Future onWillPopScope() async { + if (!listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList)) { + showDialog( + context: context, + builder: (dialogContext) => AlertDialog( + title: Text(AppLocalizations.of(context)!.discardChanges), + content: Text(AppLocalizations.of(context)!.discardChangesDescription), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.pop(dialogContext); + Navigator.pop(context); + }, + child: Text(AppLocalizations.of(context)!.confirm) + ), + const SizedBox(width: 8), + TextButton( + onPressed: () => Navigator.pop(dialogContext), + child: Text(AppLocalizations.of(context)!.cancel) + ), + ], + ) + ], + ) + ); + return false; + } + else { + return true; + } + } + + return WillPopScope( + onWillPop: onWillPopScope, + child: Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.topItemsOrder), + actions: [ + IconButton( + onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList) + ? () => appConfigProvider.setHomeTopItemsOrder(homeTopItemsList) + : null, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 8) + ], + ), + body: Column( + children: [ + Card( + margin: const EdgeInsets.all(16), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 16), + Flexible( + child: Text(AppLocalizations.of(context)!.topItemsReorderInfo) + ) + ], + ), + ), + ), + Expanded( + child: reorderable_list_library.ReorderableList( + onReorder: _reorderCallback, + onReorderDone: _reorderDone, + child: ListView.builder( + itemBuilder: (context, index) => reorderable_list_library.ReorderableItem( + key: renderItems[index].key, + childBuilder: (context, state) => Item( + tileWidget: tile(renderItems[index].title), + isFirst: index == 0, + isLast: index == renderItems.length - 1, + state: state + ), + ), + itemCount: renderItems.length, + ) + ), + ), + ], + ), + ), + ); + } +} + +class Item extends StatelessWidget { + final Widget tileWidget; + final bool isFirst; + final bool isLast; + final reorderable_list_library.ReorderableItemState state; + + const Item({ + Key? key, + required this.tileWidget, + required this.isFirst, + required this.isLast, + required this.state, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + BoxDecoration decoration; + + if ( + state == reorderable_list_library.ReorderableItemState.dragProxy || + state == reorderable_list_library.ReorderableItemState.dragProxyFinished + ) { + decoration = BoxDecoration( + color: Theme.of(context).colorScheme.surface.withOpacity(0.7) + ); + } + else { + bool placeholder = state == reorderable_list_library.ReorderableItemState.placeholder; + decoration = BoxDecoration( + border: Border( + top: isFirst && !placeholder ? BorderSide( + width: 1, + color: Theme.of(context).colorScheme.primary.withOpacity(0.1) + ) : BorderSide.none, + bottom: isLast && placeholder ? BorderSide.none : BorderSide( + width: 1, + color: Theme.of(context).colorScheme.primary.withOpacity(0.1) + ), + ), + ); + } + + return reorderable_list_library.DelayedReorderableListener( + child: Container( + decoration: decoration, + child: SafeArea( + top: false, + bottom: false, + child: Opacity( + opacity: state == reorderable_list_library.ReorderableItemState.placeholder ? 0.0 : 1.0, + child: IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: tileWidget + ), + ], + ), + ), + ) + ), + ) + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index f3a08ba..709a245 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -17,7 +17,7 @@ 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/servers/servers.dart'; import 'package:adguard_home_manager/screens/settings/advanced_setings.dart'; -import 'package:adguard_home_manager/screens/settings/general_settings.dart'; +import 'package:adguard_home_manager/screens/settings/general_settings/general_settings.dart'; import 'package:adguard_home_manager/widgets/custom_settings_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; diff --git a/pubspec.lock b/pubspec.lock index 29e7ed3..d0842e2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -267,6 +267,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + flutter_reorderable_list: + dependency: "direct main" + description: + name: flutter_reorderable_list + sha256: "0400ef34fa00b7cac69f71efc92d7e49727f425bc1080180ebe70bf47618afe0" + url: "https://pub.dev" + source: hosted + version: "1.3.1" flutter_split_view: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index c4f5812..d18eb72 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -72,6 +72,7 @@ dependencies: async: ^2.10.0 sentry_flutter: ^7.9.0 flutter_dotenv: ^5.0.2 + flutter_reorderable_list: ^1.3.1 dev_dependencies: flutter_test: From d69da88b01ba7bc2c312001976cd6bf4888a0ec0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 10 Sep 2023 00:05:04 +0200 Subject: [PATCH 300/676] Change order home and fixes --- lib/config/home_top_items_default_order.dart | 4 +- lib/screens/home/home.dart | 175 ++++++++++-------- .../reorderable_top_items_home.dart | 23 ++- 3 files changed, 122 insertions(+), 80 deletions(-) diff --git a/lib/config/home_top_items_default_order.dart b/lib/config/home_top_items_default_order.dart index 1f49093..5220987 100644 --- a/lib/config/home_top_items_default_order.dart +++ b/lib/config/home_top_items_default_order.dart @@ -8,4 +8,6 @@ final List homeTopItemsDefaultOrder = [ HomeTopItems.recurrentClients ]; -final String homeTopItemsDefaultOrderString = jsonEncode(homeTopItemsDefaultOrder); \ No newline at end of file +final String homeTopItemsDefaultOrderString = jsonEncode( + List.from(homeTopItemsDefaultOrder.map((e) => e.name)) +); \ No newline at end of file diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 41f8b26..107b680 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -175,88 +175,107 @@ class _HomeState extends State { child: CombinedHomeChart(), ), - if (width <= 700) ...[ - TopItems( - label: AppLocalizations.of(context)!.topQueriedDomains, - data: statusProvider.serverStatus!.stats.topQueriedDomains, - type: 'topQueriedDomains', - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), - ), - ), - - const SizedBox(height: 16), - - TopItems( - label: AppLocalizations.of(context)!.topBlockedDomains, - data: statusProvider.serverStatus!.stats.topBlockedDomains, - type: 'topBlockedDomains', - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), - ), - ), - const SizedBox(height: 16), - - TopItems( - label: AppLocalizations.of(context)!.topClients, - data: statusProvider.serverStatus!.stats.topClients, - type: 'topClients', - clients: true, - ), - ], + if (width <= 700) ...appConfigProvider.homeTopItemsOrder.asMap().entries.map((item) { + Widget list() { + switch (item.value) { + case HomeTopItems.queriedDomains: + return TopItems( + label: AppLocalizations.of(context)!.topQueriedDomains, + data: statusProvider.serverStatus!.stats.topQueriedDomains, + type: 'topQueriedDomains', + ); + + case HomeTopItems.blockedDomains: + return TopItems( + label: AppLocalizations.of(context)!.topBlockedDomains, + data: statusProvider.serverStatus!.stats.topBlockedDomains, + type: 'topBlockedDomains', + ); + + case HomeTopItems.recurrentClients: + return TopItems( + label: AppLocalizations.of(context)!.topClients, + data: statusProvider.serverStatus!.stats.topClients, + type: 'topClients', + clients: true, + ); + + default: + return const SizedBox(); + } + } + + return Column( + children: [ + list(), + if (item.key < appConfigProvider.homeTopItemsOrder.length - 1) ...[ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + ), + const SizedBox(height: 16), + ] + ], + ); + }), if (width > 700) Column( children: [ Wrap( alignment: WrapAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: TopItems( - label: AppLocalizations.of(context)!.topQueriedDomains, - data: statusProvider.serverStatus!.stats.topQueriedDomains, - type: 'topQueriedDomains', - ), - ), - ), - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: TopItems( - label: AppLocalizations.of(context)!.topBlockedDomains, - data: statusProvider.serverStatus!.stats.topBlockedDomains, - type: 'topBlockedDomains', - ), - ), - ), - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: TopItems( - label: AppLocalizations.of(context)!.topClients, - data: statusProvider.serverStatus!.stats.topClients, - type: 'topClients', - ), - ), - ), - ], + children: appConfigProvider.homeTopItemsOrder.map((item) { + switch (item) { + case HomeTopItems.queriedDomains: + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: TopItems( + label: AppLocalizations.of(context)!.topQueriedDomains, + data: statusProvider.serverStatus!.stats.topQueriedDomains, + type: 'topQueriedDomains', + ), + ), + ); + + case HomeTopItems.blockedDomains: + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: TopItems( + label: AppLocalizations.of(context)!.topBlockedDomains, + data: statusProvider.serverStatus!.stats.topBlockedDomains, + type: 'topBlockedDomains', + ), + ), + ); + + case HomeTopItems.recurrentClients: + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: TopItems( + label: AppLocalizations.of(context)!.topClients, + data: statusProvider.serverStatus!.stats.topClients, + type: 'topClients', + ), + ), + ); + + default: + return const SizedBox(); + } + }).toList(), ), ], ) diff --git a/lib/screens/settings/general_settings/reorderable_top_items_home.dart b/lib/screens/settings/general_settings/reorderable_top_items_home.dart index 17e8a34..75ad9cc 100644 --- a/lib/screens/settings/general_settings/reorderable_top_items_home.dart +++ b/lib/screens/settings/general_settings/reorderable_top_items_home.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -6,6 +8,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -151,6 +154,24 @@ class _ReorderableTopItemsHomeState extends State { } } + void saveSettings() async { + final result = await appConfigProvider.setHomeTopItemsOrder(homeTopItemsList); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.settingsSaved, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.settingsNotSaved, + color: Colors.red + ); + } + } + return WillPopScope( onWillPop: onWillPopScope, child: Scaffold( @@ -159,7 +180,7 @@ class _ReorderableTopItemsHomeState extends State { actions: [ IconButton( onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList) - ? () => appConfigProvider.setHomeTopItemsOrder(homeTopItemsList) + ? () => saveSettings() : null, icon: const Icon(Icons.save_rounded), tooltip: AppLocalizations.of(context)!.save, From 87bcdd337f49a4436841e1ff3284152e811ee3e1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 13 Sep 2023 01:17:19 +0200 Subject: [PATCH 301/676] Readded pull to refresh on logs --- lib/screens/home/home.dart | 1 + lib/screens/logs/logs.dart | 136 +++++++++++++++++++------------------ 2 files changed, 72 insertions(+), 65 deletions(-) diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 107b680..a37eee7 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -301,6 +301,7 @@ class _HomeState extends State { child: Builder( builder: (context) => RefreshIndicator( color: Theme.of(context).colorScheme.primary, + displacement: 95, onRefresh: () async { final result = await statusProvider.getServerStatus(); if (result == false) { diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 9a3b5af..da56dcc 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -231,78 +231,84 @@ class _LogsState extends State { top: false, bottom: false, child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (logsProvider.logsData!.data.isNotEmpty) SliverList.builder( - itemCount: logsProvider.logsData!.data.length, - itemBuilder: (context, index) { - if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { - return const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - else if (logsProvider.logsData!.data[index].question.name != null) { - return LogTile( - log: logsProvider.logsData!.data[index], - index: index, - length: logsProvider.logsData!.data.length, - isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index], - onLogTap: (log) { - if (width <= 1100) { - Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false, - ) - )); + builder: (context) => RefreshIndicator( + onRefresh: () async { + await logsProvider.fetchLogs(inOffset: 0); + }, + displacement: 95, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (logsProvider.logsData!.data.isNotEmpty) SliverList.builder( + itemCount: logsProvider.logsData!.data.length, + itemBuilder: (context, index) { + if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else if (logsProvider.logsData!.data[index].question.name != null) { + return LogTile( + log: logsProvider.logsData!.data[index], + index: index, + length: logsProvider.logsData!.data.length, + isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index], + onLogTap: (log) { + if (width <= 1100) { + Navigator.push(context, MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + ) + )); + } + setState(() => selectedLog = log); } - setState(() => selectedLog = log); - } - ); + ); + } + else { + return null; + } } - else { - return null; - } - } - ), - if (logsProvider.logsData!.data.isEmpty) SliverFillRemaining( - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - AppLocalizations.of(context)!.noLogsDisplay, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - if (logsProvider.logsOlderThan != null) Padding( - padding: const EdgeInsets.only( - top: 30, - left: 20, - right: 20 - ), - child: Text( - AppLocalizations.of(context)!.noLogsThatOld, - textAlign: TextAlign.center, + ), + if (logsProvider.logsData!.data.isEmpty) SliverFillRemaining( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context)!.noLogsDisplay, style: TextStyle( - fontSize: 16, + fontSize: 24, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), - ), - ] + if (logsProvider.logsOlderThan != null) Padding( + padding: const EdgeInsets.only( + top: 30, + left: 20, + right: 20 + ), + child: Text( + AppLocalizations.of(context)!.noLogsThatOld, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ] + ), ), - ), - ) - ], + ) + ], + ), ), ) ); From bc7cb4ccd427f4c5d19a526de24df8fe1700f779 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 19 Sep 2023 00:10:54 +0200 Subject: [PATCH 302/676] Fixed lazy loading logs --- lib/screens/logs/logs.dart | 146 +++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index da56dcc..6d9cef6 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -31,8 +31,6 @@ class Logs extends StatefulWidget { } class _LogsState extends State { - late ScrollController scrollController; - bool showDivider = true; Log? selectedLog; @@ -65,25 +63,26 @@ class _LogsState extends State { } } - void scrollListener() { + bool scrollListener(ScrollUpdateNotification scrollNotification) { final logsProvider = Provider.of(context, listen: false); - if (scrollController.position.extentAfter < 500 && logsProvider.isLoadingMore == false) { + if (scrollNotification.metrics.extentAfter < 500 && logsProvider.isLoadingMore == false) { logsProvider.fetchLogs(loadingMore: true); } - if (scrollController.position.pixels > 0) { + if (scrollNotification.metrics.pixels > 0) { setState(() => showDivider = false); } else { setState(() => showDivider = true); } + + return false; } @override void initState() { final logsProvider = Provider.of(context, listen: false); - scrollController = ScrollController()..addListener(scrollListener); logsProvider.fetchLogs(inOffset: 0); fetchFilteringRules(); fetchClients(); @@ -236,78 +235,83 @@ class _LogsState extends State { await logsProvider.fetchLogs(inOffset: 0); }, displacement: 95, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (logsProvider.logsData!.data.isNotEmpty) SliverList.builder( - itemCount: logsProvider.logsData!.data.length, - itemBuilder: (context, index) { - if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { - return const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - else if (logsProvider.logsData!.data[index].question.name != null) { - return LogTile( - log: logsProvider.logsData!.data[index], - index: index, - length: logsProvider.logsData!.data.length, - isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index], - onLogTap: (log) { - if (width <= 1100) { - Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false, - ) - )); + child: NotificationListener( + onNotification: scrollListener, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (logsProvider.logsData!.data.isNotEmpty) SliverList.builder( + itemCount: logsProvider.isLoadingMore + ? logsProvider.logsData!.data.length + 1 + : logsProvider.logsData!.data.length, + itemBuilder: (context, index) { + if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else if (logsProvider.logsData!.data[index].question.name != null) { + return LogTile( + log: logsProvider.logsData!.data[index], + index: index, + length: logsProvider.logsData!.data.length, + isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index], + onLogTap: (log) { + if (width <= 1100) { + Navigator.push(context, MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + ) + )); + } + setState(() => selectedLog = log); } - setState(() => selectedLog = log); - } - ); + ); + } + else { + return null; + } } - else { - return null; - } - } - ), - if (logsProvider.logsData!.data.isEmpty) SliverFillRemaining( - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - AppLocalizations.of(context)!.noLogsDisplay, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - if (logsProvider.logsOlderThan != null) Padding( - padding: const EdgeInsets.only( - top: 30, - left: 20, - right: 20 - ), - child: Text( - AppLocalizations.of(context)!.noLogsThatOld, - textAlign: TextAlign.center, + ), + if (logsProvider.logsData!.data.isEmpty) SliverFillRemaining( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context)!.noLogsDisplay, style: TextStyle( - fontSize: 16, + fontSize: 24, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), - ), - ] + if (logsProvider.logsOlderThan != null) Padding( + padding: const EdgeInsets.only( + top: 30, + left: 20, + right: 20 + ), + child: Text( + AppLocalizations.of(context)!.noLogsThatOld, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ] + ), ), - ), - ) - ], + ) + ], + ), ), ), ) From 45d785ad72187d83a5e770f3df12b74b3ccf9df3 Mon Sep 17 00:00:00 2001 From: dmitry Date: Sun, 24 Sep 2023 00:29:22 +0500 Subject: [PATCH 303/676] Russian_translation: init --- lib/l10n/app_ru.arb | 664 ++++++++++++++++++++++++++++++++++++++++++++ lib/main.dart | 3 +- 2 files changed, 666 insertions(+), 1 deletion(-) create mode 100644 lib/l10n/app_ru.arb diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb new file mode 100644 index 0000000..dc8b29a --- /dev/null +++ b/lib/l10n/app_ru.arb @@ -0,0 +1,664 @@ +{ + "home": "ГлавнаÑ", + "settings": "ÐаÑтройки", + "connect": "ПодключитьÑÑ", + "servers": "Сервера", + "createConnection": "Создать подключение", + "name": "Ðазвание подключениÑ", + "ipDomain": "IP-Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ домен", + "path": "Путь", + "port": "Порт", + "username": "Логин", + "password": "Пароль", + "defaultServer": "Сервер по умолчанию", + "general": "ОÑновное", + "connection": "Тип подключениÑ", + "authentication": "ÐутентификациÑ", + "other": "Прочее", + "invalidPort": "Ðеверный порт", + "invalidPath": "Ðеверный путь", + "invalidIpDomain": "Ðеверный IP-Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ домен", + "ipDomainNotEmpty": "IP-Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ домен не могут быть пуÑтыми", + "nameNotEmpty": "Ð˜Ð¼Ñ Ð½Ðµ может быть пуÑтым", + "invalidUsernamePassword": "Ðеверный логин или пароль", + "tooManyAttempts": "Слишком много попыток. Попробуйте позднее.", + "cantReachServer": "Ðе удаётÑÑ ÑƒÑтановить Ñоединение Ñ Ñервером. Проверьте наÑтройки подключениÑ", + "sslError": "SSL error. Go to Settings > Advanced settings and enable Override SSL validation.", + "unknownError": "ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°", + "connectionNotCreated": "Ðе удалоÑÑŒ Ñоздать подключение", + "connecting": "Подключение...", + "connected": "Подключено", + "selectedDisconnected": "Выбран, но отключён", + "connectionDefaultSuccessfully": "Подключение уÑпешно уÑтановлено как «подключение по умолчанию».", + "connectionDefaultFailed": "Подключение не удалоÑÑŒ уÑтановить «подключением по умолчанию».", + "noSavedConnections": "Ðет Ñохранённых подключений", + "cannotConnect": "Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ Ðº Ñерверу", + "connectionRemoved": "Подключение удалено уÑпешно", + "connectionCannotBeRemoved": "Подключение не может быть удалено.", + "remove": "Удалить", + "removeWarning": "Ð’Ñ‹ уверены, что хотите удалить Ñоединение Ñ Ñтим Ñервером AdGuard Home?", + "cancel": "Отмена", + "defaultConnection": "Подключение по умолчанию", + "setDefault": "ПодключатьÑÑ Ð¿Ð¾ умолчанию", + "edit": "Редактировать", + "delete": "Удалить", + "save": "Сохранить", + "serverStatus": "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñервера", + "connectionNotUpdated": "Соединение не было обновлено", + "ruleFilteringWidget": "Правила фильтрации", + "safeBrowsingWidget": "БезопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ", + "parentalFilteringWidget": "РодительÑкий контроль", + "safeSearchWidget": "БезопаÑный поиÑк", + "ruleFiltering": "Правила фильтрации", + "safeBrowsing": "БезопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ", + "parentalFiltering": "РодительÑкий контроль", + "safeSearch": "БезопаÑный поиÑк", + "serverStatusNotRefreshed": "Ðе удалоÑÑŒ обновить ÑÑ‚Ð°Ñ‚ÑƒÑ Ñервера", + "loadingStatus": "Загрузка...", + "errorLoadServerStatus": "Ðе удалоÑÑŒ получить ÑÑ‚Ð°Ñ‚ÑƒÑ Ñервера", + "topQueriedDomains": "ЧаÑто запрашиваемые домены", + "viewMore": "Показать больше", + "topClients": "ЧаÑтые клиенты", + "topBlockedDomains": "ЧаÑто блокируемые домены", + "appSettings": "ÐаÑтройки приложениÑ", + "theme": "Тема", + "light": "СветлаÑ", + "dark": "ТёмнаÑ", + "systemDefined": "Определено ÑиÑтемой", + "close": "Закрыть", + "connectedTo": "Подключено к:", + "selectedServer": "Selected server:", + "noServerSelected": "Ðет выбранных Ñерверов", + "manageServer": "Управление Ñервером", + "allProtections": "Защита", + "userNotEmpty": "Username cannot be empty", + "passwordNotEmpty": "Password cannot be empty", + "examplePath": "Ðапример: /adguard", + "helperPath": "ЕÑли иÑпользуетÑÑ Ñ€ÐµÐ²ÐµÑ€Ñивный прокÑи", + "aboutApp": "About the application", + "appVersion": "App version", + "createdBy": "Created by", + "clients": "Клиенты", + "allowed": "Разрешённые", + "blocked": "Заблокированные", + "noClientsList": "СпиÑок клиентов пуÑÑ‚", + "activeClients": "Ðктивные", + "removeClient": "Удалить запиÑÑŒ", + "removeClientMessage": "Ð’Ñ‹ уверены, что хотите удалить данную запиÑÑŒ из ÑпиÑка?", + "confirm": "Подтвердить", + "removingClient": "Удаление клиента...", + "clientNotRemoved": "Клиент не может быть удалён из ÑпиÑка", + "addClient": "Добавить клиента", + "list": "СпиÑок", + "ipAddress": "IP-адреÑа", + "ipNotValid": "IP address not valid", + "clientAddedSuccessfully": "ЗапиÑÑŒ уÑпешно добавлена в ÑпиÑок", + "addingClient": "Добавление клиента...", + "clientNotAdded": "Клиент не может быть внеÑён в ÑпиÑок", + "clientAnotherList": "Данный клиент уже занеÑён в один из ÑпиÑков", + "noSavedLogs": "Ðет Ñохранённых журналов", + "logs": "Журналы", + "copyLogsClipboard": "Copy logs to clipboard", + "logsCopiedClipboard": "Logs copied to clipboard", + "advancedSettings": "Advanced settings", + "dontCheckCertificate": "Don't check SSL certificate", + "dontCheckCertificateDescription": "Overrides the server's SSL certificate validation", + "advancedSetupDescription": "Advanced options", + "settingsUpdatedSuccessfully": "ÐаÑтройки уÑпешно обновлены.", + "cannotUpdateSettings": "Settings cannot be updated.", + "restartAppTakeEffect": "Restart the application", + "loadingLogs": "Загрузка журнала...", + "logsNotLoaded": "Ðевозможно загрузить ÑпиÑок журналов", + "processed": "Processed\nNo list", + "processedRow": "Обработан", + "blockedBlacklist": "Blocked\nBlacklist", + "blockedBlacklistRow": "Заблокированные (чёрный ÑпиÑок)", + "blockedSafeBrowsing": "Blocked\nSafe browsing", + "blockedSafeBrowsingRow": "Блок. (безопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ)", + "blockedParental": "Blocked\nParental filtering", + "blockedParentalRow": "Блок. (родительÑкий контроль)", + "blockedInvalid": "Blocked\nInvalid", + "blockedInvalidRow": "Blocked (invalid)", + "blockedSafeSearch": "Blocked\nSafe search", + "blockedSafeSearchRow": "Блок. (безопаÑный поиÑк)", + "blockedService": "Blocked\nBlocked service", + "blockedServiceRow": "Blocked (blocked service)", + "processedWhitelist": "Processed\nWhitelist", + "processedWhitelistRow": "Разрешённые (белый ÑпиÑок)", + "processedError": "Processed\nError", + "processedErrorRow": "Processed (error)", + "rewrite": "Rewrite", + "status": "СтатуÑ", + "result": "Результат", + "time": "ВремÑ", + "blocklist": "Blocklist", + "request": "ЗапроÑ", + "domain": "Домен", + "type": "Тип", + "clas": "КлаÑÑ", + "response": "Ответ", + "dnsServer": "DNS-Ñервер", + "elapsedTime": "Затрачено", + "responseCode": "Код ответа", + "client": "Клиент", + "deviceIp": "IP-адреÑ", + "deviceName": "Ð˜Ð¼Ñ ÑƒÑтройÑтва", + "logDetails": "Детали запроÑа", + "blockingRule": "Blocking rule", + "blockDomain": "Block domain", + "couldntGetFilteringStatus": "Ðе удаётÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ð¸", + "unblockDomain": "Unblock domain", + "userFilteringRulesNotUpdated": "Ðевозможно обновить пользовательÑкие правила фильтрации", + "userFilteringRulesUpdated": "ПользовательÑкие правила фильтрации уÑпешно обновлены", + "savingUserFilters": "Сохранение пользовательÑких правил фильтрации...", + "filters": "Фильтры", + "logsOlderThan": "Logs older than", + "responseStatus": "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ñ‚Ð²ÐµÑ‚Ð°", + "selectTime": "Select time", + "notSelected": "Not selected", + "resetFilters": "СброÑить фильтры", + "noLogsDisplay": "Ðет запиÑей в журнале", + "noLogsThatOld": "It's possible that there are no logs saved for that selected time. Try selecting a more recent time.", + "apply": "Применить", + "selectAll": "Отметить вÑе", + "unselectAll": "Отменить выбор вÑех", + "all": "Ð’Ñе", + "filtered": "Отфильтрованные", + "checkAppLogs": "Check app logs", + "refresh": "Обновить", + "search": "ПоиÑк", + "dnsQueries": "DNS-запроÑÑ‹", + "average": "Среднее", + "blockedFilters": "Заблокировано фильтрами", + "malwarePhisingBlocked": "Заблокированные вредоноÑные и фишинговые Ñайты", + "blockedAdultWebsites": "Заблокированные «взроÑлые» Ñайты", + "generalSettings": "ОÑновные наÑтройки", + "generalSettingsDescription": "Различные наÑтройки", + "hideZeroValues": "Скрывать нулевые значениÑ", + "hideZeroValuesDescription": "Скрывать блоки Ñ Ð½ÑƒÐ»ÐµÐ²Ñ‹Ð¼Ð¸ значениÑми на домашнем Ñкране", + "webAdminPanel": "Веб-панель админ.", + "visitGooglePlay": "ПоÑетить Ñтраницу в Google Play", + "gitHub": "ИÑходный код Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупен на GitHub", + "blockClient": "Заблокировать клиента", + "selectTags": "Выбрать теги клиента", + "noTagsSelected": "Ðет выбранных тегов", + "tags": "Теги", + "identifiers": "Идентификаторы", + "identifier": "Идентификатор", + "identifierHelper": "IP-адреÑ, CIDR, MAC или ClientID", + "noIdentifiers": "Идентификаторы не добавлены", + "useGlobalSettings": "Глобальные наÑтройки", + "enableFiltering": "ФильтрациÑ", + "enableSafeBrowsing": "БезопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ", + "enableParentalControl": "РодительÑкий контроль", + "enableSafeSearch": "БезопаÑный поиÑк", + "blockedServices": "Заблокированные ÑервиÑÑ‹", + "selectBlockedServices": "Заблокированные ÑервиÑÑ‹", + "noBlockedServicesSelected": "Ðет заблокированных ÑервиÑов", + "services": "СервиÑÑ‹", + "servicesBlocked": "в блокировке", + "tagsSelected": "выбрано", + "upstreamServers": "Upstream DNS-Ñерверы", + "serverAddress": "ÐÐ´Ñ€ÐµÑ Ñервера", + "noUpstreamServers": "Ðет upstream DNS-Ñерверов.", + "willBeUsedGeneralServers": "Будут иÑпользоватьÑÑ Ð¾Ð±Ñ‰Ð¸Ðµ upstream DNS-Ñервера.", + "added": "Сохранённые", + "clientUpdatedSuccessfully": "ÐаÑтройки клиента уÑпешно обновлены", + "clientNotUpdated": "Ðевозможно обновить наÑтройки клиента", + "clientDeletedSuccessfully": "Клиент уÑпешно удалён", + "clientNotDeleted": "Ðевозможно удалить клиента", + "options": "Параметры", + "loadingFilters": "Загрузка фильтров...", + "filtersNotLoaded": "Ðевозможно загрузить фильтры.", + "whitelists": "Whitelists", + "blacklists": "Blacklists", + "rules": "Rules", + "customRules": "Custom rules", + "enabledRules": "Enabled rules", + "enabled": "Enabled", + "disabled": "Disabled", + "rule": "Rule", + "addCustomRule": "Add custom rule", + "removeCustomRule": "Remove custom rule", + "removeCustomRuleMessage": "Are you sure you want to remove this custom rule?", + "updatingRules": "Updating custom rules...", + "ruleRemovedSuccessfully": "Rule removed successfully", + "ruleNotRemoved": "Couldn't remove the rule", + "ruleAddedSuccessfully": "Rule added successfully", + "ruleNotAdded": "Couldn't add the rule", + "noCustomFilters": "No custom filters", + "noBlockedClients": "Ðет запрещённых клиентов", + "noBlackLists": "No blacklists", + "noWhiteLists": "No whitelists", + "addWhitelist": "Add whitelist", + "addBlacklist": "Add blacklist", + "urlNotValid": "URL is not valid", + "urlAbsolutePath": "URL or absolute path", + "addingList": "Adding list...", + "listAdded": "List added successfully. Items added:", + "listAlreadyAdded": "List already added", + "listUrlInvalid": "List URL invalid", + "listNotAdded": "List couldn't be added", + "listDetails": "List details", + "listType": "List type", + "whitelist": "White list", + "blacklist": "Black list", + "latestUpdate": "Latest update", + "disable": "Выключить", + "enable": "Включить", + "currentStatus": "Текущий ÑтатуÑ", + "listDataUpdated": "List data updated successfull", + "listDataNotUpdated": "Couldn't update list data", + "updatingListData": "Updating list data...", + "editWhitelist": "Edit white list", + "editBlacklist": "Edit black list", + "deletingList": "Deleting list...", + "listDeleted": "List deleted successfully", + "listNotDeleted": "The list couldn't be deleted", + "deleteList": "Delete list", + "deleteListMessage": "Are you sure you want to delete this list? This action can't be reverted.", + "serverSettings": "Server settings", + "serverInformation": "Server information", + "serverInformationDescription": "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñервере и ÑтатуÑ", + "loadingServerInfo": "Загрузка информации о Ñервере...", + "serverInfoNotLoaded": "Ðевозможно загрузить информацию о Ñервере.", + "dnsAddresses": "DNS-адреÑа", + "seeDnsAddresses": "ПоÑмотреть DNS-адреÑа", + "dnsPort": "DNS-порт", + "httpPort": "HTTP-порт", + "protectionEnabled": "Защита активна", + "dhcpAvailable": "DHCP недоÑтупен", + "serverRunning": "Server running", + "serverVersion": "Server version", + "serverLanguage": "Server language", + "yes": "Yes", + "no": "No", + "allowedClients": "Разрешённые клиенты", + "disallowedClients": "Запрещённые клиенты", + "disallowedDomains": "Ðеразрешённые домены", + "accessSettings": "ÐаÑтройки доÑтупа", + "accessSettingsDescription": "ÐаÑтройка правил доÑтупа к Ñерверу", + "loadingClients": "Загрузка клиентов...", + "clientsNotLoaded": "Ðе удалоÑÑŒ загрузить ÑпиÑок клиентов.", + "noAllowedClients": "Ðет разрешённых клиентов", + "allowedClientsDescription": "ЕÑли в ÑпиÑке еÑть запиÑи, AdGuard Home будет принимать запроÑÑ‹ только от Ñтих клиентов.", + "blockedClientsDescription": "ЕÑли в ÑпиÑке еÑть запиÑи, AdGuard Home будет игнорировать запроÑÑ‹ от Ñтих клиентов. Это поле игнорируетÑÑ, еÑли ÑпиÑок разрешённых клиентов Ñодержит запиÑи.", + "disallowedDomainsDescription": "AdGuard Home будет игнорировать DNS-запроÑÑ‹ Ñ Ñтими доменами. Такие DNS-запроÑÑ‹ не будут отображатьÑÑ Ð² журнале.", + "addClientFieldDescription": "CIDR, IP-Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ ClientID", + "clientIdentifier": "Идентификатор клиента", + "allowClient": "Разрешить клиент", + "disallowClient": "Запретить клиента", + "noDisallowedDomains": "No disallowed domains", + "domainNotAdded": "The domain couldn't be added", + "statusSelected": "status selected", + "updateLists": "Update lists", + "checkHostFiltered": "Check host", + "updatingLists": "Updating lists...", + "listsUpdated": "lists updated", + "listsNotUpdated": "Couldn't update lists", + "listsNotLoaded": "Lists couldn't be loaded", + "domainNotValid": "Domain not valid", + "check": "Check", + "checkingHost": "Checking host...", + "errorCheckingHost": "Host couldn't be checked", + "block": "Block", + "unblock": "Unblock", + "custom": "Custom", + "addImportant": "Add $important", + "howCreateRules": "How to create custom rules", + "examples": "Examples", + "example1": "Block access to example.org and all its subdomains.", + "example2": "Unblocks access to example.org and all its subdomains.", + "example3": "Adds a comment.", + "example4": "Block access to domains matching the specified regular expression.", + "moreInformation": "More information", + "addingRule": "Adding rule...", + "deletingRule": "Deleting rule...", + "enablingList": "Enabling list...", + "disablingList": "Disabling list...", + "disableFiltering": "Disable filtering", + "enablingFiltering": "Enabling filtering...", + "disablingFiltering": "Disabling filtering...", + "filteringStatusUpdated": "Filtering status updated successfully", + "filteringStatusNotUpdated": "Filtering status couldn't be updated", + "updateFrequency": "Update frequency", + "never": "Ðикогда", + "hour1": "1 чаÑ", + "hours12": "12 чаÑов", + "hours24": "24 чаÑа", + "days3": "3 днÑ", + "days7": "7 дней", + "changingUpdateFrequency": "Changing...", + "updateFrequencyChanged": "Update frequency changed successfully", + "updateFrequencyNotChanged": "Updare frecuency couldn't be changed", + "updating": "Updating values...", + "blockedServicesUpdated": "Blocked services updated successfully", + "blockedServicesNotUpdated": "Blocked services couldn't be updated", + "insertDomain": "Insert a domain to check it's stauts.", + "dhcpSettings": "ÐаÑтройки DHCP", + "dhcpSettingsDescription": "ÐаÑтройка DHCP-Ñервера", + "dhcpSettingsNotLoaded": "Ðе удалоÑÑŒ загрузить наÑтройки DHCP", + "loadingDhcp": "Загрузка наÑтроек DHCP...", + "enableDhcpServer": "Включить DHCP-Ñервер", + "selectInterface": "Выбрать Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ DHCP", + "hardwareAddress": "MAC-адреÑ", + "gatewayIp": "IP-Ð°Ð´Ñ€ÐµÑ ÑˆÐ»ÑŽÐ·Ð°", + "ipv4addresses": "ÐÐ´Ñ€ÐµÑ IPv4", + "ipv6addresses": "ÐÐ´Ñ€ÐµÑ IPv6", + "neededSelectInterface": "Ðеобходимо выбрать Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ Ð½Ð°Ñтройки DHCP-Ñервера.", + "ipv4settings": "ÐаÑтройки IPv4", + "startOfRange": "Ðачало диапазона", + "endOfRange": "Конец диапазона", + "ipv6settings": "ÐаÑтройки IPv6", + "subnetMask": "МаÑка подÑети", + "subnetMaskNotValid": "Subnet mask not valid", + "gateway": "Шлюз", + "gatewayNotValid": "Gateway not valid", + "leaseTime": "Ð’Ñ€ÐµÐ¼Ñ Ð°Ñ€ÐµÐ½Ð´Ñ‹", + "seconds": "{time} seconds", + "leaseTimeNotValid": "Lease time not valid", + "restoreConfiguration": "Reset configuration", + "restoreConfigurationMessage": "Are you sure you want to continue? This will reset all the configuration. This action cannot be undone.", + "changeInterface": "Change interface", + "savingSettings": "Сохранение наÑтроек...", + "settingsSaved": "Settings saved successfully", + "settingsNotSaved": "Settings couldn't be saved", + "restoringConfig": "Restoring configuration...", + "configRestored": "Configuration reseted successfully", + "configNotRestored": "The configuration couldn't be reseted", + "dhcpStatic": "СтатичеÑкие аренды DHCP", + "noDhcpStaticLeases": "Ðе найдено ÑтатичеÑких аренд DHCP", + "deleting": "Deleting...", + "staticLeaseDeleted": "DHCP static lease deleted successfully", + "staticLeaseNotDeleted": "The DHCP static lease could not be deleted", + "deleteStaticLease": "Delete static lease", + "deleteStaticLeaseDescription": "The DHCP static lease will be deleted. This action cannot be reverted.", + "addStaticLease": "Add static lease", + "macAddress": "MAC address", + "macAddressNotValid": "MAC address not valid", + "hostName": "Host name", + "hostNameError": "Host name cannot be empty", + "creating": "Creating...", + "staticLeaseCreated": "DHCP static lease created successfully", + "staticLeaseNotCreated": "The DHCP static lease couldn't be created", + "staticLeaseExists": "The DHCP static lease already exists", + "serverNotConfigured": "Server not configured", + "restoreLeases": "Reset leases", + "restoreLeasesMessage": "Are you sure you want to continue? This will reset all the existing leases. This action cannot be undone.", + "restoringLeases": "Resetting leases...", + "leasesRestored": "Leases reseted successfully", + "leasesNotRestored": "The leases couldn't be reseted", + "dhcpLeases": "Ðренды DHCP", + "noLeases": "Ðе найдено аренд DHCP", + "dnsRewrites": "DNS rewrites", + "dnsRewritesDescription": "Configure custom DNS rules", + "loadingRewriteRules": "Loading rewrite rules...", + "rewriteRulesNotLoaded": "DNS rewrite rules could not be loaded.", + "noRewriteRules": "No DNS rewrite rules", + "answer": "Answer", + "deleteDnsRewrite": "Delete DNS rewrite", + "deleteDnsRewriteMessage": "Are you sure you want to delete this DNS rewrite? This action cannot be undone.", + "dnsRewriteRuleDeleted": "DNS rewrite rule deleted successfully", + "dnsRewriteRuleNotDeleted": "The DNS rewrite rule could not be deleted", + "addDnsRewrite": "Add DNS rewrite", + "addingRewrite": "Adding rewrite...", + "dnsRewriteRuleAdded": "DNS rewrite rule addded successfully", + "dnsRewriteRuleNotAdded": "DNS rewrite rule could not be added", + "logsSettings": "ÐаÑтройки журнала", + "enableLog": "Включить журнал", + "clearLogs": "ОчиÑтить журнал", + "anonymizeClientIp": "Ðнонимизировать IP-Ð°Ð´Ñ€ÐµÑ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ð°", + "hours6": "6 чаÑов", + "days30": "30 дней", + "days90": "90 дней", + "retentionTime": "ЧаÑтота ротации журнала запроÑов", + "selectOneItem": "Select one item", + "logSettingsNotLoaded": "Log settings couldn't be loaded.", + "updatingSettings": "Updating settings...", + "logsConfigUpdated": "ÐаÑтройки журнала уÑпешно обновлены", + "logsConfigNotUpdated": "Ðевозможно обновить наÑтройки журнала", + "deletingLogs": "ОчиÑтка журнала...", + "logsCleared": "Журнал уÑпешно очищен", + "logsNotCleared": "Ðевозможно очиÑтить журнал", + "runningHomeAssistant": "ЗапуÑкаетÑÑ Ð½Ð° Home Assistant", + "serverError": "Server error", + "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.", + "noBootstrapDns": "No bootstrap DNS servers added.", + "bootstrapDnsServersInfo": "Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams.", + "privateReverseDnsServers": "Private reverse DNS servers", + "privateReverseDnsServersDescription": "The DNS servers that AdGuard Home uses for local PTR queries. These servers are used to resolve PTR requests for addresses in private IP ranges, for example \"192.168.12.34\", using reverse DNS. If not set, AdGuard Home uses the addresses of the default DNS resolvers of your OS except for the addresses of AdGuard Home itself.", + "reverseDnsDefault": "By default, AdGuard Home uses the following reverse DNS resolvers", + "addItem": "Add item", + "noServerAddressesAdded": "No server addresses added.", + "usePrivateReverseDnsResolvers": "Use private reverse DNS resolvers", + "usePrivateReverseDnsResolversDescription": "Perform reverse DNS lookups for locally served addresses using these upstream servers. If disabled, AdGuard Home responds with NXDOMAIN to all such PTR requests except for clients known from DHCP, /etc/hosts, and so on.", + "enableReverseResolving": "Enable reverse resolving of clients' IP addresses", + "enableReverseResolvingDescription": "Reversely resolve clients' IP addresses into their hostnames by sending PTR queries to corresponding resolvers (private DNS servers for local clients, upstream servers for clients with public IP addresses).", + "dnsServerSettings": "AdGuard Home DNS server settings", + "limitRequestsSecond": "Rate limit per second", + "valueNotNumber": "Value is not a number", + "enableEdns": "Enable EDNS client subnet", + "enableEdnsDescription": "Add the EDNS Client Subnet option (ECS) to upstream requests and log the values sent by the clients in the query log.", + "enableDnssec": "Enable DNSSEC", + "enableDnssecDescription": "Set DNSSEC flag in the outcoming DNS queries and check the result (DNSSEC-enabled resolver is required).", + "disableResolvingIpv6": "Disable resolving of IPv6 addresses", + "disableResolvingIpv6Description": "Drop all DNS queries for IPv6 addresses (type AAAA).", + "blockingMode": "Blocking mode", + "defaultMode": "Default", + "defaultDescription": "Respond with zero IP address (0.0.0.0 for A; :: for AAAA) when blocked by Adblock-style rule; respond with the IP address specified in the rule when blocked by /etc/hosts-style rule", + "refusedDescription": "Respond with REFUSED code", + "nxdomainDescription": "Respond with NXDOMAIN code", + "nullIp": "Null IP", + "nullIpDescription": "Respond with zero IP address (0.0.0.0 for A; :: for AAAA)", + "customIp": "Custom IP", + "customIpDescription": "Respond with a manually set IP address", + "dnsCacheConfig": "DNS cache configuration", + "cacheSize": "Cache size", + "inBytes": "In bytes", + "overrideMinimumTtl": "Override minimum TTL", + "overrideMinimumTtlDescription": "Extend short time-to-live values (seconds) received from the upstream server when caching DNS responses.", + "overrideMaximumTtl": "Override maximum TTL", + "overrideMaximumTtlDescription": "Set a maximum time-to-live value (seconds) for entries in the DNS cache.", + "optimisticCaching": "Optimistic caching", + "optimisticCachingDescription": "Make AdGuard Home respond from the cache even when the entries are expired and also try to refresh them.", + "loadingDnsConfig": "Загрузка конфигурации DNS...", + "dnsConfigNotLoaded": "DNS config could not be loaded.", + "blockingIpv4": "Blocking IPv4", + "blockingIpv4Description": "IP address to be returned for a blocked A request", + "blockingIpv6": "Blocking IPv6", + "blockingIpv6Description": "IP address to be returned for a blocked AAAA request", + "invalidIp": "Invalid IP address", + "dnsConfigSaved": "DNS server configuration saved successfully", + "dnsConfigNotSaved": "The DNS server configuration could not be saved", + "savingConfig": "Saving configuration...", + "someValueNotValid": "Some value is not valid", + "upstreamDnsDescription": "Configure upstream servers and DNS mode", + "bootstrapDnsDescription": "Configure the bootstrap DNS servers", + "privateReverseDnsDescription": "Configure custom DNS resolvers and enable private reverse DNS resolving", + "dnsServerSettingsDescription": "Configure a rate limit, the blocking mode and more", + "dnsCacheConfigDescription": "Configure how the server should manage the DNS cache", + "comment": "Comment", + "address": "Address", + "commentsDescription": "Comments are always preceded by #. You don't have to add it, it will be added automatically.", + "encryptionSettings": "Encryption settings", + "encryptionSettingsDescription": "Encryption (HTTPS/QUIC/TLS) support", + "loadingEncryptionSettings": "Загрузка наÑтроек шифрованиÑ...", + "encryptionSettingsNotLoaded": "Encryption settings couldn't be loaded.", + "enableEncryption": "Enable encryption", + "enableEncryptionTypes": "HTTPS, DNS-over-HTTPS, and DNS-over-TLS", + "enableEncryptionDescription": "If encryption is enabled, AdGuard Home admin interface will work over HTTPS, and the DNS server will listen for requests over DNS-over-HTTPS and DNS-over-TLS.", + "serverConfiguration": "Server configuration", + "domainName": "Domain name", + "domainNameDescription": "If set, AdGuard Home detects ClientIDs, responds to DDR queries, and performs additional connection validations. If not set, these features are disabled. Must match one of the DNS Names in the certificate.", + "redirectHttps": "Redirect to HTTPS automatically", + "httpsPort": "HTTPS port", + "tlsPort": "DNS-over-TLS port", + "dnsOverQuicPort": "DNS-over-QUIC port", + "certificates": "Certificates", + "certificatesDescription": "In order to use encryption, you need to provide a valid SSL certificates chain for your domain. You can get a free certificate on letsencrypt.org or you can buy it from one of the trusted Certificate Authorities.", + "certificateFilePath": "Set a certificates file path", + "pasteCertificateContent": "Paste the certificates contents", + "certificatePath": "Certificate path", + "certificateContent": "Certificate content", + "privateKey": "Private key", + "privateKeyFile": "Set a private key file", + "pastePrivateKey": "Paste the private key contents", + "usePreviousKey": "Use the previously saved key", + "privateKeyPath": "Private key path", + "invalidCertificate": "Invalid certificate", + "invalidPrivateKey": "Invalid private key", + "validatingData": "Validating data", + "dataValid": "Data is valid", + "dataNotValid": "Data not valid", + "encryptionConfigSaved": "Encryption configuration saved successfully", + "encryptionConfigNotSaved": "Encryption configuration could not be saved", + "configError": "Configuration error", + "enterOnlyCertificate": "Enter only the certificate. Do not input the ---BEGIN--- and ---END--- lines.", + "enterOnlyPrivateKey": "Enter only the key. Do not input the ---BEGIN--- and ---END--- lines.", + "noItemsSearch": "No items for that search.", + "clearSearch": "Clear search", + "exitSearch": "Exit search", + "searchClients": "Search clients", + "noClientsSearch": "No clients with that search.", + "customization": "ПерÑонализациÑ", + "customizationDescription": "ÐаÑтройте внешний вид приложениÑ", + "color": "Color", + "useDynamicTheme": "Use dynamic theme", + "red": "Red", + "green": "Green", + "blue": "Blue", + "yellow": "Yellow", + "orange": "Orange", + "brown": "Brown", + "cyan": "Cyan", + "purple": "Purple", + "pink": "Pink", + "deepOrange": "Deep orange", + "indigo": "Indigo", + "useThemeColorStatus": "Use theme color for status", + "useThemeColorStatusDescription": "Replaces green and red status colors with theme color and grey", + "invalidCertificateChain": "Invalid certificate chain", + "validCertificateChain": "Valid certificate chain", + "subject": "Subject", + "issuer": "Issuer", + "expires": "Expires", + "validPrivateKey": "Valid private key", + "expirationDate": "Expiration date", + "keysNotMatch": "Invalid certificate or key: tls: private key does not match public key", + "timeLogs": "Time on logs", + "timeLogsDescription": "Show processing time on logs list", + "hostNames": "Host names", + "keyType": "Key type", + "updateAvailable": "Update available", + "installedVersion": "Installed version", + "newVersion": "New version", + "source": "Source", + "downloadUpdate": "Download update", + "download": "Download", + "doNotRememberAgainUpdate": "Do not remember again for this version", + "downloadingUpdate": "Скачивание", + "completed": "completed", + "permissionNotGranted": "Permission not granted", + "inputSearchTerm": "Input a search term.", + "answers": "Answers", + "copyClipboard": "Copy to clipboard", + "domainCopiedClipboard": "Domain copied to the clipboard", + "clearDnsCache": "Clear DNS cache", + "clearDnsCacheMessage": "Are you sure you want to clear the DNS cache?", + "dnsCacheCleared": "DNS cache cleared successfully", + "clearingDnsCache": "Clearing cache...", + "dnsCacheNotCleared": "DNS cache couldn't be cleared", + "clientsSelected": "clients selected", + "invalidDomain": "Invalid domain", + "loadingBlockedServicesList": "Загрузка ÑпиÑка заблокированных ÑервиÑов...", + "blockedServicesListNotLoaded": "The blocked services list could not be loaded", + "error": "Error", + "updates": "Updates", + "updatesDescription": "Update the AdGuard Home server", + "updateNow": "Update now", + "currentVersion": "Current version", + "requestStartUpdateFailed": "Request to start update failed", + "requestStartUpdateSuccessful": "Request to start update successfull", + "serverUpdated": "Server is updated", + "unknownStatus": "ÐеизвеÑтный ÑтатуÑ", + "checkingUpdates": "Проверка обновлений..", + "checkUpdates": "Проверить обновлениÑ", + "requestingUpdate": "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ...", + "autoupdateUnavailable": "Ðвтообновление недоÑтупно", + "autoupdateUnavailableDescription": "The autoupdate service is not available for this server. It could be because the server is running on a Docker container. You have to update your server manually.", + "minute": "{time} минута", + "minutes": "{time} минут", + "hour": "{time} чаÑ", + "hours": "{time} чаÑов", + "remainingTime": "ОÑтавшееÑÑ Ð²Ñ€ÐµÐ¼Ñ", + "safeSearchSettings": "ÐаÑтройки безопаÑного поиÑка", + "loadingSafeSearchSettings": "Загрузка наÑтроек безопаÑного поиÑка...", + "safeSearchSettingsNotLoaded": "Ошибка при загрузке наÑтроек безопаÑного поиÑка.", + "loadingLogsSettings": "Загрузка наÑтроек журнала...", + "selectOptionLeftColumn": "Select an option of the left column", + "selectClientLeftColumn": "Select a client of the left column", + "disableList": "Disable list", + "enableList": "Enable list", + "screens": "Screens", + "copiedClipboard": "Copied to clipboard", + "seeDetails": "See details", + "listNotAvailable": "List not available", + "copyListUrl": "Copy list URL", + "listUrlCopied": "List URL copied to the clipboard", + "unsupportedVersion": "ÐÐµÐ¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑиÑ", + "unsupprtedVersionMessage": "Поддержка Ñервера верÑии {version} не гарантируетÑÑ. Приложение может работать неÑтабильно Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ верÑией Ñервера.\n\nПриложение AdGuard Home Manager предназначено Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñо Ñтабильными верÑиÑми Ñервера AdGuard Home. Приложение может работать Ñ Ð°Ð»ÑŒÑ„Ð° и бета верÑиÑми Ñервера, но ÑовмеÑтимоÑть и ÑтабильноÑть не гарантируютÑÑ.", + "iUnderstand": "Продолжить", + "appUpdates": "Application updates", + "usingLatestVersion": "You are using the latest version", + "ipLogs": "IP on logs", + "ipLogsDescription": "Show always IP address on logs instead of client name", + "application": "Application", + "combinedChart": "Combined chart", + "combinedChartDescription": "Combine all charts into one", + "statistics": "Statistics", + "errorLoadFilters": "Ошибка при загрузке фильтров.", + "clientRemovedSuccessfully": "ЗапиÑÑŒ уÑпешно удалена", + "editRewriteRule": "Edit rewrite rule", + "dnsRewriteRuleUpdated": "DNS rewrite rule updated successfully", + "dnsRewriteRuleNotUpdated": "DNS rewrite rule could not be updated", + "updatingRule": "Updating rule...", + "serverUpdateNeeded": "Server update needed", + "updateYourServer": "Update your AdGuard Home server to {version} or greater to use this feature.", + "january": "January", + "february": "February", + "march": "March", + "april": "April", + "may": "May", + "june": "June", + "july": "July", + "august": "August", + "september": "September", + "october": "October", + "november": "November", + "december": "December", + "malwarePhising": "Malware/phising", + "queries": "Queries", + "adultSites": "Adult sites", + "quickFilters": "Quick filters", + "searchDomainInternet": "Search domain on the Internet", + "hideServerAddress": "Hide server address", + "hideServerAddressDescription": "Hides the server address on the home screen", + "topItemsOrder": "Top items order", + "topItemsOrderDescription": "Order the home screen top items lists", + "topItemsReorderInfo": "Hold and swipe an item to reorder it.", + "discardChanges": "Discard changes", + "discardChangesDescription": "Are you sure you want to discard the changes?" +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 6d2f1a3..e4e80ab 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -228,7 +228,8 @@ class _MainState extends State
{ Locale('en', ''), Locale('es', ''), Locale('zh', ''), - Locale('zh', 'CN') + Locale('zh', 'CN'), + Locale('ru', '') ], scaffoldMessengerKey: scaffoldMessengerKey, builder: (context, child) { From b531531d2c61280ff6a7da51ad3ae60052ffd487 Mon Sep 17 00:00:00 2001 From: dmitry Date: Sun, 24 Sep 2023 02:08:53 +0500 Subject: [PATCH 304/676] Russian_translation: added some translations --- lib/l10n/app_ru.arb | 208 ++++++++++++++++++++++---------------------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index dc8b29a..93d621f 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -30,7 +30,7 @@ "connected": "Подключено", "selectedDisconnected": "Выбран, но отключён", "connectionDefaultSuccessfully": "Подключение уÑпешно уÑтановлено как «подключение по умолчанию».", - "connectionDefaultFailed": "Подключение не удалоÑÑŒ уÑтановить «подключением по умолчанию».", + "connectionDefaultFailed": "Подключение не удалоÑÑŒ уÑтановить «подключением по умолчанию»", "noSavedConnections": "Ðет Ñохранённых подключений", "cannotConnect": "Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ Ðº Ñерверу", "connectionRemoved": "Подключение удалено уÑпешно", @@ -64,20 +64,20 @@ "theme": "Тема", "light": "СветлаÑ", "dark": "ТёмнаÑ", - "systemDefined": "Определено ÑиÑтемой", + "systemDefined": "СиÑÑ‚ÐµÐ¼Ð½Ð°Ñ Ñ‚ÐµÐ¼Ð°", "close": "Закрыть", "connectedTo": "Подключено к:", "selectedServer": "Selected server:", "noServerSelected": "Ðет выбранных Ñерверов", "manageServer": "Управление Ñервером", "allProtections": "Защита", - "userNotEmpty": "Username cannot be empty", - "passwordNotEmpty": "Password cannot be empty", + "userNotEmpty": "Логин не может быть пуÑтым", + "passwordNotEmpty": "Пароль не может быть пуÑтым", "examplePath": "Ðапример: /adguard", "helperPath": "ЕÑли иÑпользуетÑÑ Ñ€ÐµÐ²ÐµÑ€Ñивный прокÑи", - "aboutApp": "About the application", - "appVersion": "App version", - "createdBy": "Created by", + "aboutApp": "О приложении", + "appVersion": "ВерÑÐ¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ", + "createdBy": "Ðвтор", "clients": "Клиенты", "allowed": "Разрешённые", "blocked": "Заблокированные", @@ -91,22 +91,22 @@ "addClient": "Добавить клиента", "list": "СпиÑок", "ipAddress": "IP-адреÑа", - "ipNotValid": "IP address not valid", + "ipNotValid": "ÐедопуÑтимый IP-адреÑ", "clientAddedSuccessfully": "ЗапиÑÑŒ уÑпешно добавлена в ÑпиÑок", "addingClient": "Добавление клиента...", "clientNotAdded": "Клиент не может быть внеÑён в ÑпиÑок", "clientAnotherList": "Данный клиент уже занеÑён в один из ÑпиÑков", "noSavedLogs": "Ðет Ñохранённых журналов", "logs": "Журналы", - "copyLogsClipboard": "Copy logs to clipboard", - "logsCopiedClipboard": "Logs copied to clipboard", - "advancedSettings": "Advanced settings", - "dontCheckCertificate": "Don't check SSL certificate", - "dontCheckCertificateDescription": "Overrides the server's SSL certificate validation", - "advancedSetupDescription": "Advanced options", - "settingsUpdatedSuccessfully": "ÐаÑтройки уÑпешно обновлены.", - "cannotUpdateSettings": "Settings cannot be updated.", - "restartAppTakeEffect": "Restart the application", + "copyLogsClipboard": "Скопировать журнал в буфер обмена", + "logsCopiedClipboard": "Журнал Ñкопирован в буфер обмена", + "advancedSettings": "Продвинутые наÑтройки", + "dontCheckCertificate": "Ðе проверÑть SSL-Ñертификат", + "dontCheckCertificateDescription": "ПереопределÑет проверку SSL-Ñертификата Ñервера", + "advancedSetupDescription": "РаÑширенные параметры", + "settingsUpdatedSuccessfully": "ÐаÑтройки уÑпешно обновлены", + "cannotUpdateSettings": "Ðевозможно обновить наÑтройки", + "restartAppTakeEffect": "ПерезапуÑтите приложение", "loadingLogs": "Загрузка журнала...", "logsNotLoaded": "Ðевозможно загрузить ÑпиÑок журналов", "processed": "Processed\nNo list", @@ -257,9 +257,9 @@ "listNotDeleted": "The list couldn't be deleted", "deleteList": "Delete list", "deleteListMessage": "Are you sure you want to delete this list? This action can't be reverted.", - "serverSettings": "Server settings", - "serverInformation": "Server information", - "serverInformationDescription": "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñервере и ÑтатуÑ", + "serverSettings": "ÐаÑтройки Ñервера", + "serverInformation": "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñервере", + "serverInformationDescription": "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñервере и текущий ÑтатуÑ", "loadingServerInfo": "Загрузка информации о Ñервере...", "serverInfoNotLoaded": "Ðевозможно загрузить информацию о Ñервере.", "dnsAddresses": "DNS-адреÑа", @@ -267,12 +267,12 @@ "dnsPort": "DNS-порт", "httpPort": "HTTP-порт", "protectionEnabled": "Защита активна", - "dhcpAvailable": "DHCP недоÑтупен", - "serverRunning": "Server running", - "serverVersion": "Server version", - "serverLanguage": "Server language", - "yes": "Yes", - "no": "No", + "dhcpAvailable": "DHCP доÑтупен", + "serverRunning": "Сервер запущен ", + "serverVersion": "ВерÑÐ¸Ñ Ñервера", + "serverLanguage": "Язык Ñервера", + "yes": "Да", + "no": "Ðет", "allowedClients": "Разрешённые клиенты", "disallowedClients": "Запрещённые клиенты", "disallowedDomains": "Ðеразрешённые домены", @@ -390,20 +390,20 @@ "leasesNotRestored": "The leases couldn't be reseted", "dhcpLeases": "Ðренды DHCP", "noLeases": "Ðе найдено аренд DHCP", - "dnsRewrites": "DNS rewrites", - "dnsRewritesDescription": "Configure custom DNS rules", - "loadingRewriteRules": "Loading rewrite rules...", - "rewriteRulesNotLoaded": "DNS rewrite rules could not be loaded.", - "noRewriteRules": "No DNS rewrite rules", - "answer": "Answer", - "deleteDnsRewrite": "Delete DNS rewrite", - "deleteDnsRewriteMessage": "Are you sure you want to delete this DNS rewrite? This action cannot be undone.", - "dnsRewriteRuleDeleted": "DNS rewrite rule deleted successfully", - "dnsRewriteRuleNotDeleted": "The DNS rewrite rule could not be deleted", - "addDnsRewrite": "Add DNS rewrite", - "addingRewrite": "Adding rewrite...", - "dnsRewriteRuleAdded": "DNS rewrite rule addded successfully", - "dnsRewriteRuleNotAdded": "DNS rewrite rule could not be added", + "dnsRewrites": "ПерезапиÑÑŒ DNS-запроÑов", + "dnsRewritesDescription": "ÐаÑтройка пользовательÑких правил DNS", + "loadingRewriteRules": "Загрузка правил перезапиÑи...", + "rewriteRulesNotLoaded": "Ðе удалоÑÑŒ загрузить правила перезапиÑи DNS.", + "noRewriteRules": "Ðет правил перезапиÑи DNS", + "answer": "Ответ", + "deleteDnsRewrite": "Удалить правило перезапиÑи DNS-запроÑов", + "deleteDnsRewriteMessage": "Ð’Ñ‹ уверены, что хотите удалить Ñто правило перезапиÑи DNS? Данное дейÑтвие не может быть отменено.", + "dnsRewriteRuleDeleted": "Правило перезапиÑи DNS уÑпешно удалено", + "dnsRewriteRuleNotDeleted": "Ðе удалоÑÑŒ удалить правило перезапиÑи DNS", + "addDnsRewrite": "Правило перезапиÑи", + "addingRewrite": "Добавление правила перезапиÑи DNS-запроÑов...", + "dnsRewriteRuleAdded": "Правило перезапиÑи DNS уÑпешно добавлено", + "dnsRewriteRuleNotAdded": "Ðе удалоÑÑŒ добавить правило перезапиÑи DNS", "logsSettings": "ÐаÑтройки журнала", "enableLog": "Включить журнал", "clearLogs": "ОчиÑтить журнал", @@ -535,31 +535,31 @@ "noClientsSearch": "No clients with that search.", "customization": "ПерÑонализациÑ", "customizationDescription": "ÐаÑтройте внешний вид приложениÑ", - "color": "Color", - "useDynamicTheme": "Use dynamic theme", - "red": "Red", - "green": "Green", - "blue": "Blue", - "yellow": "Yellow", - "orange": "Orange", - "brown": "Brown", - "cyan": "Cyan", - "purple": "Purple", - "pink": "Pink", - "deepOrange": "Deep orange", - "indigo": "Indigo", - "useThemeColorStatus": "Use theme color for status", - "useThemeColorStatusDescription": "Replaces green and red status colors with theme color and grey", - "invalidCertificateChain": "Invalid certificate chain", - "validCertificateChain": "Valid certificate chain", + "color": "Ð¦Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ñ‚ÐµÐ¼Ð°", + "useDynamicTheme": "ИÑпользовать динамичеÑкую тему", + "red": "КраÑный", + "green": "Зелёный", + "blue": "Синий", + "yellow": "Жёлтый", + "orange": "Оранжевый", + "brown": "Коричневый", + "cyan": "Бирюзовый", + "purple": "Пурпурный", + "pink": "Розовый", + "deepOrange": "Темно-оранжевый", + "indigo": "Индиго", + "useThemeColorStatus": "ИÑпользовать цвет темы Ð´Ð»Ñ Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÑтатуÑа", + "useThemeColorStatusDescription": "ЗаменÑет зеленый и краÑный цвета ÑтатуÑа цветом темы и Ñерым", + "invalidCertificateChain": "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ñ†ÐµÐ¿Ð¾Ñ‡ÐºÐ° Ñертификатов", + "validCertificateChain": "ДейÑÑ‚Ð²Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ†ÐµÐ¿Ð¾Ñ‡ÐºÐ° Ñертификатов", "subject": "Subject", "issuer": "Issuer", "expires": "Expires", "validPrivateKey": "Valid private key", "expirationDate": "Expiration date", "keysNotMatch": "Invalid certificate or key: tls: private key does not match public key", - "timeLogs": "Time on logs", - "timeLogsDescription": "Show processing time on logs list", + "timeLogs": "Ð’Ñ€ÐµÐ¼Ñ Ð² запиÑÑÑ… журнала", + "timeLogsDescription": "Показывать Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ в журнале", "hostNames": "Host names", "keyType": "Key type", "updateAvailable": "Update available", @@ -585,20 +585,20 @@ "invalidDomain": "Invalid domain", "loadingBlockedServicesList": "Загрузка ÑпиÑка заблокированных ÑервиÑов...", "blockedServicesListNotLoaded": "The blocked services list could not be loaded", - "error": "Error", - "updates": "Updates", - "updatesDescription": "Update the AdGuard Home server", - "updateNow": "Update now", - "currentVersion": "Current version", + "error": "Ошибка", + "updates": "ОбновлениÑ", + "updatesDescription": "Обновить AdGuard Home server", + "updateNow": "Обновить ÑейчаÑ", + "currentVersion": "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð²ÐµÑ€ÑиÑ", "requestStartUpdateFailed": "Request to start update failed", "requestStartUpdateSuccessful": "Request to start update successfull", - "serverUpdated": "Server is updated", + "serverUpdated": "Сервер обновлён", "unknownStatus": "ÐеизвеÑтный ÑтатуÑ", "checkingUpdates": "Проверка обновлений..", "checkUpdates": "Проверить обновлениÑ", "requestingUpdate": "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ...", "autoupdateUnavailable": "Ðвтообновление недоÑтупно", - "autoupdateUnavailableDescription": "The autoupdate service is not available for this server. It could be because the server is running on a Docker container. You have to update your server manually.", + "autoupdateUnavailableDescription": "Служба автоматичеÑкого Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½ÐµÐ´Ð¾Ñтупна Ð´Ð»Ñ Ñтого Ñервера. Это может быть ÑвÑзано Ñ Ñ‚ÐµÐ¼, что Ñервер запущен в контейнере Docker. Вам необходимо обновить Ñвой Ñервер вручную.", "minute": "{time} минута", "minutes": "{time} минут", "hour": "{time} чаÑ", @@ -621,44 +621,44 @@ "unsupportedVersion": "ÐÐµÐ¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑиÑ", "unsupprtedVersionMessage": "Поддержка Ñервера верÑии {version} не гарантируетÑÑ. Приложение может работать неÑтабильно Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ верÑией Ñервера.\n\nПриложение AdGuard Home Manager предназначено Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñо Ñтабильными верÑиÑми Ñервера AdGuard Home. Приложение может работать Ñ Ð°Ð»ÑŒÑ„Ð° и бета верÑиÑми Ñервера, но ÑовмеÑтимоÑть и ÑтабильноÑть не гарантируютÑÑ.", "iUnderstand": "Продолжить", - "appUpdates": "Application updates", - "usingLatestVersion": "You are using the latest version", - "ipLogs": "IP on logs", - "ipLogsDescription": "Show always IP address on logs instead of client name", - "application": "Application", - "combinedChart": "Combined chart", - "combinedChartDescription": "Combine all charts into one", - "statistics": "Statistics", + "appUpdates": "ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹", + "usingLatestVersion": "Ð’Ñ‹ иÑпользуете поÑледнюю верÑию", + "ipLogs": "IP-адреÑа в запиÑÑÑ… журнала", + "ipLogsDescription": "Ð’Ñегда показывать IP-Ð°Ð´Ñ€ÐµÑ Ð² запиÑÑÑ… журнала вмеÑто имени клиента", + "application": "Приложение", + "combinedChart": "Объединить графики", + "combinedChartDescription": "Комбинирует вÑе графики в один", + "statistics": "СтатиÑтика", "errorLoadFilters": "Ошибка при загрузке фильтров.", "clientRemovedSuccessfully": "ЗапиÑÑŒ уÑпешно удалена", - "editRewriteRule": "Edit rewrite rule", - "dnsRewriteRuleUpdated": "DNS rewrite rule updated successfully", - "dnsRewriteRuleNotUpdated": "DNS rewrite rule could not be updated", - "updatingRule": "Updating rule...", - "serverUpdateNeeded": "Server update needed", - "updateYourServer": "Update your AdGuard Home server to {version} or greater to use this feature.", - "january": "January", - "february": "February", - "march": "March", - "april": "April", - "may": "May", - "june": "June", - "july": "July", - "august": "August", - "september": "September", - "october": "October", - "november": "November", - "december": "December", - "malwarePhising": "Malware/phising", - "queries": "Queries", - "adultSites": "Adult sites", - "quickFilters": "Quick filters", - "searchDomainInternet": "Search domain on the Internet", - "hideServerAddress": "Hide server address", - "hideServerAddressDescription": "Hides the server address on the home screen", - "topItemsOrder": "Top items order", - "topItemsOrderDescription": "Order the home screen top items lists", - "topItemsReorderInfo": "Hold and swipe an item to reorder it.", - "discardChanges": "Discard changes", - "discardChangesDescription": "Are you sure you want to discard the changes?" + "editRewriteRule": "Редактировать правило", + "dnsRewriteRuleUpdated": "Правило перезапиÑи DNS уÑпешно обновлено", + "dnsRewriteRuleNotUpdated": "Ðевозможно обновить правило перезапиÑи DNS", + "updatingRule": "Обновление правила...", + "serverUpdateNeeded": "ТребуетÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ðµ Ñервера", + "updateYourServer": "Обновите Ñервер AdGuard Home до верÑии {version} или выше, чтобы иÑпользовать Ñту функцию.", + "january": "Январь", + "february": "Февраль", + "march": "Март", + "april": "Ðпрель", + "may": "Май", + "june": "Июнь", + "july": "Июль", + "august": "ÐвгуÑÑ‚", + "september": "СентÑбрь", + "october": "ОктÑбрь", + "november": "ÐоÑбрь", + "december": "Декабрь", + "malwarePhising": "ВредоноÑные/фишинговые Ñайты", + "queries": "ЗапроÑÑ‹", + "adultSites": "«ВзроÑлые» Ñайты", + "quickFilters": "БыÑтрые фильтры", + "searchDomainInternet": "ПоиÑк домена в Интернете", + "hideServerAddress": "Скрывать Ð°Ð´Ñ€ÐµÑ Ñервера", + "hideServerAddressDescription": "Скрывает Ð°Ð´Ñ€ÐµÑ Ñервера на главном Ñкране", + "topItemsOrder": "РаÑположение блоков на главном Ñкране", + "topItemsOrderDescription": "УпорÑдочьте раÑположение блоков на главном Ñкране", + "topItemsReorderInfo": "Чтобы менÑть порÑдок Ñлементов, ÑƒÐ´ÐµÑ€Ð¶Ð¸Ð²Ð°Ñ Ñлемент, перетащите его на новое меÑто.", + "discardChanges": "Отменить изменениÑ", + "discardChangesDescription": "Ð’Ñ‹ уверены, что хотите отменить изменениÑ?" } \ No newline at end of file From cd2c1b9cbddf325511ac6b7a9168a1866ce41870 Mon Sep 17 00:00:00 2001 From: dmitry Date: Sun, 24 Sep 2023 22:39:56 +0500 Subject: [PATCH 305/676] Russian_translation: added all translations --- lib/l10n/app_ru.arb | 636 ++++++++++++++++++++++---------------------- 1 file changed, 318 insertions(+), 318 deletions(-) diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 93d621f..78b3e37 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -2,9 +2,9 @@ "home": "ГлавнаÑ", "settings": "ÐаÑтройки", "connect": "ПодключитьÑÑ", - "servers": "Сервера", + "servers": "Серверы", "createConnection": "Создать подключение", - "name": "Ðазвание подключениÑ", + "name": "ИмÑ", "ipDomain": "IP-Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ домен", "path": "Путь", "port": "Порт", @@ -23,7 +23,7 @@ "invalidUsernamePassword": "Ðеверный логин или пароль", "tooManyAttempts": "Слишком много попыток. Попробуйте позднее.", "cantReachServer": "Ðе удаётÑÑ ÑƒÑтановить Ñоединение Ñ Ñервером. Проверьте наÑтройки подключениÑ", - "sslError": "SSL error. Go to Settings > Advanced settings and enable Override SSL validation.", + "sslError": "Ошибка SSL. Перейдите в «ÐаÑтройки» > «Дополнительные наÑтройки» и активируйте «Ðе проверÑть SSL-Ñертификат».", "unknownError": "ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°", "connectionNotCreated": "Ðе удалоÑÑŒ Ñоздать подключение", "connecting": "Подключение...", @@ -79,13 +79,13 @@ "appVersion": "ВерÑÐ¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ", "createdBy": "Ðвтор", "clients": "Клиенты", - "allowed": "Разрешённые", - "blocked": "Заблокированные", + "allowed": "Разрешён", + "blocked": "Заблокирован", "noClientsList": "СпиÑок клиентов пуÑÑ‚", "activeClients": "Ðктивные", "removeClient": "Удалить запиÑÑŒ", "removeClientMessage": "Ð’Ñ‹ уверены, что хотите удалить данную запиÑÑŒ из ÑпиÑка?", - "confirm": "Подтвердить", + "confirm": "Ок", "removingClient": "Удаление клиента...", "clientNotRemoved": "Клиент не может быть удалён из ÑпиÑка", "addClient": "Добавить клиента", @@ -97,43 +97,43 @@ "clientNotAdded": "Клиент не может быть внеÑён в ÑпиÑок", "clientAnotherList": "Данный клиент уже занеÑён в один из ÑпиÑков", "noSavedLogs": "Ðет Ñохранённых журналов", - "logs": "Журналы", + "logs": "Журнал", "copyLogsClipboard": "Скопировать журнал в буфер обмена", "logsCopiedClipboard": "Журнал Ñкопирован в буфер обмена", - "advancedSettings": "Продвинутые наÑтройки", + "advancedSettings": "Дополнительные наÑтройки", "dontCheckCertificate": "Ðе проверÑть SSL-Ñертификат", "dontCheckCertificateDescription": "ПереопределÑет проверку SSL-Ñертификата Ñервера", "advancedSetupDescription": "РаÑширенные параметры", "settingsUpdatedSuccessfully": "ÐаÑтройки уÑпешно обновлены", - "cannotUpdateSettings": "Ðевозможно обновить наÑтройки", + "cannotUpdateSettings": "Ðе удалоÑÑŒ обновить наÑтройки", "restartAppTakeEffect": "ПерезапуÑтите приложение", "loadingLogs": "Загрузка журнала...", - "logsNotLoaded": "Ðевозможно загрузить ÑпиÑок журналов", - "processed": "Processed\nNo list", + "logsNotLoaded": "Ðе удалоÑÑŒ загрузить журнал", + "processed": "Обработан\nБез ÑпиÑка", "processedRow": "Обработан", - "blockedBlacklist": "Blocked\nBlacklist", - "blockedBlacklistRow": "Заблокированные (чёрный ÑпиÑок)", - "blockedSafeBrowsing": "Blocked\nSafe browsing", + "blockedBlacklist": "Заблокирован\nЧёрный ÑпиÑок", + "blockedBlacklistRow": "Заблокирован (чёрный ÑпиÑок)", + "blockedSafeBrowsing": "Заблокирован\nБезопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ", "blockedSafeBrowsingRow": "Блок. (безопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ)", - "blockedParental": "Blocked\nParental filtering", + "blockedParental": "Заблокирован\nРодительÑкий контроль", "blockedParentalRow": "Блок. (родительÑкий контроль)", - "blockedInvalid": "Blocked\nInvalid", - "blockedInvalidRow": "Blocked (invalid)", - "blockedSafeSearch": "Blocked\nSafe search", + "blockedInvalid": "Заблокировано\nÐеверный", + "blockedInvalidRow": "Заблокирован (Ðеверный)", + "blockedSafeSearch": "Заблокирован\nБезопаÑный поиÑк", "blockedSafeSearchRow": "Блок. (безопаÑный поиÑк)", - "blockedService": "Blocked\nBlocked service", - "blockedServiceRow": "Blocked (blocked service)", - "processedWhitelist": "Processed\nWhitelist", - "processedWhitelistRow": "Разрешённые (белый ÑпиÑок)", - "processedError": "Processed\nError", - "processedErrorRow": "Processed (error)", - "rewrite": "Rewrite", + "blockedService": "Заблокирован\nЗаблокированный ÑервиÑ", + "blockedServiceRow": "Заблокирован (заблокированный ÑервиÑ)", + "processedWhitelist": "Обработан\nБелый ÑпиÑок", + "processedWhitelistRow": "Разрешён (белый ÑпиÑок)", + "processedError": "Обработан\nОшибка", + "processedErrorRow": "Обработан (ошибка)", + "rewrite": "ПерепиÑать", "status": "СтатуÑ", "result": "Результат", "time": "ВремÑ", - "blocklist": "Blocklist", + "blocklist": "Блок-лиÑÑ‚", "request": "ЗапроÑ", - "domain": "Домен", + "domain": "ХоÑÑ‚", "type": "Тип", "clas": "КлаÑÑ", "response": "Ответ", @@ -144,27 +144,27 @@ "deviceIp": "IP-адреÑ", "deviceName": "Ð˜Ð¼Ñ ÑƒÑтройÑтва", "logDetails": "Детали запроÑа", - "blockingRule": "Blocking rule", - "blockDomain": "Block domain", - "couldntGetFilteringStatus": "Ðе удаётÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ð¸", - "unblockDomain": "Unblock domain", - "userFilteringRulesNotUpdated": "Ðевозможно обновить пользовательÑкие правила фильтрации", + "blockingRule": "Правило блокировки", + "blockDomain": "Заблокировать домен", + "couldntGetFilteringStatus": "Ðе удалоÑÑŒ получить журнал фильтрации", + "unblockDomain": "Разблокировать домен", + "userFilteringRulesNotUpdated": "Ðе удалоÑÑŒ обновить пользовательÑкие правила фильтрации", "userFilteringRulesUpdated": "ПользовательÑкие правила фильтрации уÑпешно обновлены", "savingUserFilters": "Сохранение пользовательÑких правил фильтрации...", "filters": "Фильтры", - "logsOlderThan": "Logs older than", + "logsOlderThan": "ЗапиÑи журнала Ñтарше, чем", "responseStatus": "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ñ‚Ð²ÐµÑ‚Ð°", - "selectTime": "Select time", - "notSelected": "Not selected", + "selectTime": "Выберите времÑ", + "notSelected": "Ðе выбрано", "resetFilters": "СброÑить фильтры", "noLogsDisplay": "Ðет запиÑей в журнале", - "noLogsThatOld": "It's possible that there are no logs saved for that selected time. Try selecting a more recent time.", + "noLogsThatOld": "Возможно, что за Ñто выбранное Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи журнала не Ñохранены. Попробуйте выбрать более позднее времÑ.", "apply": "Применить", "selectAll": "Отметить вÑе", "unselectAll": "Отменить выбор вÑех", "all": "Ð’Ñе", "filtered": "Отфильтрованные", - "checkAppLogs": "Check app logs", + "checkAppLogs": "Проверьте журналы приложениÑ", "refresh": "Обновить", "search": "ПоиÑк", "dnsQueries": "DNS-запроÑÑ‹", @@ -188,7 +188,7 @@ "identifierHelper": "IP-адреÑ, CIDR, MAC или ClientID", "noIdentifiers": "Идентификаторы не добавлены", "useGlobalSettings": "Глобальные наÑтройки", - "enableFiltering": "ФильтрациÑ", + "enableFiltering": "Включить фильтрацию", "enableSafeBrowsing": "БезопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ", "enableParentalControl": "РодительÑкий контроль", "enableSafeSearch": "БезопаÑный поиÑк", @@ -204,64 +204,64 @@ "willBeUsedGeneralServers": "Будут иÑпользоватьÑÑ Ð¾Ð±Ñ‰Ð¸Ðµ upstream DNS-Ñервера.", "added": "Сохранённые", "clientUpdatedSuccessfully": "ÐаÑтройки клиента уÑпешно обновлены", - "clientNotUpdated": "Ðевозможно обновить наÑтройки клиента", + "clientNotUpdated": "Ðе удалоÑÑŒ обновить наÑтройки клиента", "clientDeletedSuccessfully": "Клиент уÑпешно удалён", - "clientNotDeleted": "Ðевозможно удалить клиента", + "clientNotDeleted": "Ðе удалоÑÑŒ удалить клиента", "options": "Параметры", "loadingFilters": "Загрузка фильтров...", - "filtersNotLoaded": "Ðевозможно загрузить фильтры.", - "whitelists": "Whitelists", - "blacklists": "Blacklists", - "rules": "Rules", - "customRules": "Custom rules", - "enabledRules": "Enabled rules", - "enabled": "Enabled", - "disabled": "Disabled", - "rule": "Rule", - "addCustomRule": "Add custom rule", - "removeCustomRule": "Remove custom rule", - "removeCustomRuleMessage": "Are you sure you want to remove this custom rule?", - "updatingRules": "Updating custom rules...", - "ruleRemovedSuccessfully": "Rule removed successfully", - "ruleNotRemoved": "Couldn't remove the rule", - "ruleAddedSuccessfully": "Rule added successfully", - "ruleNotAdded": "Couldn't add the rule", - "noCustomFilters": "No custom filters", + "filtersNotLoaded": "Ðе удалоÑÑŒ загрузить фильтры", + "whitelists": "Белые ÑпиÑки DNS", + "blacklists": "Чёрные ÑпиÑки DNS", + "rules": "КоличеÑтво правил", + "customRules": "ПользовательÑкие правила фильтрации", + "enabledRules": "Включенные правила", + "enabled": "Включено", + "disabled": "Отключено", + "rule": "Правило", + "addCustomRule": "Добавить пользовательÑкое правило фильтрации", + "removeCustomRule": "Удалить пользовательÑкое правило фильтрации", + "removeCustomRuleMessage": "Ð’Ñ‹ уверены, что хотите удалить данное пользовательÑкое правило фильтрации?", + "updatingRules": "Обновление пользовательÑких правил фильтрации...", + "ruleRemovedSuccessfully": "Правило уÑпешно удалено", + "ruleNotRemoved": "Ðе удаётÑÑ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ данное правило", + "ruleAddedSuccessfully": "Правило уÑпешно добавлено", + "ruleNotAdded": "Ðе удаётÑÑ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ правило", + "noCustomFilters": "Ðет пользовательÑких правил фильтрации", "noBlockedClients": "Ðет запрещённых клиентов", - "noBlackLists": "No blacklists", - "noWhiteLists": "No whitelists", - "addWhitelist": "Add whitelist", - "addBlacklist": "Add blacklist", - "urlNotValid": "URL is not valid", - "urlAbsolutePath": "URL or absolute path", - "addingList": "Adding list...", - "listAdded": "List added successfully. Items added:", - "listAlreadyAdded": "List already added", - "listUrlInvalid": "List URL invalid", - "listNotAdded": "List couldn't be added", - "listDetails": "List details", - "listType": "List type", - "whitelist": "White list", - "blacklist": "Black list", - "latestUpdate": "Latest update", - "disable": "Выключить", + "noBlackLists": "Ðет чёрных ÑпиÑков", + "noWhiteLists": "Ðет белых ÑпиÑков", + "addWhitelist": "Добавить белый ÑпиÑок", + "addBlacklist": "Добавить чёрный ÑпиÑок", + "urlNotValid": "Ðеверный URL или абÑолютный путь", + "urlAbsolutePath": "URL-Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ абÑолютный путь", + "addingList": "Добавление ÑпиÑка...", + "listAdded": "СпиÑок уÑпешно добавлен. Добавлены:", + "listAlreadyAdded": "СпиÑок уже был добавлен", + "listUrlInvalid": "Ðеверный URL-Ð°Ð´Ñ€ÐµÑ ÑпиÑка", + "listNotAdded": "Ðе удаётÑÑ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ ÑпиÑок", + "listDetails": "Параметры ÑпиÑка", + "listType": "Тип", + "whitelist": "Белый ÑпиÑок", + "blacklist": "Чёрный ÑпиÑок", + "latestUpdate": "ПоÑледнее обновление", + "disable": "Отключить", "enable": "Включить", "currentStatus": "Текущий ÑтатуÑ", - "listDataUpdated": "List data updated successfull", - "listDataNotUpdated": "Couldn't update list data", - "updatingListData": "Updating list data...", - "editWhitelist": "Edit white list", - "editBlacklist": "Edit black list", - "deletingList": "Deleting list...", - "listDeleted": "List deleted successfully", - "listNotDeleted": "The list couldn't be deleted", - "deleteList": "Delete list", - "deleteListMessage": "Are you sure you want to delete this list? This action can't be reverted.", + "listDataUpdated": "Параметры ÑпиÑка уÑпешно обновлены", + "listDataNotUpdated": "Ðе удалоÑÑŒ обновить параметры ÑпиÑка", + "updatingListData": "Обновление параметров ÑпиÑка...", + "editWhitelist": "Редактировать белый ÑпиÑок", + "editBlacklist": "Редактировать чёрный ÑпиÑок", + "deletingList": "Удаление ÑпиÑка...", + "listDeleted": "СпиÑок уÑпешно удалён", + "listNotDeleted": "Ðе удалоÑÑŒ удалить ÑпиÑок", + "deleteList": "Удалить ÑпиÑок", + "deleteListMessage": "Ð’Ñ‹ уверены, что хотите удалить Ñтот ÑпиÑок? Это дейÑтвие Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ.", "serverSettings": "ÐаÑтройки Ñервера", "serverInformation": "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñервере", "serverInformationDescription": "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñервере и текущий ÑтатуÑ", "loadingServerInfo": "Загрузка информации о Ñервере...", - "serverInfoNotLoaded": "Ðевозможно загрузить информацию о Ñервере.", + "serverInfoNotLoaded": "Ðе удалоÑÑŒ загрузить информацию о Ñервере.", "dnsAddresses": "DNS-адреÑа", "seeDnsAddresses": "ПоÑмотреть DNS-адреÑа", "dnsPort": "DNS-порт", @@ -288,53 +288,53 @@ "clientIdentifier": "Идентификатор клиента", "allowClient": "Разрешить клиент", "disallowClient": "Запретить клиента", - "noDisallowedDomains": "No disallowed domains", - "domainNotAdded": "The domain couldn't be added", - "statusSelected": "status selected", - "updateLists": "Update lists", - "checkHostFiltered": "Check host", - "updatingLists": "Updating lists...", - "listsUpdated": "lists updated", - "listsNotUpdated": "Couldn't update lists", - "listsNotLoaded": "Lists couldn't be loaded", - "domainNotValid": "Domain not valid", - "check": "Check", - "checkingHost": "Checking host...", - "errorCheckingHost": "Host couldn't be checked", - "block": "Block", - "unblock": "Unblock", + "noDisallowedDomains": "Ðет запрещенных доменов", + "domainNotAdded": "Ðе удалоÑÑŒ добавить домен", + "statusSelected": "выбран ÑтатуÑ", + "updateLists": "Проверить обновлениÑ", + "checkHostFiltered": "Проверить хоÑÑ‚", + "updatingLists": "Обновление ÑпиÑков...", + "listsUpdated": "ÑпиÑки обновлены", + "listsNotUpdated": "Ðе удалоÑÑŒ обновить ÑпиÑки", + "listsNotLoaded": "Ðе удалоÑÑŒ загрузить ÑпиÑки", + "domainNotValid": "ÐедейÑтвительный домен", + "check": "Проверить", + "checkingHost": "Проверка хоÑта...", + "errorCheckingHost": "Ðе удалоÑÑŒ проверить хоÑÑ‚", + "block": "Запретить", + "unblock": "Разрешить", "custom": "Custom", - "addImportant": "Add $important", - "howCreateRules": "How to create custom rules", - "examples": "Examples", - "example1": "Block access to example.org and all its subdomains.", - "example2": "Unblocks access to example.org and all its subdomains.", - "example3": "Adds a comment.", - "example4": "Block access to domains matching the specified regular expression.", - "moreInformation": "More information", - "addingRule": "Adding rule...", - "deletingRule": "Deleting rule...", - "enablingList": "Enabling list...", - "disablingList": "Disabling list...", - "disableFiltering": "Disable filtering", - "enablingFiltering": "Enabling filtering...", - "disablingFiltering": "Disabling filtering...", - "filteringStatusUpdated": "Filtering status updated successfully", - "filteringStatusNotUpdated": "Filtering status couldn't be updated", - "updateFrequency": "Update frequency", + "addImportant": "Добавить $important", + "howCreateRules": "Как Ñоздать пользовательÑкие правила", + "examples": "Примеры", + "example1": "Заблокировать доÑтуп к домену example.org и вÑем его поддоменам.", + "example2": "Разблокировать доÑтуп к домену example.org и вÑем его поддоменам.", + "example3": "ДобавлÑть комментарий.", + "example4": "Блокировать доÑтуп к доменам, ÑоответÑтвующим заданному регулÑрному выражению.", + "moreInformation": "Больше информации", + "addingRule": "Добавление правила...", + "deletingRule": "Удаление правила...", + "enablingList": "Включение ÑпиÑка...", + "disablingList": "Отключение ÑпиÑка...", + "disableFiltering": "Отключить фильтрацию", + "enablingFiltering": "Включение фильтрации...", + "disablingFiltering": "Отключение фильтрации...", + "filteringStatusUpdated": "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ð¸ уÑпешно обновлен", + "filteringStatusNotUpdated": "Ðе удалоÑÑŒ обновить ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ð¸", + "updateFrequency": "ЧаÑтота обновлениÑ", "never": "Ðикогда", "hour1": "1 чаÑ", "hours12": "12 чаÑов", "hours24": "24 чаÑа", "days3": "3 днÑ", "days7": "7 дней", - "changingUpdateFrequency": "Changing...", - "updateFrequencyChanged": "Update frequency changed successfully", - "updateFrequencyNotChanged": "Updare frecuency couldn't be changed", - "updating": "Updating values...", - "blockedServicesUpdated": "Blocked services updated successfully", - "blockedServicesNotUpdated": "Blocked services couldn't be updated", - "insertDomain": "Insert a domain to check it's stauts.", + "changingUpdateFrequency": "Обновление...", + "updateFrequencyChanged": "ЧаÑтота Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑпешно изменена", + "updateFrequencyNotChanged": "Ðе удаётÑÑ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ чаÑтоту обновлениÑ", + "updating": "Обновление значений...", + "blockedServicesUpdated": "Заблокированные ÑервиÑÑ‹ уÑпешно обновлены", + "blockedServicesNotUpdated": "Ðе удаётÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ заблокированные ÑервиÑÑ‹", + "insertDomain": "Проверить фильтрацию имени хоÑта.", "dhcpSettings": "ÐаÑтройки DHCP", "dhcpSettingsDescription": "ÐаÑтройка DHCP-Ñервера", "dhcpSettingsNotLoaded": "Ðе удалоÑÑŒ загрузить наÑтройки DHCP", @@ -351,43 +351,43 @@ "endOfRange": "Конец диапазона", "ipv6settings": "ÐаÑтройки IPv6", "subnetMask": "МаÑка подÑети", - "subnetMaskNotValid": "Subnet mask not valid", + "subnetMaskNotValid": "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ð¼Ð°Ñка подÑети", "gateway": "Шлюз", - "gatewayNotValid": "Gateway not valid", + "gatewayNotValid": "ÐедопуÑтимый шлюз", "leaseTime": "Ð’Ñ€ÐµÐ¼Ñ Ð°Ñ€ÐµÐ½Ð´Ñ‹", - "seconds": "{time} seconds", - "leaseTimeNotValid": "Lease time not valid", - "restoreConfiguration": "Reset configuration", - "restoreConfigurationMessage": "Are you sure you want to continue? This will reset all the configuration. This action cannot be undone.", - "changeInterface": "Change interface", + "seconds": "{time} Ñекунд", + "leaseTimeNotValid": "ÐедопуÑтимый Ñрок аренды", + "restoreConfiguration": "СброÑить конфигурацию", + "restoreConfigurationMessage": "Ð’Ñ‹ уверены, что хотите продолжить? Это приведет к ÑброÑу вÑей конфигурации. Данное дейÑтвие не может быть отменено.", + "changeInterface": "Изменить интерфейÑ", "savingSettings": "Сохранение наÑтроек...", - "settingsSaved": "Settings saved successfully", - "settingsNotSaved": "Settings couldn't be saved", - "restoringConfig": "Restoring configuration...", - "configRestored": "Configuration reseted successfully", - "configNotRestored": "The configuration couldn't be reseted", + "settingsSaved": "ÐаÑтройки уÑпешно Ñохранены", + "settingsNotSaved": "Ðе удалоÑÑŒ Ñохранить наÑтройки", + "restoringConfig": "ВоÑÑтановление конфигурации...", + "configRestored": "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÑƒÑпешно Ñброшена", + "configNotRestored": "Ðе удалоÑÑŒ произвеÑти ÑÐ±Ñ€Ð¾Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¸", "dhcpStatic": "СтатичеÑкие аренды DHCP", "noDhcpStaticLeases": "Ðе найдено ÑтатичеÑких аренд DHCP", - "deleting": "Deleting...", - "staticLeaseDeleted": "DHCP static lease deleted successfully", - "staticLeaseNotDeleted": "The DHCP static lease could not be deleted", - "deleteStaticLease": "Delete static lease", - "deleteStaticLeaseDescription": "The DHCP static lease will be deleted. This action cannot be reverted.", - "addStaticLease": "Add static lease", - "macAddress": "MAC address", - "macAddressNotValid": "MAC address not valid", - "hostName": "Host name", - "hostNameError": "Host name cannot be empty", - "creating": "Creating...", - "staticLeaseCreated": "DHCP static lease created successfully", - "staticLeaseNotCreated": "The DHCP static lease couldn't be created", - "staticLeaseExists": "The DHCP static lease already exists", - "serverNotConfigured": "Server not configured", - "restoreLeases": "Reset leases", - "restoreLeasesMessage": "Are you sure you want to continue? This will reset all the existing leases. This action cannot be undone.", - "restoringLeases": "Resetting leases...", - "leasesRestored": "Leases reseted successfully", - "leasesNotRestored": "The leases couldn't be reseted", + "deleting": "Удаление...", + "staticLeaseDeleted": "СтатичеÑÐºÐ°Ñ Ð°Ñ€ÐµÐ½Ð´Ð° DHCP уÑпешно удалена", + "staticLeaseNotDeleted": "Ðе удалоÑÑŒ удалить ÑтатичеÑкую аренду DHCP", + "deleteStaticLease": "Удалить ÑтатичеÑкую аренду", + "deleteStaticLeaseDescription": "СтатичеÑÐºÐ°Ñ Ð°Ñ€ÐµÐ½Ð´Ð° DHCP будет удалена. Данное дейÑтвие не может быть отменено.", + "addStaticLease": "Добавить ÑтатичеÑкую аренду", + "macAddress": "MAC-адреÑ", + "macAddressNotValid": "ÐедопуÑтимый MAC-адреÑ", + "hostName": "Ð˜Ð¼Ñ Ñ…Ð¾Ñта", + "hostNameError": "Ð˜Ð¼Ñ Ñ…Ð¾Ñта не может быть пуÑтым", + "creating": "Создание...", + "staticLeaseCreated": "СтатичеÑÐºÐ°Ñ Ð°Ñ€ÐµÐ½Ð´Ð° DHCP уÑпешно Ñоздана", + "staticLeaseNotCreated": "Ðе удалоÑÑŒ Ñоздать ÑтатичеÑкую аренду DHCP", + "staticLeaseExists": "СтатичеÑÐºÐ°Ñ Ð°Ñ€ÐµÐ½Ð´Ð° DHCP уже ÑущеÑтвует", + "serverNotConfigured": "Сервер не наÑтроен", + "restoreLeases": "СброÑить аренды DHCP", + "restoreLeasesMessage": "Ð’Ñ‹ уверены, что хотите продолжить? Это приведет к ÑброÑу вÑех ÑущеÑтвующих аренд DHCP. Данное дейÑтвие не может быть отменено.", + "restoringLeases": "Ð¡Ð±Ñ€Ð¾Ñ Ð°Ñ€ÐµÐ½Ð´ DHCP...", + "leasesRestored": "Ðренды DHCP уÑпешно Ñброшены", + "leasesNotRestored": "Ðе удалоÑÑŒ ÑброÑить аренды DHCP", "dhcpLeases": "Ðренды DHCP", "noLeases": "Ðе найдено аренд DHCP", "dnsRewrites": "ПерезапиÑÑŒ DNS-запроÑов", @@ -400,139 +400,139 @@ "deleteDnsRewriteMessage": "Ð’Ñ‹ уверены, что хотите удалить Ñто правило перезапиÑи DNS? Данное дейÑтвие не может быть отменено.", "dnsRewriteRuleDeleted": "Правило перезапиÑи DNS уÑпешно удалено", "dnsRewriteRuleNotDeleted": "Ðе удалоÑÑŒ удалить правило перезапиÑи DNS", - "addDnsRewrite": "Правило перезапиÑи", + "addDnsRewrite": "Добавить правило", "addingRewrite": "Добавление правила перезапиÑи DNS-запроÑов...", "dnsRewriteRuleAdded": "Правило перезапиÑи DNS уÑпешно добавлено", "dnsRewriteRuleNotAdded": "Ðе удалоÑÑŒ добавить правило перезапиÑи DNS", "logsSettings": "ÐаÑтройки журнала", "enableLog": "Включить журнал", "clearLogs": "ОчиÑтить журнал", - "anonymizeClientIp": "Ðнонимизировать IP-Ð°Ð´Ñ€ÐµÑ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ð°", + "anonymizeClientIp": "Ðнонимизировать клиента", "hours6": "6 чаÑов", "days30": "30 дней", "days90": "90 дней", "retentionTime": "ЧаÑтота ротации журнала запроÑов", - "selectOneItem": "Select one item", - "logSettingsNotLoaded": "Log settings couldn't be loaded.", - "updatingSettings": "Updating settings...", + "selectOneItem": "Выберите один Ñлемент", + "logSettingsNotLoaded": "Ðе удалоÑÑŒ загрузить наÑтройки журнала.", + "updatingSettings": "Обновление наÑтроек...", "logsConfigUpdated": "ÐаÑтройки журнала уÑпешно обновлены", - "logsConfigNotUpdated": "Ðевозможно обновить наÑтройки журнала", + "logsConfigNotUpdated": "Ðе удалоÑÑŒ обновить наÑтройки журнала", "deletingLogs": "ОчиÑтка журнала...", "logsCleared": "Журнал уÑпешно очищен", - "logsNotCleared": "Ðевозможно очиÑтить журнал", + "logsNotCleared": "Ðе удалоÑÑŒ очиÑтить журнал", "runningHomeAssistant": "ЗапуÑкаетÑÑ Ð½Ð° Home Assistant", - "serverError": "Server error", - "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.", - "noBootstrapDns": "No bootstrap DNS servers added.", - "bootstrapDnsServersInfo": "Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams.", - "privateReverseDnsServers": "Private reverse DNS servers", - "privateReverseDnsServersDescription": "The DNS servers that AdGuard Home uses for local PTR queries. These servers are used to resolve PTR requests for addresses in private IP ranges, for example \"192.168.12.34\", using reverse DNS. If not set, AdGuard Home uses the addresses of the default DNS resolvers of your OS except for the addresses of AdGuard Home itself.", - "reverseDnsDefault": "By default, AdGuard Home uses the following reverse DNS resolvers", - "addItem": "Add item", - "noServerAddressesAdded": "No server addresses added.", - "usePrivateReverseDnsResolvers": "Use private reverse DNS resolvers", - "usePrivateReverseDnsResolversDescription": "Perform reverse DNS lookups for locally served addresses using these upstream servers. If disabled, AdGuard Home responds with NXDOMAIN to all such PTR requests except for clients known from DHCP, /etc/hosts, and so on.", - "enableReverseResolving": "Enable reverse resolving of clients' IP addresses", - "enableReverseResolvingDescription": "Reversely resolve clients' IP addresses into their hostnames by sending PTR queries to corresponding resolvers (private DNS servers for local clients, upstream servers for clients with public IP addresses).", - "dnsServerSettings": "AdGuard Home DNS server settings", - "limitRequestsSecond": "Rate limit per second", - "valueNotNumber": "Value is not a number", - "enableEdns": "Enable EDNS client subnet", - "enableEdnsDescription": "Add the EDNS Client Subnet option (ECS) to upstream requests and log the values sent by the clients in the query log.", - "enableDnssec": "Enable DNSSEC", - "enableDnssecDescription": "Set DNSSEC flag in the outcoming DNS queries and check the result (DNSSEC-enabled resolver is required).", - "disableResolvingIpv6": "Disable resolving of IPv6 addresses", - "disableResolvingIpv6Description": "Drop all DNS queries for IPv6 addresses (type AAAA).", - "blockingMode": "Blocking mode", - "defaultMode": "Default", - "defaultDescription": "Respond with zero IP address (0.0.0.0 for A; :: for AAAA) when blocked by Adblock-style rule; respond with the IP address specified in the rule when blocked by /etc/hosts-style rule", - "refusedDescription": "Respond with REFUSED code", - "nxdomainDescription": "Respond with NXDOMAIN code", - "nullIp": "Null IP", - "nullIpDescription": "Respond with zero IP address (0.0.0.0 for A; :: for AAAA)", - "customIp": "Custom IP", - "customIpDescription": "Respond with a manually set IP address", - "dnsCacheConfig": "DNS cache configuration", - "cacheSize": "Cache size", - "inBytes": "In bytes", - "overrideMinimumTtl": "Override minimum TTL", - "overrideMinimumTtlDescription": "Extend short time-to-live values (seconds) received from the upstream server when caching DNS responses.", - "overrideMaximumTtl": "Override maximum TTL", - "overrideMaximumTtlDescription": "Set a maximum time-to-live value (seconds) for entries in the DNS cache.", - "optimisticCaching": "Optimistic caching", - "optimisticCachingDescription": "Make AdGuard Home respond from the cache even when the entries are expired and also try to refresh them.", + "serverError": "Ошибка Ñервера", + "noItems": "ЗдеÑÑŒ нет предметов Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ð°", + "dnsSettings": "ÐаÑтройки DNS", + "dnsSettingsDescription": "ÐаÑтройка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº DNS-Ñерверам", + "upstreamDns": "Upstream DNS-Ñерверы", + "bootstrapDns": "Bootstrap DNS-Ñерверы", + "noUpstreamDns": "Ðе добавлены upstream DNS-Ñерверы.", + "dnsMode": "Режим DNS", + "noDnsMode": "Ðе выбран режим DNS", + "loadBalancing": "РаÑпределение нагрузки", + "parallelRequests": "Параллельные запроÑÑ‹", + "fastestIpAddress": "Самый быÑтрый IP-адреÑ", + "loadBalancingDescription": "Запрашивать по одному Ñерверу за раз. AdGuard Home иÑпользует алгоритм взвешенного Ñлучайного выбора Ñервера, так что Ñамый быÑтрый Ñервер иÑпользуетÑÑ Ñ‡Ð°Ñ‰Ðµ.", + "parallelRequestsDescription": "ИÑпользовать параллельные запроÑÑ‹ ко вÑем Ñерверам одновременно Ð´Ð»Ñ ÑƒÑÐºÐ¾Ñ€ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ запроÑа.", + "fastestIpAddressDescription": "ОпроÑить вÑе DNS-Ñерверы и вернуть Ñамый быÑтрый IP-Ð°Ð´Ñ€ÐµÑ Ð¸Ð· полученных ответов. Это замедлит DNS-запроÑÑ‹, так как нужно будет дождатьÑÑ Ð¾Ñ‚Ð²ÐµÑ‚Ð¾Ð² Ñо вÑех DNS-Ñерверов, но улучшит Ñоединение.", + "noBootstrapDns": "Ðе добавлены bootstrap DNS-Ñерверы.", + "bootstrapDnsServersInfo": "Bootstrap DNS-Ñервера иÑпользуютÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка IP-адреÑов DoH/DoT upstream-Ñерверов, которые вы указали.", + "privateReverseDnsServers": "Приватные Ñерверы Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾Ð³Ð¾ DNS", + "privateReverseDnsServersDescription": "DNS-Ñерверы, которые AdGuard Home иÑпользует Ð´Ð»Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ñ‹Ñ… PTR-запроÑов. Эти Ñерверы иÑпользуютÑÑ, чтобы получить доменные имена клиентов Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ñ‹Ð¼Ð¸ IP-адреÑами, например «192.168.12.34», Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ обратного DNS. ЕÑли ÑпиÑок пуÑÑ‚, AdGuard Home иÑпользует DNS-Ñерверы по умолчанию вашей ОС.", + "reverseDnsDefault": "По умолчанию AdGuard Home иÑпользует Ñледующие обратные DNS-Ñерверы", + "addItem": "Добавить Ñервер", + "noServerAddressesAdded": "ÐдреÑа Ñерверов не указаны.", + "usePrivateReverseDnsResolvers": "ИÑпользовать приватные обратные DNS-резолверы", + "usePrivateReverseDnsResolversDescription": "ПоÑылать обратные DNS-запроÑÑ‹ Ð´Ð»Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾ обÑлуживаемых адреÑов на указанные Ñерверы. ЕÑли отключено, AdGuard Home будет отвечать NXDOMAIN на вÑе подобные PTR-запроÑÑ‹, кроме запроÑов о клиентах, уже извеÑтных по DHCP, /etc/hosts и так далее.", + "enableReverseResolving": "Включить запрашивание доменных имён Ð´Ð»Ñ IP-адреÑов клиентов", + "enableReverseResolvingDescription": "ОпределÑть доменные имена клиентов через PTR-запроÑÑ‹ к ÑоответÑтвующим Ñерверам (приватные DNS-Ñерверы Ð´Ð»Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ñ‹Ñ… клиентов, upstream-Ñерверы Ð´Ð»Ñ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ð¾Ð² Ñ Ð¿ÑƒÐ±Ð»Ð¸Ñ‡Ð½Ñ‹Ð¼ IP-адреÑом).", + "dnsServerSettings": "ÐаÑтройки DNS-Ñервера", + "limitRequestsSecond": "Лимит запроÑов в Ñекунду", + "valueNotNumber": "Значение - не чиÑло", + "enableEdns": "Включить отправку EDNS Client Subnet", + "enableEdnsDescription": "ДобавлÑть опцию EDNS Client Subnet (ECS) к запроÑам к upstream-Ñерверам, а также запиÑывать приÑланные клиентами Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² журнал.", + "enableDnssec": "Включить DNSSEC", + "enableDnssecDescription": "УÑтановите флаг DNSSEC в иÑходÑщих DNS-запроÑах и проверьте результат (требуетÑÑ Ñ€ÐµÐ·Ð¾Ð»Ð²ÐµÑ€ Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ DNSSEC).", + "disableResolvingIpv6": "Отключить обработку IPv6-адреÑов", + "disableResolvingIpv6Description": "Игнорировать вÑе DNS-запроÑÑ‹ адреÑов IPv6 (тип AAAA) и удалÑть IPv6-данные из ответов типа HTTPS.", + "blockingMode": "Режим блокировки", + "defaultMode": "Стандартный", + "defaultDescription": "Отвечает Ñ Ð½ÑƒÐ»ÐµÐ²Ñ‹Ð¼ IP-адреÑом, (0.0.0.0 Ð´Ð»Ñ A; :: Ð´Ð»Ñ AAAA) когда заблокировано правилом в Ñтиле Adblock; отвечает Ñ IP-адреÑом, указанным в правиле, когда заблокировано правилом в Ñтиле файлов hosts", + "refusedDescription": "Отвечает Ñ ÐºÐ¾Ð´Ð¾Ð¼ REFUSED", + "nxdomainDescription": "Отвечает Ñ ÐºÐ¾Ð´Ð¾Ð¼ NXDOMAIN ", + "nullIp": "Ðулевой IP", + "nullIpDescription": "Отвечает Ñ Ð½ÑƒÐ»ÐµÐ²Ñ‹Ð¼ IP-адреÑом (0.0.0.0 Ð´Ð»Ñ A; :: Ð´Ð»Ñ AAAA)", + "customIp": "ПользовательÑкий IP", + "customIpDescription": "Отвечает Ñ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÑŽ наÑтроенным IP-адреÑом", + "dnsCacheConfig": "ÐаÑтройка кеша DNS", + "cacheSize": "Размер кеша", + "inBytes": "Ð’ байтах", + "overrideMinimumTtl": "Переопределить минимальный TTL", + "overrideMinimumTtlDescription": "РаÑширить короткие TTL-Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ (в Ñекундах), полученные Ñ upstream-Ñервера при кешировании DNS-ответов.", + "overrideMaximumTtl": "Переопределить макÑимальный TTL", + "overrideMaximumTtlDescription": "УÑтановить макÑимальное TTL-значение (в Ñекундах) Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñей в DNS-кеше.", + "optimisticCaching": "ОптимиÑтичеÑкое кеширование", + "optimisticCachingDescription": "AdGuard Home будет отвечать из кеша, даже еÑли ответы в нём неактуальны, и попытаетÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ их.", "loadingDnsConfig": "Загрузка конфигурации DNS...", - "dnsConfigNotLoaded": "DNS config could not be loaded.", - "blockingIpv4": "Blocking IPv4", - "blockingIpv4Description": "IP address to be returned for a blocked A request", - "blockingIpv6": "Blocking IPv6", - "blockingIpv6Description": "IP address to be returned for a blocked AAAA request", - "invalidIp": "Invalid IP address", - "dnsConfigSaved": "DNS server configuration saved successfully", - "dnsConfigNotSaved": "The DNS server configuration could not be saved", - "savingConfig": "Saving configuration...", - "someValueNotValid": "Some value is not valid", - "upstreamDnsDescription": "Configure upstream servers and DNS mode", - "bootstrapDnsDescription": "Configure the bootstrap DNS servers", - "privateReverseDnsDescription": "Configure custom DNS resolvers and enable private reverse DNS resolving", - "dnsServerSettingsDescription": "Configure a rate limit, the blocking mode and more", - "dnsCacheConfigDescription": "Configure how the server should manage the DNS cache", - "comment": "Comment", - "address": "Address", - "commentsDescription": "Comments are always preceded by #. You don't have to add it, it will be added automatically.", - "encryptionSettings": "Encryption settings", - "encryptionSettingsDescription": "Encryption (HTTPS/QUIC/TLS) support", + "dnsConfigNotLoaded": "Ðе удалоÑÑŒ загрузить конфигурацию DNS.", + "blockingIpv4": "БлокируетÑÑ IPv4", + "blockingIpv4Description": "IP-адреÑ, который будет возвращен Ð´Ð»Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð¾Ð³Ð¾ запроÑа Ð", + "blockingIpv6": "БлокируетÑÑ IPv6", + "blockingIpv6Description": "IP-адреÑ, который будет возвращен Ð´Ð»Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð¾Ð³Ð¾ запроÑа AAAA", + "invalidIp": "ÐедопуÑтимый IP-адреÑ", + "dnsConfigSaved": "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ DNS-Ñервера Ñохранена уÑпешно", + "dnsConfigNotSaved": "Ðе удалоÑÑŒ Ñохранить конфигурацию DNS-Ñервера", + "savingConfig": "Сохранение конфигурации...", + "someValueNotValid": "Ðекоторое значение недопуÑтимо", + "upstreamDnsDescription": "ÐаÑтройка upstream DNS-Ñерверов и режима DNS", + "bootstrapDnsDescription": "ÐаÑтройка bootstrap DNS-Ñерверов", + "privateReverseDnsDescription": "ÐаÑтройка пользовательÑких DNS-Ñерверов и приватных Ñерверы Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾Ð³Ð¾ DNS", + "dnsServerSettingsDescription": "ÐаÑтройка Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð° количеÑтво запроÑов, режима блокировки и многое другое", + "dnsCacheConfigDescription": "ÐаÑтройка, как Ñервер должен управлÑть кÑшем DNS", + "comment": "Комментарий", + "address": "ÐдреÑ", + "commentsDescription": "КомментариÑм вÑегда предшеÑтвует #. Вам не обÑзательно добавлÑть его, он будет добавлен автоматичеÑки.", + "encryptionSettings": "ÐаÑтройки шифрованиÑ", + "encryptionSettingsDescription": "Поддержка ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ (HTTPS/QUIC/TLS)", "loadingEncryptionSettings": "Загрузка наÑтроек шифрованиÑ...", - "encryptionSettingsNotLoaded": "Encryption settings couldn't be loaded.", - "enableEncryption": "Enable encryption", - "enableEncryptionTypes": "HTTPS, DNS-over-HTTPS, and DNS-over-TLS", - "enableEncryptionDescription": "If encryption is enabled, AdGuard Home admin interface will work over HTTPS, and the DNS server will listen for requests over DNS-over-HTTPS and DNS-over-TLS.", - "serverConfiguration": "Server configuration", - "domainName": "Domain name", - "domainNameDescription": "If set, AdGuard Home detects ClientIDs, responds to DDR queries, and performs additional connection validations. If not set, these features are disabled. Must match one of the DNS Names in the certificate.", - "redirectHttps": "Redirect to HTTPS automatically", - "httpsPort": "HTTPS port", - "tlsPort": "DNS-over-TLS port", - "dnsOverQuicPort": "DNS-over-QUIC port", - "certificates": "Certificates", - "certificatesDescription": "In order to use encryption, you need to provide a valid SSL certificates chain for your domain. You can get a free certificate on letsencrypt.org or you can buy it from one of the trusted Certificate Authorities.", - "certificateFilePath": "Set a certificates file path", - "pasteCertificateContent": "Paste the certificates contents", - "certificatePath": "Certificate path", - "certificateContent": "Certificate content", - "privateKey": "Private key", - "privateKeyFile": "Set a private key file", - "pastePrivateKey": "Paste the private key contents", - "usePreviousKey": "Use the previously saved key", - "privateKeyPath": "Private key path", - "invalidCertificate": "Invalid certificate", - "invalidPrivateKey": "Invalid private key", - "validatingData": "Validating data", - "dataValid": "Data is valid", - "dataNotValid": "Data not valid", - "encryptionConfigSaved": "Encryption configuration saved successfully", - "encryptionConfigNotSaved": "Encryption configuration could not be saved", - "configError": "Configuration error", - "enterOnlyCertificate": "Enter only the certificate. Do not input the ---BEGIN--- and ---END--- lines.", - "enterOnlyPrivateKey": "Enter only the key. Do not input the ---BEGIN--- and ---END--- lines.", - "noItemsSearch": "No items for that search.", - "clearSearch": "Clear search", - "exitSearch": "Exit search", - "searchClients": "Search clients", - "noClientsSearch": "No clients with that search.", + "encryptionSettingsNotLoaded": "Ðе удалоÑÑŒ загрузить наÑтройки шифрованиÑ.", + "enableEncryption": "Включить шифрование", + "enableEncryptionTypes": "HTTPS, DNS-over-HTTPS и DNS-over-TLS", + "enableEncryptionDescription": "ЕÑли порт HTTPS наÑтроен, веб-Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸ÑÑ‚Ñ€Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ AdGuard Home будет доÑтупен через HTTPS, а также DNS-over-HTTPS Ñервер будет доÑтупен по пути '/dns-query'.", + "serverConfiguration": "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñервера", + "domainName": "Доменное имÑ", + "domainNameDescription": "ЕÑли задано, AdGuard Home раÑпознаёт ClientID, отвечает на DDR-запроÑÑ‹, и дополнительно проверÑет ÑоединениÑ. ЕÑли не задано, Ñтот функционал отключён. Должно ÑоответÑтвовать одному из параметров DNS Names в Ñертификате.", + "redirectHttps": "ÐвтоматичеÑки перенаправлÑть на HTTPS", + "httpsPort": "Порт HTTPS", + "tlsPort": "Порт DNS-over-TLS", + "dnsOverQuicPort": "Порт DNS-over-QUIC", + "certificates": "Сертификаты", + "certificatesDescription": "Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°Ð¼ необходимо предоÑтавить корректную цепочку SSL-Ñертификатов Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ домена. Ð’Ñ‹ можете получить беÑплатный Ñертификат на letsencrypt.org или вы можете купить его у одного из доверенных Центров Сертификации.", + "certificateFilePath": "Указать путь к файлу Ñертификатов", + "pasteCertificateContent": "Ð’Ñтавить Ñодержимое Ñертификатов", + "certificatePath": "Путь к Ñертификату", + "certificateContent": "Содержимое Ñертификата", + "privateKey": "Закрытый ключ", + "privateKeyFile": "Указать файл закрытого ключа", + "pastePrivateKey": "Ð’Ñтавить Ñодержимое закрытого ключа", + "usePreviousKey": "ИÑпользовать Ñохранённый ранее ключ", + "privateKeyPath": "Путь к закрытому ключу", + "invalidCertificate": "Цепочка Ñертификатов не прошла проверку", + "invalidPrivateKey": "Ðекорректный приватный ключ", + "validatingData": "Проверка данных", + "dataValid": "Данные дейÑтвительны", + "dataNotValid": "ÐедопуÑтимые данные", + "encryptionConfigSaved": "ÐаÑтройки ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÑƒÑпешно Ñохранены", + "encryptionConfigNotSaved": "Ðе удаётÑÑ Ñохранить наÑтройки шифрованиÑ", + "configError": "Ошибка конфигурации", + "enterOnlyCertificate": "Введите только Ñертификат. Ðе вводите Ñтроки ---BEGIN--- и ---END---.", + "enterOnlyPrivateKey": "Введите только ключ. Ðе вводите Ñтроки ---BEGIN--- и ---END---.", + "noItemsSearch": "Ðичего не найдено по данному запроÑу.", + "clearSearch": "ОчиÑтить поиÑк", + "exitSearch": "Покинуть поиÑк", + "searchClients": "ПоиÑк клиентов", + "noClientsSearch": "Ðе найдено клиентов по данному запроÑу.", "customization": "ПерÑонализациÑ", "customizationDescription": "ÐаÑтройте внешний вид приложениÑ", "color": "Ð¦Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ñ‚ÐµÐ¼Ð°", @@ -550,48 +550,48 @@ "indigo": "Индиго", "useThemeColorStatus": "ИÑпользовать цвет темы Ð´Ð»Ñ Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÑтатуÑа", "useThemeColorStatusDescription": "ЗаменÑет зеленый и краÑный цвета ÑтатуÑа цветом темы и Ñерым", - "invalidCertificateChain": "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ñ†ÐµÐ¿Ð¾Ñ‡ÐºÐ° Ñертификатов", + "invalidCertificateChain": "Цепочка Ñертификатов не прошла проверку", "validCertificateChain": "ДейÑÑ‚Ð²Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ†ÐµÐ¿Ð¾Ñ‡ÐºÐ° Ñертификатов", - "subject": "Subject", - "issuer": "Issuer", - "expires": "Expires", - "validPrivateKey": "Valid private key", - "expirationDate": "Expiration date", - "keysNotMatch": "Invalid certificate or key: tls: private key does not match public key", + "subject": "Субъект", + "issuer": "Издатель", + "expires": "ИÑтекает", + "validPrivateKey": "ДейÑтвительный закрытый ключ", + "expirationDate": "ИÑтекает", + "keysNotMatch": "ÐедейÑтвительный Ñертификат или ключ: tls: закрытый ключ не ÑоответÑтвует открытому ключу", "timeLogs": "Ð’Ñ€ÐµÐ¼Ñ Ð² запиÑÑÑ… журнала", "timeLogsDescription": "Показывать Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ в журнале", - "hostNames": "Host names", - "keyType": "Key type", - "updateAvailable": "Update available", - "installedVersion": "Installed version", - "newVersion": "New version", - "source": "Source", - "downloadUpdate": "Download update", - "download": "Download", - "doNotRememberAgainUpdate": "Do not remember again for this version", + "hostNames": "Имена хоÑтов", + "keyType": "Тип ключа", + "updateAvailable": "ДоÑтупно обновление", + "installedVersion": "УÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ð°Ñ Ð²ÐµÑ€ÑиÑ", + "newVersion": "ÐÐ¾Ð²Ð°Ñ Ð²ÐµÑ€ÑиÑ", + "source": "ИÑточник", + "downloadUpdate": "Загрузить обновление", + "download": "Скачать", + "doNotRememberAgainUpdate": "Ðе запоминать Ñнова Ð´Ð»Ñ Ñтой верÑии", "downloadingUpdate": "Скачивание", - "completed": "completed", - "permissionNotGranted": "Permission not granted", - "inputSearchTerm": "Input a search term.", - "answers": "Answers", - "copyClipboard": "Copy to clipboard", - "domainCopiedClipboard": "Domain copied to the clipboard", - "clearDnsCache": "Clear DNS cache", - "clearDnsCacheMessage": "Are you sure you want to clear the DNS cache?", - "dnsCacheCleared": "DNS cache cleared successfully", - "clearingDnsCache": "Clearing cache...", - "dnsCacheNotCleared": "DNS cache couldn't be cleared", - "clientsSelected": "clients selected", - "invalidDomain": "Invalid domain", + "completed": "завершено", + "permissionNotGranted": "Разрешение не предоÑтавлено", + "inputSearchTerm": "Введите поиÑковый запроÑ.", + "answers": "Ответы", + "copyClipboard": "Скопировать в буфер обмена", + "domainCopiedClipboard": "Домен Ñкопирован в буфер обмена", + "clearDnsCache": "ОчиÑтить кÑш DNS", + "clearDnsCacheMessage": "Ð’Ñ‹ уверены, что хотите очиÑтить кÑш DNS?", + "dnsCacheCleared": "КÑш DNS очищен уÑпешно", + "clearingDnsCache": "ОчиÑтка кÑша...", + "dnsCacheNotCleared": "Ðе удалоÑÑŒ очиÑтить кÑш DNS", + "clientsSelected": "выбранные клиенты", + "invalidDomain": "ÐедопуÑтимый домен", "loadingBlockedServicesList": "Загрузка ÑпиÑка заблокированных ÑервиÑов...", - "blockedServicesListNotLoaded": "The blocked services list could not be loaded", + "blockedServicesListNotLoaded": "Ðе удалоÑÑŒ загрузить ÑпиÑок заблокированных Ñлужб", "error": "Ошибка", "updates": "ОбновлениÑ", "updatesDescription": "Обновить AdGuard Home server", "updateNow": "Обновить ÑейчаÑ", "currentVersion": "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð²ÐµÑ€ÑиÑ", - "requestStartUpdateFailed": "Request to start update failed", - "requestStartUpdateSuccessful": "Request to start update successfull", + "requestStartUpdateFailed": "Ðе удалоÑÑŒ выполнить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° запуÑк обновлениÑ", + "requestStartUpdateSuccessful": "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° запуÑк Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑпешен", "serverUpdated": "Сервер обновлён", "unknownStatus": "ÐеизвеÑтный ÑтатуÑ", "checkingUpdates": "Проверка обновлений..", @@ -608,16 +608,16 @@ "loadingSafeSearchSettings": "Загрузка наÑтроек безопаÑного поиÑка...", "safeSearchSettingsNotLoaded": "Ошибка при загрузке наÑтроек безопаÑного поиÑка.", "loadingLogsSettings": "Загрузка наÑтроек журнала...", - "selectOptionLeftColumn": "Select an option of the left column", - "selectClientLeftColumn": "Select a client of the left column", - "disableList": "Disable list", - "enableList": "Enable list", - "screens": "Screens", - "copiedClipboard": "Copied to clipboard", - "seeDetails": "See details", - "listNotAvailable": "List not available", - "copyListUrl": "Copy list URL", - "listUrlCopied": "List URL copied to the clipboard", + "selectOptionLeftColumn": "Выберите опцию в левой колонке", + "selectClientLeftColumn": "Выберите клиента в левой колонке", + "disableList": "Отключить ÑпиÑок", + "enableList": "Включить ÑпиÑок", + "screens": "Экраны", + "copiedClipboard": "Скопировано в буфер обмена", + "seeDetails": "Смотрите подробноÑти", + "listNotAvailable": "СпиÑок недоÑтупен", + "copyListUrl": "Скопировать URL", + "listUrlCopied": "URL ÑпиÑка Ñохранён в буфер обмена", "unsupportedVersion": "ÐÐµÐ¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑиÑ", "unsupprtedVersionMessage": "Поддержка Ñервера верÑии {version} не гарантируетÑÑ. Приложение может работать неÑтабильно Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ верÑией Ñервера.\n\nПриложение AdGuard Home Manager предназначено Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñо Ñтабильными верÑиÑми Ñервера AdGuard Home. Приложение может работать Ñ Ð°Ð»ÑŒÑ„Ð° и бета верÑиÑми Ñервера, но ÑовмеÑтимоÑть и ÑтабильноÑть не гарантируютÑÑ.", "iUnderstand": "Продолжить", @@ -633,7 +633,7 @@ "clientRemovedSuccessfully": "ЗапиÑÑŒ уÑпешно удалена", "editRewriteRule": "Редактировать правило", "dnsRewriteRuleUpdated": "Правило перезапиÑи DNS уÑпешно обновлено", - "dnsRewriteRuleNotUpdated": "Ðевозможно обновить правило перезапиÑи DNS", + "dnsRewriteRuleNotUpdated": "Ðе удалоÑÑŒ обновить правило перезапиÑи DNS", "updatingRule": "Обновление правила...", "serverUpdateNeeded": "ТребуетÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ðµ Ñервера", "updateYourServer": "Обновите Ñервер AdGuard Home до верÑии {version} или выше, чтобы иÑпользовать Ñту функцию.", From 525facc538865b848c98cc3db8f72d4885ab728d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 4 Oct 2023 19:20:43 +0200 Subject: [PATCH 306/676] Bug fixes --- lib/models/dhcp.dart | 4 +- lib/models/dns_info.dart | 2 +- lib/providers/servers_provider.dart | 14 +- lib/screens/home/home.dart | 2 +- lib/screens/home/management_modal.dart | 2 +- lib/screens/settings/dns/cache_config.dart | 2 +- lib/screens/top_items/top_items.dart | 2 +- lib/services/http_requests.dart | 258 ++++++++++++--------- lib/widgets/add_server_modal.dart | 6 + 9 files changed, 171 insertions(+), 121 deletions(-) diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index aaf4a42..c04ecc9 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -72,8 +72,8 @@ class DhcpStatus { factory DhcpStatus.fromJson(Map json) => DhcpStatus( interfaceName: json["interface_name"], - v4: IpVersion.fromJson(json["v4"]), - v6: IpVersion.fromJson(json["v6"]), + v4: json["v4"] != null ? IpVersion.fromJson(json["v4"]) : null, + v6: json["v6"] != null ? IpVersion.fromJson(json["v6"]) : null, leases: List.from(json["leases"].map((x) => Lease.fromJson(x))), staticLeases: List.from(json["static_leases"].map((x) => Lease.fromJson(x))), enabled: json["enabled"], diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 138efa3..5ab3cc2 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -12,7 +12,7 @@ class DnsInfo { int? cacheSize; int? cacheTtlMin; int? cacheTtlMax; - bool cacheOptimistic; + bool? cacheOptimistic; bool resolveClients; bool usePrivatePtrResolvers; List localPtrUpstreams; diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index c745260..601e149 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -169,12 +169,14 @@ class ServersProvider with ChangeNotifier { void checkServerUpdatesAvailable({ required Server server, + ApiClient? apiClient }) async { + final client = apiClient ?? _apiClient; setUpdateAvailableLoadStatus(LoadStatus.loading, true); - final result = await _apiClient!.checkServerUpdates(); + final result = await client!.checkServerUpdates(); if (result['result'] == 'success') { UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); - final gitHubResult = await _apiClient!.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); + final gitHubResult = await client!.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); if (gitHubResult['result'] == 'success') { data.changelog = gitHubResult['body']; } @@ -186,11 +188,12 @@ class ServersProvider with ChangeNotifier { } } - Future initializateServer(Server server) async { + Future initializateServer(Server server, ApiClient apiClient) async { final serverStatus = await _apiClient!.getServerStatus(); if (serverStatus['result'] == 'success') { checkServerUpdatesAvailable( // Do not await server: server, + apiClient: apiClient ); } } @@ -222,8 +225,9 @@ class ServersProvider with ChangeNotifier { if (defaultServer != null) { _selectedServer = defaultServer; - _apiClient = ApiClient(server: defaultServer); - initializateServer(defaultServer); + final client = ApiClient(server: defaultServer); + _apiClient = client; + initializateServer(defaultServer, client); } } else { diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index a37eee7..7acfa63 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -304,7 +304,7 @@ class _HomeState extends State { displacement: 95, onRefresh: () async { final result = await statusProvider.getServerStatus(); - if (result == false) { + if (mounted && result == false) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverStatusNotRefreshed, diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index aaeaab7..d23ddd4 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -80,7 +80,7 @@ class _ManagementModalState extends State with SingleTickerProv newStatus: value, time: time ); - if (result != null) { + if (mounted && result != null) { if (result != false) { appConfigProvider.addLog(result); } diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index cd2968b..eb5aad3 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -58,7 +58,7 @@ class _CacheConfigDnsScreenState extends State { cacheSizeController.text = dnsProvider.dnsInfo!.cacheSize.toString(); overrideMinTtlController.text = dnsProvider.dnsInfo!.cacheTtlMin.toString(); overrideMaxTtlController.text = dnsProvider.dnsInfo!.cacheTtlMax.toString(); - optimisticCache = dnsProvider.dnsInfo!.cacheOptimistic; + optimisticCache = dnsProvider.dnsInfo!.cacheOptimistic ?? false; validData = true; super.initState(); } diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 6e9af74..f536b47 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -130,7 +130,7 @@ class _TopItemsScreenState extends State { body: RefreshIndicator( onRefresh: () async { final result = await statusProvider.getServerStatus(); - if (result == false) { + if (mounted && result == false) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverStatusNotRefreshed, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 85de805..c2b2c59 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -20,6 +20,7 @@ import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/constants/urls.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; Future> apiRequest({ @@ -270,80 +271,107 @@ class ApiClient { }); Future getServerVersion() async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/status', - type: 'get_server_version' - ); + try { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/status', + type: 'get_server_version' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200 && result['body'] != null) { - return { - 'result': 'success', - 'data': jsonDecode(result['body'])['version'] - }; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200 && result['body'] != null) { + return { + 'result': 'success', + 'data': jsonDecode(result['body'])['version'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_version', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_server_version', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } - } - else { - return result; + } catch (e) { + Sentry.captureException(e); + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_version', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + resBody: e.toString() + ) + }; } } Future getServerStatus() async { - final result = await Future.wait([ - apiRequest(server: server, method: 'get', urlPath: '/stats', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/filtering/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/safesearch/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/safebrowsing/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/parental/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'server_status'), - ]); + try { + final result = await Future.wait([ + apiRequest(server: server, method: 'get', urlPath: '/stats', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/filtering/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/safesearch/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/safebrowsing/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/parental/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'server_status'), + ]); - if ( - result[0]['hasResponse'] == true && - result[1]['hasResponse'] == true && - result[2]['hasResponse'] == true && - result[3]['hasResponse'] == true && - result[4]['hasResponse'] == true && - result[5]['hasResponse'] == true && - result[6]['hasResponse'] == true - ) { if ( - result[0]['statusCode'] == 200 && - result[1]['statusCode'] == 200 && - result[2]['statusCode'] == 200 && - result[3]['statusCode'] == 200 && - result[4]['statusCode'] == 200 && - result[5]['statusCode'] == 200 && - result[6]['statusCode'] == 200 + result[0]['hasResponse'] == true && + result[1]['hasResponse'] == true && + result[2]['hasResponse'] == true && + result[3]['hasResponse'] == true && + result[4]['hasResponse'] == true && + result[5]['hasResponse'] == true && + result[6]['hasResponse'] == true ) { - final Map mappedData = { - 'stats': jsonDecode(result[0]['body']), - 'clients': jsonDecode(result[6]['body'])['clients'], - 'status': jsonDecode(result[1]['body']), - 'filtering': jsonDecode(result[2]['body']), - 'safeSearch': jsonDecode(result[3]['body']), - 'safeBrowsingEnabled': jsonDecode(result[4]['body']), - 'parentalControlEnabled': jsonDecode(result[5]['body']), - }; - return { - 'result': 'success', - 'data': ServerStatus.fromJson(mappedData) - }; + if ( + result[0]['statusCode'] == 200 && + result[1]['statusCode'] == 200 && + result[2]['statusCode'] == 200 && + result[3]['statusCode'] == 200 && + result[4]['statusCode'] == 200 && + result[5]['statusCode'] == 200 && + result[6]['statusCode'] == 200 + ) { + final Map mappedData = { + 'stats': jsonDecode(result[0]['body']), + 'clients': jsonDecode(result[6]['body'])['clients'], + 'status': jsonDecode(result[1]['body']), + 'filtering': jsonDecode(result[2]['body']), + 'safeSearch': jsonDecode(result[3]['body']), + 'safeBrowsingEnabled': jsonDecode(result[4]['body']), + 'parentalControlEnabled': jsonDecode(result[5]['body']), + }; + return { + 'result': 'success', + 'data': ServerStatus.fromJson(mappedData) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode']).toString(), + resBody: result.map((res) => res['body']).toString() + ) + }; + } } else { return { @@ -351,24 +379,23 @@ class ApiClient { 'log': AppLog( type: 'get_server_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result.map((res) => res['statusCode']).toString(), - resBody: result.map((res) => res['body']).toString() + message: 'no_response', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString() ) }; } - } - else { + } catch (e) { + Sentry.captureException(e); return { - 'result': 'error', - 'log': AppLog( - type: 'get_server_status', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString() - ) - }; + 'result': 'error', + 'log': AppLog( + type: 'get_server_status', + dateTime: DateTime.now(), + message: 'no_response', + resBody: e.toString() + ) + }; } } @@ -2004,34 +2031,48 @@ class ApiClient { } Future checkServerUpdates() async { - final result = await Future.wait([ - apiRequest( - urlPath: '/version.json', - method: 'post', - server: server, - type: 'check_server_updates', - body: { - "recheck_now": true - } - ), - apiRequest( - urlPath: '/status', - method: 'get', - server: server, - type: 'check_server_updates', - ), - ]); + try { + final result = await Future.wait([ + apiRequest( + urlPath: '/version.json', + method: 'post', + server: server, + type: 'check_server_updates', + body: { + "recheck_now": true + } + ), + apiRequest( + urlPath: '/status', + method: 'get', + server: server, + type: 'check_server_updates', + ), + ]); - if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - final Map obj = { - ...jsonDecode(result[0]['body']), - 'current_version': ServerInfoData.fromJson(jsonDecode(result[1]['body'])).version - }; - return { - 'result': 'success', - 'data': obj - }; + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { + final Map obj = { + ...jsonDecode(result[0]['body']), + 'current_version': ServerInfoData.fromJson(jsonDecode(result[1]['body'])).version + }; + return { + 'result': 'success', + 'data': obj + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -2039,22 +2080,21 @@ class ApiClient { 'log': AppLog( type: 'get_filtering_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: 'no_response', statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } - } - else { + } catch (e) { + Sentry.captureException(e); return { 'result': 'error', 'log': AppLog( type: 'get_filtering_status', dateTime: DateTime.now(), message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), + resBody: e.toString(), ) }; } diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 362eee9..c7604a1 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -256,6 +256,8 @@ class _AddServerModalState extends State { ? await loginHA(serverObj) : await login(serverObj); + if (!mounted) return; + if (result['result'] == 'success') { if (serverObj.user != null && serverObj.password != null) { serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); @@ -268,6 +270,8 @@ class _AddServerModalState extends State { final serverStatus = await apiClient.getServerStatus(); + if (!mounted) return; + if (serverStatus['result'] == 'success') { statusProvider.setServerStatusData( data: serverStatus['data'] @@ -380,12 +384,14 @@ class _AddServerModalState extends State { ? await loginHA(serverObj) : await login(serverObj); + if (!mounted) return; if (result['result'] == 'success') { if (serverObj.user != null && serverObj.password != null) { serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); } final serverSaved = await serversProvider.editServer(serverObj); + if (!mounted) return; if (serverSaved == null) { final ApiClient apiClient = ApiClient(server: serverObj); final version = await apiClient.getServerVersion(); From b2e8413559f7657b7fe37176917aba299f4097cd Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Thu, 5 Oct 2023 09:06:08 +0800 Subject: [PATCH 307/676] Update app_zh_CN.arb --- lib/l10n/app_zh_CN.arb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb index f6a5eaf..796a6c6 100644 --- a/lib/l10n/app_zh_CN.arb +++ b/lib/l10n/app_zh_CN.arb @@ -653,5 +653,12 @@ "queries": "查询", "adultSites": "æˆäººç½‘ç«™", "quickFilters": "状æ€è¿‡æ»¤å™¨", - "searchDomainInternet": "在互è”网上æœç´¢è¯¥åŸŸå" + "searchDomainInternet": "在互è”网上æœç´¢è¯¥åŸŸå", + "hideServerAddress": "éšè—æœåŠ¡å™¨åœ°å€", + "hideServerAddressDescription": "在主页上éšè—æœåŠ¡å™¨åœ°å€", + "topItemsOrder": "顶部项目顺åº", + "topItemsOrderDescription": "排列主页顶部项目列表", + "topItemsReorderInfo": "按ä½å¹¶æ»‘åŠ¨ä¸€ä¸ªé¡¹ç›®ä»¥é‡æ–°æŽ’åºã€‚", + "discardChanges": "放弃更改", + "discardChangesDescription": "æ‚¨ç¡®å®šè¦æ”¾å¼ƒæ›´æ”¹å—?" } From bc967c16527c0d583681ca9b557c47977514f10e Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Thu, 5 Oct 2023 09:07:13 +0800 Subject: [PATCH 308/676] Update app_zh.arb --- lib/l10n/app_zh.arb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index f6a5eaf..796a6c6 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -653,5 +653,12 @@ "queries": "查询", "adultSites": "æˆäººç½‘ç«™", "quickFilters": "状æ€è¿‡æ»¤å™¨", - "searchDomainInternet": "在互è”网上æœç´¢è¯¥åŸŸå" + "searchDomainInternet": "在互è”网上æœç´¢è¯¥åŸŸå", + "hideServerAddress": "éšè—æœåŠ¡å™¨åœ°å€", + "hideServerAddressDescription": "在主页上éšè—æœåŠ¡å™¨åœ°å€", + "topItemsOrder": "顶部项目顺åº", + "topItemsOrderDescription": "排列主页顶部项目列表", + "topItemsReorderInfo": "按ä½å¹¶æ»‘åŠ¨ä¸€ä¸ªé¡¹ç›®ä»¥é‡æ–°æŽ’åºã€‚", + "discardChanges": "放弃更改", + "discardChangesDescription": "æ‚¨ç¡®å®šè¦æ”¾å¼ƒæ›´æ”¹å—?" } From 210606306ab63487fc4747696adcab829bc5bd66 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 5 Oct 2023 09:15:19 +0200 Subject: [PATCH 309/676] Fixed db create issue --- lib/providers/servers_provider.dart | 2 +- lib/services/db/database.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 601e149..3a0e1ad 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -176,7 +176,7 @@ class ServersProvider with ChangeNotifier { final result = await client!.checkServerUpdates(); if (result['result'] == 'success') { UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); - final gitHubResult = await client!.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); + final gitHubResult = await client.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); if (gitHubResult['result'] == 'success') { data.changelog = gitHubResult['body']; } diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index 66bd269..4562b81 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -122,7 +122,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { onCreate: (Database db, int version) async { await db.execute("CREATE TABLE servers (id TEXT PRIMARY KEY, name TEXT, connectionMethod TEXT, domain TEXT, path TEXT, port INTEGER, user TEXT, password TEXT, defaultServer INTEGER, authToken TEXT, runningOnHa INTEGER)"); await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showTimeLogs NUMERIC, showIpLogs NUMERIC, combinedChart NUMERIC, doNotRememberVersion TEXT, hideServerAddress NUMERIC, homeTopItemsOrder TEXT)"); - await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs, combinedChart, hideServerAddress, homeTopItemsOrder) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0, 0, 0, $homeTopItemsDefaultOrderString)"); + await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs, combinedChart, hideServerAddress, homeTopItemsOrder) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0, 0, 0, '$homeTopItemsDefaultOrderString')"); }, onUpgrade: (Database db, int oldVersion, int newVersion) async { if (oldVersion == 1) { From b311dfe57ba12d1922db6cc0729609fce30dca28 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 5 Oct 2023 09:42:34 +0200 Subject: [PATCH 310/676] Improved database strings format --- lib/services/db/database.dart | 73 +++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index 4562b81..5fed50f 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -120,9 +120,76 @@ Future> loadDb(bool acceptsDynamicTheme) async { 'adguard_home_manager.db', version: 9, onCreate: (Database db, int version) async { - await db.execute("CREATE TABLE servers (id TEXT PRIMARY KEY, name TEXT, connectionMethod TEXT, domain TEXT, path TEXT, port INTEGER, user TEXT, password TEXT, defaultServer INTEGER, authToken TEXT, runningOnHa INTEGER)"); - await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showTimeLogs NUMERIC, showIpLogs NUMERIC, combinedChart NUMERIC, doNotRememberVersion TEXT, hideServerAddress NUMERIC, homeTopItemsOrder TEXT)"); - await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs, combinedChart, hideServerAddress, homeTopItemsOrder) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0, 0, 0, '$homeTopItemsDefaultOrderString')"); + await db.execute( + """ + CREATE TABLE + servers ( + id TEXT PRIMARY KEY, + name TEXT, + connectionMethod TEXT, + domain TEXT, + path TEXT, + port INTEGER, + user TEXT, + password TEXT, + defaultServer INTEGER, + authToken TEXT, + runningOnHa INTEGER + ) + """ + ); + + await db.execute( + """ + CREATE TABLE + appConfig ( + theme NUMERIC, + overrideSslCheck NUMERIC, + hideZeroValues NUMERIC, + useDynamicColor NUMERIC, + staticColor NUMERIC, + useThemeColorForStatus NUMERIC, + showTimeLogs NUMERIC, + showIpLogs NUMERIC, + combinedChart NUMERIC, + doNotRememberVersion TEXT, + hideServerAddress NUMERIC, + homeTopItemsOrder TEXT + ) + """ + ); + + await db.execute( + """ + INSERT INTO + appConfig ( + theme, + overrideSslCheck, + hideZeroValues, + useDynamicColor, + staticColor, + useThemeColorForStatus, + showTimeLogs, + showIpLogs, + combinedChart, + hideServerAddress, + homeTopItemsOrder + ) + VALUES ( + 0, + 0, + 0, + ${acceptsDynamicTheme == true ? 1 : 0}, + 0, + 0, + 0, + 0, + 0, + 0, + '$homeTopItemsDefaultOrderString' + ) + """ + ); }, onUpgrade: (Database db, int oldVersion, int newVersion) async { if (oldVersion == 1) { From 2389e345714cd0df7078f696c4dcb955f6b7b67e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 7 Oct 2023 18:37:16 +0200 Subject: [PATCH 311/676] Refactor add server form --- lib/l10n/app_en.arb | 1 + lib/l10n/app_es.arb | 1 + lib/screens/connect/fab.dart | 35 +- lib/screens/servers/servers.dart | 35 +- .../add_server/add_server_functions.dart | 120 +++ lib/widgets/add_server/add_server_modal.dart | 561 +++++++++++++ lib/widgets/add_server/form_text_field.dart | 54 ++ lib/widgets/add_server_modal.dart | 766 ------------------ .../servers_list/servers_list_item.dart | 41 +- .../servers_list/servers_tile_item.dart | 41 +- 10 files changed, 749 insertions(+), 906 deletions(-) create mode 100644 lib/widgets/add_server/add_server_functions.dart create mode 100644 lib/widgets/add_server/add_server_modal.dart create mode 100644 lib/widgets/add_server/form_text_field.dart delete mode 100644 lib/widgets/add_server_modal.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 37e0acb..84a22f6 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -4,6 +4,7 @@ "connect": "Connect", "servers": "Servers", "createConnection": "Create connection", + "editConnection": "Edit connection", "name": "Name", "ipDomain": "IP address or domain", "path": "Path", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 4b2af05..9b97a3a 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -4,6 +4,7 @@ "connect": "Conectar", "servers": "Servidores", "createConnection": "Crear conexión", + "editConnection": "Editar conexión", "name": "Nombre", "ipDomain": "Dirección IP o dominio", "path": "Ruta", diff --git a/lib/screens/connect/fab.dart b/lib/screens/connect/fab.dart index 47cb65e..05ed1a2 100644 --- a/lib/screens/connect/fab.dart +++ b/lib/screens/connect/fab.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:adguard_home_manager/widgets/add_server_modal.dart'; -import 'package:adguard_home_manager/widgets/version_warning_modal.dart'; +import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; class FabConnect extends StatelessWidget { const FabConnect({Key? key}) : super(key: key); @@ -12,37 +11,7 @@ class FabConnect extends StatelessWidget { void openAddServerModal() async { await Future.delayed(const Duration(seconds: 0), (() => { - if (width > 700) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => AddServerModal( - window: true, - onUnsupportedVersion: (version) => showDialog( - context: context, - builder: (ctx) => VersionWarningModal( - version: version - ), - barrierDismissible: false - ), - ), - ) - } - else { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => AddServerModal( - window: false, - onUnsupportedVersion: (version) => showDialog( - context: context, - builder: (ctx) => VersionWarningModal( - version: version - ), - barrierDismissible: false - ), - ) - )) - } + openServerFormModal(context: context, width: width) })); } diff --git a/lib/screens/servers/servers.dart b/lib/screens/servers/servers.dart index 8a557fb..180af77 100644 --- a/lib/screens/servers/servers.dart +++ b/lib/screens/servers/servers.dart @@ -6,9 +6,8 @@ import 'package:flutter/rendering.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; -import 'package:adguard_home_manager/widgets/version_warning_modal.dart'; +import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; import 'package:adguard_home_manager/widgets/servers_list/servers_list.dart'; -import 'package:adguard_home_manager/widgets/add_server_modal.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -69,37 +68,7 @@ class _ServersState extends State { void openAddServerModal() async { await Future.delayed(const Duration(seconds: 0), (() => { - if (width > 700) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => AddServerModal( - window: true, - onUnsupportedVersion: (version) => showDialog( - context: context, - builder: (ctx) => VersionWarningModal( - version: version - ), - barrierDismissible: false - ), - ), - ) - } - else { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => AddServerModal( - window: false, - onUnsupportedVersion: (version) => showDialog( - context: context, - builder: (ctx) => VersionWarningModal( - version: version - ), - barrierDismissible: false - ), - ) - )) - } + openServerFormModal(context: context, width: width) })); } diff --git a/lib/widgets/add_server/add_server_functions.dart b/lib/widgets/add_server/add_server_functions.dart new file mode 100644 index 0000000..16a0149 --- /dev/null +++ b/lib/widgets/add_server/add_server_functions.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/models/server.dart'; +import 'package:adguard_home_manager/widgets/add_server/add_server_modal.dart'; +import 'package:adguard_home_manager/widgets/version_warning_modal.dart'; + +bool checkDataValid({ + required TextEditingController nameController, + required TextEditingController ipDomainController, + required String? ipDomainError, + required String? pathError, + required String? portError, +}) { + if ( + nameController.text != '' && + ipDomainController.text != '' && + ipDomainError == null && + pathError == null && + portError == null + ) { + return true; + } + else { + return false; + } +} + + +String? validatePort({ + required String? value, + required BuildContext context +}) { + if (value != null && value != '') { + if (int.tryParse(value) != null && int.parse(value) <= 65535) { + return null; + } + else { + return AppLocalizations.of(context)!.invalidPort; + } + } + else { + return null; + } +} + +String? validateSubroute({ + required BuildContext context, + required String? value +}) { + if (value != null && value != '') { + RegExp subrouteRegexp = RegExp(r'^\/\b([A-Za-z0-9_\-~/]*)[^\/|\.|\:]$'); + if (subrouteRegexp.hasMatch(value) == true) { + return null; + } + else { + return AppLocalizations.of(context)!.invalidPath; + } + } + else { + return null; + } +} + +String? validateAddress({ + required BuildContext context, + required String? value +}) { + if (value != null && value != '') { + RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); + RegExp domain = RegExp(r'^(([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+)|((\w|-)+)$'); + if (ipAddress.hasMatch(value) == true || domain.hasMatch(value) == true) { + return null; + } + else { + return AppLocalizations.of(context)!.invalidIpDomain; + } + } + else { + return AppLocalizations.of(context)!.ipDomainNotEmpty; + } +} + +void openServerFormModal({ + required BuildContext context, + required double width, + Server? server, +}) { + showGeneralDialog( + context: context, + barrierColor: width <= 700 + ?Colors.transparent + : Colors.black54, + transitionBuilder: (context, anim1, anim2, child) { + return SlideTransition( + position: Tween( + begin: const Offset(0, 1), + end: const Offset(0, 0) + ).animate( + CurvedAnimation( + parent: anim1, + curve: Curves.easeInOutCubicEmphasized + ) + ), + child: child, + ); + }, + pageBuilder: (context, animation, secondaryAnimation) => AddServerModal( + fullScreen: width <= 700, + server: server, + onUnsupportedVersion: (version) => showDialog( + context: context, + builder: (ctx) => VersionWarningModal( + version: version + ), + barrierDismissible: false + ), + ), + ); +} \ No newline at end of file diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart new file mode 100644 index 0000000..7eb8949 --- /dev/null +++ b/lib/widgets/add_server/add_server_modal.dart @@ -0,0 +1,561 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:provider/provider.dart'; +import 'package:flutter/material.dart'; +import 'package:uuid/uuid.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/add_server/form_text_field.dart'; +import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; + +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/urls.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/functions/base64.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/models/app_log.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/models/server.dart'; + +enum ConnectionType { http, https} + +class AddServerModal extends StatefulWidget { + final Server? server; + final bool fullScreen; + final void Function(String version) onUnsupportedVersion; + + const AddServerModal({ + Key? key, + this.server, + required this.fullScreen, + required this.onUnsupportedVersion + }) : super(key: key); + + @override + State createState() => _AddServerModalState(); +} + +class _AddServerModalState extends State { + final uuid = const Uuid(); + + final TextEditingController nameController = TextEditingController(); + String? nameError; + + ConnectionType connectionType = ConnectionType.http; + + final TextEditingController ipDomainController = TextEditingController(); + String? ipDomainError; + + final TextEditingController pathController = TextEditingController(); + String? pathError; + + final TextEditingController portController = TextEditingController(); + String? portError; + + final TextEditingController userController = TextEditingController(); + + final TextEditingController passwordController = TextEditingController(); + + bool defaultServer = false; + + bool homeAssistant = false; + + bool allDataValid = false; + + bool isConnecting = false; + + Widget sectionLabel(String label) { + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 24 + ), + child: Text( + label, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + ); + } + + @override + void initState() { + if (widget.server != null) { + nameController.text = widget.server!.name; + connectionType = widget.server!.connectionMethod == 'https' ? ConnectionType.https : ConnectionType.http; + ipDomainController.text = widget.server!.domain; + pathController.text = widget.server!.path ?? ''; + portController.text = widget.server!.port != null ? widget.server!.port.toString() : ""; + userController.text = widget.server!.user ?? ""; + passwordController.text = widget.server!.password ?? ""; + defaultServer = widget.server!.defaultServer; + homeAssistant = widget.server!.runningOnHa; + } + setState(() => allDataValid = checkDataValid( + ipDomainController: ipDomainController, + nameController: nameController, + ipDomainError: ipDomainError, + pathError: pathError, + portError: portError + )); + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context, listen: false); + final statusProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + + void cancelConnecting() { + if (mounted) { + setState(() => isConnecting = false); + } + else { + isConnecting = false; + } + } + + void validateData() { + setState(() => allDataValid = checkDataValid( + ipDomainController: ipDomainController, + nameController: nameController, + ipDomainError: ipDomainError, + pathError: pathError, + portError: portError + )); + } + + String getErrorMessage(String message) { + if (message == 'invalid_username_password') return AppLocalizations.of(context)!.invalidUsernamePassword; + if (message == 'many_attempts') return AppLocalizations.of(context)!.tooManyAttempts; + if (message == 'no_connection') return AppLocalizations.of(context)!.cantReachServer; + if (message == 'server_error') return AppLocalizations.of(context)!.serverError; + return AppLocalizations.of(context)!.unknownError; + } + + void connect() async { + Server serverObj = Server( + id: uuid.v4(), + name: nameController.text, + connectionMethod: connectionType.name, + domain: ipDomainController.text, + port: portController.text != '' ? int.parse(portController.text) : null, + user: userController.text != "" ? userController.text : null, + password: passwordController.text != "" ? passwordController.text : null, + defaultServer: defaultServer, + authToken: homeAssistant == true + ? encodeBase64UserPass(userController.text, passwordController.text) + : null, + runningOnHa: homeAssistant + ); + setState(() => isConnecting = true); + + final result = homeAssistant == true + ? await loginHA(serverObj) + : await login(serverObj); + + // If something goes wrong with the connection + if (result['result'] != 'success') { + cancelConnecting(); + appConfigProvider.addLog(result['log']); + if (mounted) { + return showSnacbkar( + appConfigProvider: appConfigProvider, + label: getErrorMessage(result['result']), + color: Colors.red + ); + } + } + + if (serverObj.user != null && serverObj.password != null) { + serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); + } + + final serverCreated = await serversProvider.createServer(serverObj); + + // If something goes wrong when saving the connection on the db + if (serverCreated == null) { + if (mounted) setState(() => isConnecting = false); + appConfigProvider.addLog( + AppLog( + type: 'save_connection_db', + dateTime: DateTime.now(), + message: serverCreated.toString() + ) + ); + if (mounted) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionNotCreated, + color: Colors.red + ); + } + } + + statusProvider.setServerStatusLoad(LoadStatus.loading); + final ApiClient apiClient = ApiClient(server: serverObj); + final serverStatus = await apiClient.getServerStatus(); + + // If something goes wrong when fetching server status + if (serverStatus['result'] != 'success') { + appConfigProvider.addLog(serverStatus['log']); + statusProvider.setServerStatusLoad(LoadStatus.error); + Navigator.pop(context); + } + + // If everything is successful + statusProvider.setServerStatusData( + data: serverStatus['data'] + ); + serversProvider.setApiClient(apiClient); + statusProvider.setServerStatusLoad(LoadStatus.loaded); + if (serverStatus['data'].serverVersion.contains('a') || serverStatus['data'].serverVersion.contains('b')) { + Navigator.pop(context); + widget.onUnsupportedVersion(serverStatus['data'].serverVersion); + } + else { + Navigator.pop(context); + } + } + + void edit() async { + final Server serverObj = Server( + id: widget.server!.id, + name: nameController.text, + connectionMethod: connectionType.name, + domain: ipDomainController.text, + port: portController.text != '' ? int.parse(portController.text) : null, + user: userController.text != "" ? userController.text : null, + password: passwordController.text != "" ? passwordController.text : null, + defaultServer: defaultServer, + authToken: homeAssistant == true + ? encodeBase64UserPass(userController.text, passwordController.text) + : null, + runningOnHa: homeAssistant + ); + + final result = homeAssistant == true + ? await loginHA(serverObj) + : await login(serverObj); + + // If something goes wrong with the connection + if (result['result'] != 'success') { + cancelConnecting(); + appConfigProvider.addLog(result['log']); + if (mounted) { + return showSnacbkar( + appConfigProvider: appConfigProvider, + label: getErrorMessage(result['result']), + color: Colors.red + ); + } + } + + if (serverObj.user != null && serverObj.password != null) { + serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); + } + final serverSaved = await serversProvider.editServer(serverObj); + + // If something goes wrong when saving the connection on the db + if (serverSaved == null) { + if (mounted) setState(() => isConnecting = false); + appConfigProvider.addLog( + AppLog( + type: 'save_connection_db', + dateTime: DateTime.now(), + message: serverSaved.toString() + ) + ); + if (mounted) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionNotCreated, + color: Colors.red + ); + } + } + + // If everything is successful + final ApiClient apiClient = ApiClient(server: serverObj); + final version = await apiClient.getServerVersion(); + if ( + version['result'] == 'success' && + (version['data'].contains('a') || version['data'].contains('b')) // alpha or beta + ) { + Navigator.pop(context); + widget.onUnsupportedVersion(version['data']); + } + else { + Navigator.pop(context); + } + } + + Widget actions() { + return Row( + children: [ + IconButton( + onPressed: () => openUrl(Urls.connectionInstructions), + icon: const Icon(Icons.help_outline_outlined) + ), + IconButton( + tooltip: widget.server == null + ? AppLocalizations.of(context)!.connect + : AppLocalizations.of(context)!.save, + onPressed: allDataValid == true && isConnecting == false + ? widget.server == null + ? () => connect() + : () => edit() + : null, + icon: isConnecting + ? const CircularProgressIndicator() + : Icon( + widget.server == null + ? Icons.login_rounded + : Icons.save_rounded + ) + ), + ], + ); + } + + List form() { + return [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + margin: const EdgeInsets.only( + top: 24, + left: 24, + right: 24 + ), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withOpacity(0.05), + borderRadius: BorderRadius.circular(30), + border: Border.all( + color: Theme.of(context).colorScheme.primary + ) + ), + child: Text( + "${connectionType.name}://${ipDomainController.text}${portController.text != '' ? ':${portController.text}' : ""}${pathController.text}", + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w500 + ), + ), + ), + sectionLabel(AppLocalizations.of(context)!.general), + FormTextField( + label: AppLocalizations.of(context)!.name, + controller: nameController, + icon: Icons.badge_rounded, + error: nameError, + onChanged: (value) { + if (value != '') { + setState(() => nameError = null); + } + else { + setState(() => nameError = AppLocalizations.of(context)!.nameNotEmpty); + } + validateData(); + }, + isConnecting: isConnecting, + ), + sectionLabel(AppLocalizations.of(context)!.connection), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: SegmentedButton( + segments: const [ + ButtonSegment( + value: ConnectionType.http, + label: Text("HTTP") + ), + ButtonSegment( + value: ConnectionType.https, + label: Text("HTTPS") + ), + ], + selected: {connectionType}, + onSelectionChanged: (value) => setState(() => connectionType = value.first), + ), + ), + const SizedBox(height: 30), + FormTextField( + label: AppLocalizations.of(context)!.ipDomain, + controller: ipDomainController, + icon: Icons.link_rounded, + error: ipDomainError, + keyboardType: TextInputType.url, + onChanged: (v) { + setState(() => ipDomainError = validateAddress(context: context, value: v)); + validateData(); + }, + isConnecting: isConnecting, + ), + const SizedBox(height: 20), + FormTextField( + label: AppLocalizations.of(context)!.path, + controller: pathController, + icon: Icons.route_rounded, + error: pathError, + onChanged: (v) { + setState(() => pathError = validateSubroute(context: context, value: v)); + validateData(); + }, + hintText: AppLocalizations.of(context)!.examplePath, + helperText: AppLocalizations.of(context)!.helperPath, + isConnecting: isConnecting, + ), + const SizedBox(height: 20), + FormTextField( + label: AppLocalizations.of(context)!.port, + controller: portController, + icon: Icons.numbers_rounded, + error: portError, + keyboardType: TextInputType.number, + onChanged: (v) { + setState(() => portError = validatePort(context: context, value: v)); + validateData(); + }, + isConnecting: isConnecting, + ), + sectionLabel(AppLocalizations.of(context)!.authentication), + FormTextField( + label: AppLocalizations.of(context)!.username, + controller: userController, + icon: Icons.person_rounded, + isConnecting: isConnecting, + ), + const SizedBox(height: 20), + FormTextField( + label: AppLocalizations.of(context)!.password, + controller: passwordController, + icon: Icons.lock_rounded, + keyboardType: TextInputType.visiblePassword, + obscureText: true, + isConnecting: isConnecting, + ), + sectionLabel(AppLocalizations.of(context)!.other), + Material( + color: Colors.transparent, + child: InkWell( + onTap: widget.server == null + ? () => setState(() => defaultServer = !defaultServer) + : null, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.defaultServer, + style: const TextStyle( + fontSize: 15, + ), + ), + Switch( + value: defaultServer, + onChanged: widget.server == null + ? (value) => setState(() => defaultServer = value) + : null, + ) + ], + ), + ), + ), + ), + const SizedBox(height: 20), + Material( + color: Colors.transparent, + child: InkWell( + onTap: () => setState(() => homeAssistant = !homeAssistant), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.runningHomeAssistant, + style: const TextStyle( + fontSize: 15, + ), + ), + Switch( + value: homeAssistant, + onChanged: (value) => setState(() => homeAssistant = value), + ) + ], + ), + ), + ), + ), + const SizedBox(height: 20), + ]; + } + + if (widget.fullScreen == true) { + return Dialog.fullscreen( + child: Scaffold( + appBar: AppBar( + title: widget.server != null + ? Text(AppLocalizations.of(context)!.createConnection) + : Text(AppLocalizations.of(context)!.editConnection), + actions: [ + actions(), + const SizedBox(width: 8) + ], + ), + body: ListView( + children: form() + ), + ), + ); + } + else { + return Dialog( + child: SizedBox( + width: 400, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded) + ), + const SizedBox(width: 8), + Text( + AppLocalizations.of(context)!.createConnection, + style: const TextStyle( + fontSize: 20 + ), + ), + ], + ), + actions() + ], + ), + ), + Expanded( + child: ListView( + children: form() + ), + ) + ], + ), + ), + ); + } + } +} \ No newline at end of file diff --git a/lib/widgets/add_server/form_text_field.dart b/lib/widgets/add_server/form_text_field.dart new file mode 100644 index 0000000..0fb6f94 --- /dev/null +++ b/lib/widgets/add_server/form_text_field.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; + +class FormTextField extends StatelessWidget { + final TextEditingController controller; + final String label; + final String? error; + final IconData icon; + final TextInputType? keyboardType; + final Function(String)? onChanged; + final bool? obscureText; + final String? hintText; + final String? helperText; + final bool isConnecting; + + const FormTextField({ + Key? key, + required this.label, + required this.controller, + this.error, + required this.icon, + this.keyboardType, + this.onChanged, + this.obscureText, + this.hintText, + this.helperText, + required this.isConnecting + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: controller, + onChanged: onChanged, + obscureText: obscureText ?? false, + enabled: !isConnecting, + decoration: InputDecoration( + prefixIcon: Icon(icon), + errorText: error, + hintText: hintText, + helperText: helperText, + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: label, + ), + keyboardType: keyboardType, + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart deleted file mode 100644 index c7604a1..0000000 --- a/lib/widgets/add_server_modal.dart +++ /dev/null @@ -1,766 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:provider/provider.dart'; -import 'package:flutter/material.dart'; -import 'package:uuid/uuid.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/constants/urls.dart'; -import 'package:adguard_home_manager/functions/open_url.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/functions/base64.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/models/app_log.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/models/server.dart'; - -enum ConnectionType { http, https} - -class AddServerModal extends StatefulWidget { - final Server? server; - final bool window; - final void Function(String version) onUnsupportedVersion; - - const AddServerModal({ - Key? key, - this.server, - required this.window, - required this.onUnsupportedVersion - }) : super(key: key); - - @override - State createState() => _AddServerModalState(); -} - -class _AddServerModalState extends State { - final uuid = const Uuid(); - - final TextEditingController nameController = TextEditingController(); - String? nameError; - - ConnectionType connectionType = ConnectionType.http; - - final TextEditingController ipDomainController = TextEditingController(); - String? ipDomainError; - - final TextEditingController pathController = TextEditingController(); - String? pathError; - - final TextEditingController portController = TextEditingController(); - String? portError; - - final TextEditingController userController = TextEditingController(); - - final TextEditingController passwordController = TextEditingController(); - - bool defaultServer = false; - - bool homeAssistant = false; - - bool allDataValid = false; - - bool isConnecting = false; - - Widget sectionLabel(String label) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 24 - ), - child: Text( - label, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - ); - } - - Widget textField({ - required String label, - required TextEditingController controller, - String? error, - required IconData icon, - TextInputType? keyboardType, - Function(String)? onChanged, - bool? obscureText, - String? hintText, - String? helperText - }) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: controller, - onChanged: onChanged, - obscureText: obscureText ?? false, - decoration: InputDecoration( - prefixIcon: Icon(icon), - errorText: error, - hintText: hintText, - helperText: helperText, - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: label, - ), - keyboardType: keyboardType, - ), - ); - } - - void checkDataValid() { - if ( - nameController.text != '' && - ipDomainController.text != '' && - ipDomainError == null && - pathError == null && - portError == null - ) { - setState(() { - allDataValid = true; - }); - } - else { - setState(() { - allDataValid = false; - }); - } - } - - - void validatePort(String? value) { - if (value != null && value != '') { - if (int.tryParse(value) != null && int.parse(value) <= 65535) { - setState(() { - portError = null; - }); - } - else { - setState(() { - portError = AppLocalizations.of(context)!.invalidPort; - }); - } - } - else { - setState(() { - portError = null; - }); - } - checkDataValid(); - } - - void validateSubroute(String? value) { - if (value != null && value != '') { - RegExp subrouteRegexp = RegExp(r'^\/\b([A-Za-z0-9_\-~/]*)[^\/|\.|\:]$'); - if (subrouteRegexp.hasMatch(value) == true) { - setState(() { - pathError = null; - }); - } - else { - setState(() { - pathError = AppLocalizations.of(context)!.invalidPath; - }); - } - } - else { - setState(() { - pathError = null; - }); - } - checkDataValid(); - } - - void validateAddress(String? value) { - if (value != null && value != '') { - RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); - RegExp domain = RegExp(r'^(([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+)|((\w|-)+)$'); - if (ipAddress.hasMatch(value) == true || domain.hasMatch(value) == true) { - setState(() { - ipDomainError = null; - }); - } - else { - setState(() { - ipDomainError = AppLocalizations.of(context)!.invalidIpDomain; - }); - } - } - else { - setState(() { - ipDomainError = AppLocalizations.of(context)!.ipDomainNotEmpty; - }); - } - checkDataValid(); - } - - @override - void initState() { - if (widget.server != null) { - nameController.text = widget.server!.name; - connectionType = widget.server!.connectionMethod == 'https' ? ConnectionType.https : ConnectionType.http; - ipDomainController.text = widget.server!.domain; - pathController.text = widget.server!.path ?? ''; - portController.text = widget.server!.port != null ? widget.server!.port.toString() : ""; - userController.text = widget.server!.user ?? ""; - passwordController.text = widget.server!.password ?? ""; - defaultServer = widget.server!.defaultServer; - homeAssistant = widget.server!.runningOnHa; - } - checkDataValid(); - super.initState(); - } - - @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context, listen: false); - final statusProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - final mediaQuery = MediaQuery.of(context); - - void cancelConnecting() { - if (mounted) { - setState(() => isConnecting = false); - } - else { - isConnecting = false; - } - } - - void connect() async { - Server serverObj = Server( - id: uuid.v4(), - name: nameController.text, - connectionMethod: connectionType.name, - domain: ipDomainController.text, - port: portController.text != '' ? int.parse(portController.text) : null, - user: userController.text != "" ? userController.text : null, - password: passwordController.text != "" ? passwordController.text : null, - defaultServer: defaultServer, - authToken: homeAssistant == true - ? encodeBase64UserPass(userController.text, passwordController.text) - : null, - runningOnHa: homeAssistant - ); - setState(() => isConnecting = true); - - final result = homeAssistant == true - ? await loginHA(serverObj) - : await login(serverObj); - - if (!mounted) return; - - if (result['result'] == 'success') { - if (serverObj.user != null && serverObj.password != null) { - serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); - } - final serverCreated = await serversProvider.createServer(serverObj); - if (serverCreated == null) { - statusProvider.setServerStatusLoad(LoadStatus.loading); - - final ApiClient apiClient = ApiClient(server: serverObj); - - final serverStatus = await apiClient.getServerStatus(); - - if (!mounted) return; - - if (serverStatus['result'] == 'success') { - statusProvider.setServerStatusData( - data: serverStatus['data'] - ); - serversProvider.setApiClient(apiClient); - statusProvider.setServerStatusLoad(LoadStatus.loaded); - if (serverStatus['data'].serverVersion.contains('a') || serverStatus['data'].serverVersion.contains('b')) { - Navigator.pop(context); - widget.onUnsupportedVersion(serverStatus['data'].serverVersion); - } - else { - Navigator.pop(context); - } - } - else { - appConfigProvider.addLog(serverStatus['log']); - statusProvider.setServerStatusLoad(LoadStatus.error); - Navigator.pop(context); - } - } - else { - setState(() => isConnecting = false); - appConfigProvider.addLog( - AppLog( - type: 'save_connection_db', - dateTime: DateTime.now(), - message: serverCreated.toString() - ) - ); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionNotCreated, - color: Colors.red - ); - } - } - else if (result['result'] == 'invalid_username_password') { - cancelConnecting(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.invalidUsernamePassword, - color: Colors.red - ); - } - else if (result['result'] == 'many_attempts') { - cancelConnecting(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.tooManyAttempts, - color: Colors.red - ); - } - else if (result['result'] == 'no_connection') { - cancelConnecting(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.cantReachServer, - color: Colors.red - ); - } - else if (result['result'] == 'ssl_error') { - cancelConnecting(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.sslError, - color: Colors.red - ); - } - else if (result['result'] == 'server_error') { - cancelConnecting(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.serverError, - color: Colors.red - ); - } - else { - cancelConnecting(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.unknownError, - color: Colors.red - ); - } - } - - void edit() async { - final Server serverObj = Server( - id: widget.server!.id, - name: nameController.text, - connectionMethod: connectionType.name, - domain: ipDomainController.text, - port: portController.text != '' ? int.parse(portController.text) : null, - user: userController.text != "" ? userController.text : null, - password: passwordController.text != "" ? passwordController.text : null, - defaultServer: defaultServer, - authToken: homeAssistant == true - ? encodeBase64UserPass(userController.text, passwordController.text) - : null, - runningOnHa: homeAssistant - ); - - final result = homeAssistant == true - ? await loginHA(serverObj) - : await login(serverObj); - - if (!mounted) return; - if (result['result'] == 'success') { - if (serverObj.user != null && serverObj.password != null) { - serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); - } - final serverSaved = await serversProvider.editServer(serverObj); - - if (!mounted) return; - if (serverSaved == null) { - final ApiClient apiClient = ApiClient(server: serverObj); - final version = await apiClient.getServerVersion(); - if ( - version['result'] == 'success' && - (version['data'].contains('a') || version['data'].contains('b')) // alpha or beta - ) { - Navigator.pop(context); - widget.onUnsupportedVersion(version['data']); - } - else { - Navigator.pop(context); - } - } - else { - appConfigProvider.addLog( - AppLog( - type: 'edit_connection_db', - dateTime: DateTime.now(), - message: serverSaved.toString() - ) - ); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionNotCreated, - color: Colors.red - ); - } - } - else if (result['result'] == 'invalid_username_password') { - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.invalidUsernamePassword, - color: Colors.red - ); - } - else if (result['result'] == 'many_attempts') { - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.tooManyAttempts, - color: Colors.red - ); - } - else if (result['result'] == 'no_connection') { - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.cantReachServer, - color: Colors.red - ); - } - else if (result['result'] == 'ssl_error') { - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.sslError, - color: Colors.red - ); - } - else if (result['result'] == 'server_error') { - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.serverError, - color: Colors.red - ); - } - else { - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.unknownError, - color: Colors.red - ); - } - } - - List form() { - return [ - Container( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), - margin: const EdgeInsets.only( - top: 24, - left: 24, - right: 24 - ), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withOpacity(0.05), - borderRadius: BorderRadius.circular(30), - border: Border.all( - color: Theme.of(context).colorScheme.primary - ) - ), - child: Text( - "${connectionType.name}://${ipDomainController.text}${portController.text != '' ? ':${portController.text}' : ""}${pathController.text}", - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.w500 - ), - ), - ), - sectionLabel(AppLocalizations.of(context)!.general), - textField( - label: AppLocalizations.of(context)!.name, - controller: nameController, - icon: Icons.badge_rounded, - error: nameError, - onChanged: (value) { - if (value != '') { - setState(() => nameError = null); - } - else { - setState(() => nameError = AppLocalizations.of(context)!.nameNotEmpty); - } - checkDataValid(); - } - ), - sectionLabel(AppLocalizations.of(context)!.connection), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: SegmentedButton( - segments: const [ - ButtonSegment( - value: ConnectionType.http, - label: Text("HTTP") - ), - ButtonSegment( - value: ConnectionType.https, - label: Text("HTTPS") - ), - ], - selected: {connectionType}, - onSelectionChanged: (value) => setState(() => connectionType = value.first), - ), - ), - const SizedBox(height: 30), - textField( - label: AppLocalizations.of(context)!.ipDomain, - controller: ipDomainController, - icon: Icons.link_rounded, - error: ipDomainError, - keyboardType: TextInputType.url, - onChanged: validateAddress - ), - const SizedBox(height: 20), - textField( - label: AppLocalizations.of(context)!.path, - controller: pathController, - icon: Icons.route_rounded, - error: pathError, - onChanged: validateSubroute, - hintText: AppLocalizations.of(context)!.examplePath, - helperText: AppLocalizations.of(context)!.helperPath, - ), - const SizedBox(height: 20), - textField( - label: AppLocalizations.of(context)!.port, - controller: portController, - icon: Icons.numbers_rounded, - error: portError, - keyboardType: TextInputType.number, - onChanged: validatePort - ), - sectionLabel(AppLocalizations.of(context)!.authentication), - textField( - label: AppLocalizations.of(context)!.username, - controller: userController, - icon: Icons.person_rounded, - ), - const SizedBox(height: 20), - textField( - label: AppLocalizations.of(context)!.password, - controller: passwordController, - icon: Icons.lock_rounded, - keyboardType: TextInputType.visiblePassword, - obscureText: true - ), - sectionLabel(AppLocalizations.of(context)!.other), - Material( - color: Colors.transparent, - child: InkWell( - onTap: widget.server == null - ? () => setState(() => defaultServer = !defaultServer) - : null, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.defaultServer, - style: const TextStyle( - fontSize: 15, - ), - ), - Switch( - value: defaultServer, - onChanged: widget.server == null - ? (value) => setState(() => defaultServer = value) - : null, - ) - ], - ), - ), - ), - ), - const SizedBox(height: 20), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => setState(() => homeAssistant = !homeAssistant), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.runningHomeAssistant, - style: const TextStyle( - fontSize: 15, - ), - ), - Switch( - value: homeAssistant, - onChanged: (value) => setState(() => homeAssistant = value), - ) - ], - ), - ), - ), - ), - const SizedBox(height: 20), - ]; - } - - if (widget.window == true) { - return Dialog( - child: SizedBox( - width: 400, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.clear_rounded) - ), - const SizedBox(width: 8), - Text( - AppLocalizations.of(context)!.createConnection, - style: const TextStyle( - fontSize: 20 - ), - ), - ], - ), - Row( - children: [ - IconButton( - onPressed: () => openUrl(Urls.connectionInstructions), - icon: const Icon(Icons.help_outline_outlined) - ), - IconButton( - tooltip: widget.server == null - ? AppLocalizations.of(context)!.connect - : AppLocalizations.of(context)!.save, - onPressed: allDataValid == true - ? widget.server == null - ? () => connect() - : () => edit() - : null, - icon: Icon( - widget.server == null - ? Icons.login_rounded - : Icons.save_rounded - ) - ), - ], - ), - ], - ), - ), - Expanded( - child: ListView( - children: form() - ), - ) - ], - ), - ), - ); - } - else { - return Stack( - children: [ - Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.createConnection), - actions: [ - IconButton( - onPressed: () => openUrl(Urls.connectionInstructions), - icon: const Icon(Icons.help_outline_outlined) - ), - IconButton( - tooltip: widget.server == null - ? AppLocalizations.of(context)!.connect - : AppLocalizations.of(context)!.save, - onPressed: allDataValid == true - ? widget.server == null - ? () => connect() - : () => edit() - : null, - icon: Icon( - widget.server == null - ? Icons.login_rounded - : Icons.save_rounded - ) - ), - const SizedBox(width: 10) - ], - toolbarHeight: 70, - ), - body: ListView( - children: form(), - ) - ), - AnimatedOpacity( - opacity: isConnecting == true ? 1 : 0, - duration: const Duration(milliseconds: 250), - curve: Curves.easeInOut, - child: IgnorePointer( - ignoring: isConnecting == true ? false : true, - child: Scaffold( - backgroundColor: Colors.transparent, - body: Container( - width: mediaQuery.size.width, - height: mediaQuery.size.height, - color: const Color.fromRGBO(0, 0, 0, 0.7), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const CircularProgressIndicator( - color: Colors.white, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.connecting, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.w500, - fontSize: 26 - ), - ) - ], - ), - ), - ), - ), - ) - ], - ); - } - } -} \ No newline at end of file diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 724be22..280ae7c 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -5,8 +5,7 @@ import 'package:expandable/expandable.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/version_warning_modal.dart'; -import 'package:adguard_home_manager/widgets/add_server_modal.dart'; +import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -88,41 +87,9 @@ class _ServersListItemState extends State with SingleTickerProv }); } - void openAddServerBottomSheet({Server? server}) async { + void openServerModal({Server? server}) async { await Future.delayed(const Duration(seconds: 0), (() => { - if (width > 700) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => AddServerModal( - server: server, - window: true, - onUnsupportedVersion: (version) => showDialog( - context: context, - builder: (ctx) => VersionWarningModal( - version: version - ), - barrierDismissible: false - ), - ), - ) - } - else { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => AddServerModal( - server: server, - window: false, - onUnsupportedVersion: (version) => showDialog( - context: context, - builder: (ctx) => VersionWarningModal( - version: version - ), - barrierDismissible: false - ), - ) - )) - } + openServerFormModal(context: context, width: width, server: server) })); } @@ -326,7 +293,7 @@ class _ServersListItemState extends State with SingleTickerProv ) ), PopupMenuItem( - onTap: (() => openAddServerBottomSheet(server: server)), + onTap: (() => openServerModal(server: server)), child: Row( children: [ const Icon(Icons.edit), diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index 1cbd622..8407526 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -4,8 +4,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/version_warning_modal.dart'; -import 'package:adguard_home_manager/widgets/add_server_modal.dart'; +import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -57,41 +56,9 @@ class _ServersTileItemState extends State with SingleTickerProv }); } - void openAddServerBottomSheet({Server? server}) async { + void openServerModal({Server? server}) async { await Future.delayed(const Duration(seconds: 0), (() => { - if (width > 700) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => AddServerModal( - server: server, - window: true, - onUnsupportedVersion: (version) => showDialog( - context: context, - builder: (ctx) => VersionWarningModal( - version: version - ), - barrierDismissible: false - ), - ), - ) - } - else { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => AddServerModal( - server: server, - window: false, - onUnsupportedVersion: (version) => showDialog( - context: context, - builder: (ctx) => VersionWarningModal( - version: version - ), - barrierDismissible: false - ), - ) - )) - } + openServerFormModal(context: context, width: width, server: server) })); } @@ -291,7 +258,7 @@ class _ServersTileItemState extends State with SingleTickerProv ) ), PopupMenuItem( - onTap: (() => openAddServerBottomSheet(server: server)), + onTap: (() => openServerModal(server: server)), child: Row( children: [ const Icon(Icons.edit), From 36bd7acfedf1560e7f7d9147b9febf590b3b3e5b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 7 Oct 2023 21:51:29 +0200 Subject: [PATCH 312/676] Improvements and fixes --- .../add_server/add_server_functions.dart | 2 +- lib/widgets/add_server/add_server_modal.dart | 134 ++++++++---------- 2 files changed, 59 insertions(+), 77 deletions(-) diff --git a/lib/widgets/add_server/add_server_functions.dart b/lib/widgets/add_server/add_server_functions.dart index 16a0149..6dd9c38 100644 --- a/lib/widgets/add_server/add_server_functions.dart +++ b/lib/widgets/add_server/add_server_functions.dart @@ -68,7 +68,7 @@ String? validateAddress({ }) { if (value != null && value != '') { RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); - RegExp domain = RegExp(r'^(([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+)|((\w|-)+)$'); + RegExp domain = RegExp(r'^(([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+)$'); if (ipAddress.hasMatch(value) == true || domain.hasMatch(value) == true) { return null; } diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index 7eb8949..294cd7d 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -6,6 +6,8 @@ import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/add_server/form_text_field.dart'; +import 'package:adguard_home_manager/widgets/section_label.dart'; +import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -67,23 +69,6 @@ class _AddServerModalState extends State { bool isConnecting = false; - Widget sectionLabel(String label) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 24 - ), - child: Text( - label, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - ); - } - @override void initState() { if (widget.server != null) { @@ -166,12 +151,13 @@ class _AddServerModalState extends State { cancelConnecting(); appConfigProvider.addLog(result['log']); if (mounted) { - return showSnacbkar( + showSnacbkar( appConfigProvider: appConfigProvider, label: getErrorMessage(result['result']), color: Colors.red ); } + return; } if (serverObj.user != null && serverObj.password != null) { @@ -181,7 +167,7 @@ class _AddServerModalState extends State { final serverCreated = await serversProvider.createServer(serverObj); // If something goes wrong when saving the connection on the db - if (serverCreated == null) { + if (serverCreated != null) { if (mounted) setState(() => isConnecting = false); appConfigProvider.addLog( AppLog( @@ -197,6 +183,7 @@ class _AddServerModalState extends State { color: Colors.red ); } + return; } statusProvider.setServerStatusLoad(LoadStatus.loading); @@ -208,6 +195,7 @@ class _AddServerModalState extends State { appConfigProvider.addLog(serverStatus['log']); statusProvider.setServerStatusLoad(LoadStatus.error); Navigator.pop(context); + return; } // If everything is successful @@ -223,6 +211,7 @@ class _AddServerModalState extends State { else { Navigator.pop(context); } + return; } void edit() async { @@ -250,12 +239,13 @@ class _AddServerModalState extends State { cancelConnecting(); appConfigProvider.addLog(result['log']); if (mounted) { - return showSnacbkar( + showSnacbkar( appConfigProvider: appConfigProvider, label: getErrorMessage(result['result']), color: Colors.red ); } + return; } if (serverObj.user != null && serverObj.password != null) { @@ -264,7 +254,7 @@ class _AddServerModalState extends State { final serverSaved = await serversProvider.editServer(serverObj); // If something goes wrong when saving the connection on the db - if (serverSaved == null) { + if (serverSaved != null) { if (mounted) setState(() => isConnecting = false); appConfigProvider.addLog( AppLog( @@ -280,6 +270,7 @@ class _AddServerModalState extends State { color: Colors.red ); } + return; } // If everything is successful @@ -294,7 +285,8 @@ class _AddServerModalState extends State { } else { Navigator.pop(context); - } + } + return; } Widget actions() { @@ -314,7 +306,11 @@ class _AddServerModalState extends State { : () => edit() : null, icon: isConnecting - ? const CircularProgressIndicator() + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator() + ) : Icon( widget.server == null ? Icons.login_rounded @@ -350,7 +346,10 @@ class _AddServerModalState extends State { ), ), ), - sectionLabel(AppLocalizations.of(context)!.general), + SectionLabel( + label: AppLocalizations.of(context)!.general, + padding: const EdgeInsets.all(24), + ), FormTextField( label: AppLocalizations.of(context)!.name, controller: nameController, @@ -367,7 +366,10 @@ class _AddServerModalState extends State { }, isConnecting: isConnecting, ), - sectionLabel(AppLocalizations.of(context)!.connection), + SectionLabel( + label: AppLocalizations.of(context)!.connection, + padding: const EdgeInsets.all(24), + ), Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: SegmentedButton( @@ -425,7 +427,10 @@ class _AddServerModalState extends State { }, isConnecting: isConnecting, ), - sectionLabel(AppLocalizations.of(context)!.authentication), + SectionLabel( + label: AppLocalizations.of(context)!.authentication, + padding: const EdgeInsets.all(24), + ), FormTextField( label: AppLocalizations.of(context)!.username, controller: userController, @@ -441,58 +446,32 @@ class _AddServerModalState extends State { obscureText: true, isConnecting: isConnecting, ), - sectionLabel(AppLocalizations.of(context)!.other), - Material( - color: Colors.transparent, - child: InkWell( - onTap: widget.server == null - ? () => setState(() => defaultServer = !defaultServer) - : null, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.defaultServer, - style: const TextStyle( - fontSize: 15, - ), - ), - Switch( - value: defaultServer, - onChanged: widget.server == null - ? (value) => setState(() => defaultServer = value) - : null, - ) - ], - ), - ), + SectionLabel( + label: AppLocalizations.of(context)!.other, + padding: const EdgeInsets.only( + top: 32, + left: 24, + bottom: 12 ), ), - const SizedBox(height: 20), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => setState(() => homeAssistant = !homeAssistant), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.runningHomeAssistant, - style: const TextStyle( - fontSize: 15, - ), - ), - Switch( - value: homeAssistant, - onChanged: (value) => setState(() => homeAssistant = value), - ) - ], - ), - ), + CustomSwitchListTile( + value: defaultServer, + onChanged: (value) => setState(() => defaultServer = value), + title: AppLocalizations.of(context)!.defaultServer, + disabled: widget.server != null || isConnecting, + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 4 + ), + ), + CustomSwitchListTile( + value: homeAssistant, + onChanged: (value) => setState(() => homeAssistant = value), + title: AppLocalizations.of(context)!.runningHomeAssistant, + disabled: widget.server != null || isConnecting, + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 4 ), ), const SizedBox(height: 20), @@ -503,6 +482,9 @@ class _AddServerModalState extends State { return Dialog.fullscreen( child: Scaffold( appBar: AppBar( + leading: CloseButton( + onPressed: () => Navigator.pop(context), + ), title: widget.server != null ? Text(AppLocalizations.of(context)!.createConnection) : Text(AppLocalizations.of(context)!.editConnection), From adaa75e7173e3b8174ecd623501c8aac232dca4e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 7 Oct 2023 23:03:30 +0200 Subject: [PATCH 313/676] Refactor clients --- lib/screens/clients/added_list.dart | 7 +- .../{ => client}/active_client_tile.dart | 0 .../{ => client}/added_client_tile.dart | 14 +- .../client/blocked_services_section.dart | 114 +++ lib/screens/clients/client/client_screen.dart | 442 +++++++++ .../client/client_screen_functions.dart | 87 ++ .../clients/client/identifiers_section.dart | 103 +++ .../{ => client}/logs_list_client.dart | 0 .../{ => client}/remove_client_modal.dart | 0 .../{ => client}/safe_search_modal.dart | 0 .../clients/{ => client}/services_modal.dart | 0 lib/screens/clients/client/settings_tile.dart | 63 ++ .../clients/{ => client}/tags_modal.dart | 0 lib/screens/clients/client/tags_section.dart | 63 ++ .../client/upstream_servers_section.dart | 111 +++ lib/screens/clients/client_screen.dart | 838 ------------------ lib/screens/clients/clients.dart | 6 +- lib/screens/clients/clients_desktop_view.dart | 2 +- lib/screens/clients/clients_list.dart | 2 +- lib/screens/clients/fab.dart | 2 +- lib/screens/clients/search_clients.dart | 4 +- .../access_settings/clients_list.dart | 2 +- 22 files changed, 1009 insertions(+), 851 deletions(-) rename lib/screens/clients/{ => client}/active_client_tile.dart (100%) rename lib/screens/clients/{ => client}/added_client_tile.dart (96%) create mode 100644 lib/screens/clients/client/blocked_services_section.dart create mode 100644 lib/screens/clients/client/client_screen.dart create mode 100644 lib/screens/clients/client/client_screen_functions.dart create mode 100644 lib/screens/clients/client/identifiers_section.dart rename lib/screens/clients/{ => client}/logs_list_client.dart (100%) rename lib/screens/clients/{ => client}/remove_client_modal.dart (100%) rename lib/screens/clients/{ => client}/safe_search_modal.dart (100%) rename lib/screens/clients/{ => client}/services_modal.dart (100%) create mode 100644 lib/screens/clients/client/settings_tile.dart rename lib/screens/clients/{ => client}/tags_modal.dart (100%) create mode 100644 lib/screens/clients/client/tags_section.dart create mode 100644 lib/screens/clients/client/upstream_servers_section.dart delete mode 100644 lib/screens/clients/client_screen.dart diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 6b7f33c..c49667d 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -9,9 +9,9 @@ import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/clients/client_screen.dart'; -import 'package:adguard_home_manager/screens/clients/added_client_tile.dart'; -import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; +import 'package:adguard_home_manager/screens/clients/client/client_screen.dart'; +import 'package:adguard_home_manager/screens/clients/client/added_client_tile.dart'; +import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/fab.dart'; import 'package:adguard_home_manager/screens/clients/options_modal.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; @@ -205,6 +205,7 @@ class _AddedListState extends State { onTap: widget.onClientSelected, onLongPress: openOptionsModal, onEdit: openClientModal, + onDelete: openDeleteModal, splitView: widget.splitView, serverVersion: statusProvider.serverStatus!.serverVersion, ), diff --git a/lib/screens/clients/active_client_tile.dart b/lib/screens/clients/client/active_client_tile.dart similarity index 100% rename from lib/screens/clients/active_client_tile.dart rename to lib/screens/clients/client/active_client_tile.dart diff --git a/lib/screens/clients/added_client_tile.dart b/lib/screens/clients/client/added_client_tile.dart similarity index 96% rename from lib/screens/clients/added_client_tile.dart rename to lib/screens/clients/client/added_client_tile.dart index c63c816..356d7be 100644 --- a/lib/screens/clients/added_client_tile.dart +++ b/lib/screens/clients/client/added_client_tile.dart @@ -15,6 +15,7 @@ class AddedClientTile extends StatelessWidget { final void Function(Client) onTap; final void Function(Client) onLongPress; final void Function(Client) onEdit; + final void Function(Client) onDelete; final Client? selectedClient; final bool? splitView; final String serverVersion; @@ -25,6 +26,7 @@ class AddedClientTile extends StatelessWidget { required this.onTap, required this.onLongPress, required this.onEdit, + required this.onDelete, this.selectedClient, required this.splitView, required this.serverVersion @@ -43,13 +45,21 @@ class AddedClientTile extends StatelessWidget { child: ContextMenuArea( builder: (context) => [ CustomListTile( - title: AppLocalizations.of(context)!.seeDetails, - icon: Icons.file_open_rounded, + title: AppLocalizations.of(context)!.edit, + icon: Icons.edit_rounded, onTap: () { Navigator.pop(context); onEdit(client); } ), + CustomListTile( + title: AppLocalizations.of(context)!.delete, + icon: Icons.delete_rounded, + onTap: () { + Navigator.pop(context); + onDelete(client); + } + ), CustomListTile( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, diff --git a/lib/screens/clients/client/blocked_services_section.dart b/lib/screens/clients/client/blocked_services_section.dart new file mode 100644 index 0000000..37c01d3 --- /dev/null +++ b/lib/screens/clients/client/blocked_services_section.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/clients/client/client_screen_functions.dart'; + +class BlockedServicesSection extends StatelessWidget { + final bool useGlobalSettingsServices; + final List blockedServices; + final void Function(List) onUpdatedBlockedServices; + final void Function(bool) onUpdateServicesGlobalSettings; + + const BlockedServicesSection({ + Key? key, + required this.useGlobalSettingsServices, + required this.blockedServices, + required this.onUpdatedBlockedServices, + required this.onUpdateServicesGlobalSettings + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + 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: () => onUpdateServicesGlobalSettings(!useGlobalSettingsServices), + 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: useGlobalSettingsServices, + onChanged: (value) => onUpdateServicesGlobalSettings(value), + ) + ], + ), + ), + ), + ), + ), + const SizedBox(height: 10), + Material( + color: Colors.transparent, + child: InkWell( + onTap: useGlobalSettingsServices == false + ? () => openServicesModal( + context: context, + blockedServices: blockedServices, + onUpdateBlockedServices: onUpdatedBlockedServices + ) + : null, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 24 + ), + child: Row( + children: [ + Icon( + Icons.public, + color: useGlobalSettingsServices == false + ? Theme.of(context).listTileTheme.iconColor + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38), + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.selectBlockedServices, + style: TextStyle( + fontSize: 16, + color: useGlobalSettingsServices == false + ? Theme.of(context).colorScheme.onSurface + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38), + ), + ), + if (useGlobalSettingsServices == false) ...[ + const SizedBox(height: 5), + Text( + blockedServices.isNotEmpty + ? "${blockedServices.length} ${AppLocalizations.of(context)!.servicesBlocked}" + : AppLocalizations.of(context)!.noBlockedServicesSelected, + style: TextStyle( + color: Theme.of(context).listTileTheme.iconColor + ), + ) + ] + ], + ) + ], + ), + ), + ), + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart new file mode 100644 index 0000000..5994767 --- /dev/null +++ b/lib/screens/clients/client/client_screen.dart @@ -0,0 +1,442 @@ +import 'package:flutter/material.dart'; +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_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'; +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 ClientScreen extends StatefulWidget { + final Client? client; + final String serverVersion; + final void Function(Client) onConfirm; + final void Function(Client)? onDelete; + final bool dialog; + + const ClientScreen({ + Key? key, + this.client, + required this.serverVersion, + required this.onConfirm, + this.onDelete, + required this.dialog + }) : super(key: key); + + @override + State createState() => _ClientScreenState(); +} + +class _ClientScreenState extends State { + final Uuid uuid = const Uuid(); + + bool validValues = false; + + TextEditingController nameController = TextEditingController(); + + List selectedTags = []; + + List> identifiersControllers = [ + { + 'id': 0, + 'controller': TextEditingController() + } + ]; + + bool useGlobalSettingsFiltering = true; + bool? enableFiltering; + bool? enableSafeBrowsing; + bool? enableParentalControl; + bool? enableSafeSearch; + SafeSearch? safeSearch; + + final SafeSearch defaultSafeSearch = SafeSearch( + enabled: false, + bing: false, + duckduckgo: false, + google: false, + pixabay: false, + yandex: false, + youtube: false + ); + + bool useGlobalSettingsServices = true; + List blockedServices = []; + + List> upstreamServers = []; + + bool version = false; + + @override + void initState() { + version = serverVersionIsAhead( + currentVersion: widget.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ); + + if (widget.client != null) { + validValues = true; + + nameController.text = widget.client!.name; + selectedTags = widget.client!.tags; + identifiersControllers = widget.client!.ids.map((e) => { + 'id': uuid.v4(), + 'controller': TextEditingController(text: e) + }).toList(); + useGlobalSettingsFiltering = widget.client!.useGlobalSettings; + enableFiltering = widget.client!.filteringEnabled; + enableParentalControl = widget.client!.parentalEnabled; + enableSafeBrowsing = widget.client!.safebrowsingEnabled; + if (version == true) { + safeSearch = widget.client!.safeSearch; + } + else { + enableSafeSearch = widget.client!.safesearchEnabled ?? false; + } + useGlobalSettingsServices = widget.client!.useGlobalBlockedServices; + blockedServices = widget.client!.blockedServices; + upstreamServers = widget.client!.upstreams.map((e) => { + 'id': uuid.v4(), + 'controller': TextEditingController(text: e) + }).toList(); + } + super.initState(); + } + + @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)), + useGlobalSettings: useGlobalSettingsFiltering, + filteringEnabled: enableFiltering ?? false, + parentalEnabled: enableParentalControl ?? false, + safebrowsingEnabled: enableSafeBrowsing ?? false, + safesearchEnabled: version == false ? enableSafeSearch : null, + safeSearch: version == true ? safeSearch : null, + useGlobalBlockedServices: useGlobalSettingsServices, + blockedServices: blockedServices, + 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( + onPressed: validValues == true + ? () { + createClient(); + Navigator.pop(context); + } + : null, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + if (widget.client != null) IconButton( + onPressed: () => openDeleteClientScreen( + context: context, + onDelete: () => clientsProvider.deleteClient(widget.client!), + ), + icon: const Icon(Icons.delete_rounded), + tooltip: AppLocalizations.of(context)!.delete, + ), + const SizedBox(width: 10), + ]; + } + + 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.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + CloseButton(onPressed: () => Navigator.pop(context)), + const SizedBox(width: 8), + Text( + widget.client != null + ? AppLocalizations.of(context)!.client + : AppLocalizations.of(context)!.addClient, + style: const TextStyle( + fontSize: 22 + ), + ), + ], + ), + Row( + children: actions() + ) + ], + ), + ), + Flexible( + child: content(false) + ) + ], + ), + ), + ); + } + else { + return Scaffold( + appBar: AppBar( + leading: IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.close) + ), + title: Text( + widget.client != null + ? AppLocalizations.of(context)!.client + : AppLocalizations.of(context)!.addClient + ), + actions: actions(), + ), + body: content(true) + ); + } + } +} \ 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 new file mode 100644 index 0000000..1bbfd24 --- /dev/null +++ b/lib/screens/clients/client/client_screen_functions.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.dart'; +import 'package:adguard_home_manager/screens/clients/client/safe_search_modal.dart'; +import 'package:adguard_home_manager/screens/clients/client/services_modal.dart'; +import 'package:adguard_home_manager/screens/clients/client/tags_modal.dart'; + +import 'package:adguard_home_manager/providers/clients_provider.dart'; +import 'package:adguard_home_manager/models/safe_search.dart'; + +void openTagsModal({ + required BuildContext context, + required List selectedTags, + required void Function(List) onSelectedTags +}) { + showDialog( + context: context, + builder: (context) => TagsModal( + selectedTags: selectedTags, + tags: Provider.of(context, listen: false).clients!.supportedTags, + onConfirm: onSelectedTags, + ) + ); +} + +void openServicesModal({ + required BuildContext context, + required List blockedServices, + required void Function(List) onUpdateBlockedServices +}) { + showDialog( + context: context, + builder: (context) => ServicesModal( + blockedServices: blockedServices, + onConfirm: onUpdateBlockedServices, + ) + ); +} + +void openDeleteClientScreen({ + required BuildContext context, + required void Function() onDelete +}) { + showDialog( + context: context, + builder: (ctx) => RemoveClientModal( + onConfirm: () { + Navigator.pop(context); + onDelete(); + } + ) + ); +} + +void openSafeSearchModal({ + required BuildContext context, + required List blockedServices, + required void Function(SafeSearch) onUpdateSafeSearch, + required SafeSearch? safeSearch, + required SafeSearch defaultSafeSearch +}) { + showDialog( + context: context, + builder: (context) => SafeSearchModal( + safeSearch: safeSearch ?? defaultSafeSearch, + disabled: false, + onConfirm: onUpdateSafeSearch + ) + ); +} + +bool checkValidValues({ + required TextEditingController nameController, + required List> identifiersControllers +}) { + if ( + nameController.text != '' && + identifiersControllers.isNotEmpty && + identifiersControllers[0]['controller']!.text != '' + ) { + return true; + } + else { + return false; + } +} diff --git a/lib/screens/clients/client/identifiers_section.dart b/lib/screens/clients/client/identifiers_section.dart new file mode 100644 index 0000000..08b044b --- /dev/null +++ b/lib/screens/clients/client/identifiers_section.dart @@ -0,0 +1,103 @@ +import 'package:adguard_home_manager/screens/clients/client/client_screen_functions.dart'; +import 'package:flutter/material.dart'; +import 'package:uuid/uuid.dart'; +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 void Function() onCheckValidValues; + + const IdentifiersSection({ + Key? key, + required this.identifiersControllers, + required this.onUpdateIdentifiersControllers, + required this.onCheckValidValues + }) : super(key: key); + + @override + State createState() => _IdentifiersSectionState(); +} + +class _IdentifiersSectionState extends State { + final Uuid uuid = const Uuid(); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SectionLabel( + label: AppLocalizations.of(context)!.identifiers, + padding: const EdgeInsets.only( + left: 24, right: 24, top: 24, bottom: 12 + ) + ), + Padding( + padding: const EdgeInsets.only(right: 20), + child: IconButton( + onPressed: () => widget.onUpdateIdentifiersControllers([ + ...widget.identifiersControllers, + Map.from({ + 'id': uuid.v4(), + 'controller': TextEditingController() + }) + ]), + icon: const Icon(Icons.add) + ), + ) + ], + ), + if (widget.identifiersControllers.isNotEmpty) ...widget.identifiersControllers.map((controller) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: TextFormField( + controller: controller['controller'], + onChanged: (_) => widget.onCheckValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.tag), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + helperText: AppLocalizations.of(context)!.identifierHelper, + labelText: AppLocalizations.of(context)!.identifier, + ), + ), + ), + const SizedBox(width: 20), + Padding( + padding: const EdgeInsets.only(bottom: 25), + child: IconButton( + onPressed: () => widget.onUpdateIdentifiersControllers( + widget.identifiersControllers.where((e) => e['id'] != controller['id']).toList() + ), + icon: const Icon(Icons.remove_circle_outline_outlined) + ), + ) + ], + ), + )).toList(), + if (widget.identifiersControllers.isEmpty) Container( + padding: const EdgeInsets.only(top: 10), + child: Text( + AppLocalizations.of(context)!.noIdentifiers, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart similarity index 100% rename from lib/screens/clients/logs_list_client.dart rename to lib/screens/clients/client/logs_list_client.dart diff --git a/lib/screens/clients/remove_client_modal.dart b/lib/screens/clients/client/remove_client_modal.dart similarity index 100% rename from lib/screens/clients/remove_client_modal.dart rename to lib/screens/clients/client/remove_client_modal.dart diff --git a/lib/screens/clients/safe_search_modal.dart b/lib/screens/clients/client/safe_search_modal.dart similarity index 100% rename from lib/screens/clients/safe_search_modal.dart rename to lib/screens/clients/client/safe_search_modal.dart diff --git a/lib/screens/clients/services_modal.dart b/lib/screens/clients/client/services_modal.dart similarity index 100% rename from lib/screens/clients/services_modal.dart rename to lib/screens/clients/client/services_modal.dart diff --git a/lib/screens/clients/client/settings_tile.dart b/lib/screens/clients/client/settings_tile.dart new file mode 100644 index 0000000..81f0c5c --- /dev/null +++ b/lib/screens/clients/client/settings_tile.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; + +class SettingsTile extends StatelessWidget { + final String label; + final bool? value; + final void Function(bool)? onChange; + final bool useGlobalSettingsFiltering; + + const SettingsTile({ + Key? key, + required this.label, + required this.value, + this.onChange, + required this.useGlobalSettingsFiltering + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: onChange != null + ? value != null ? () => onChange!(!value!) : null + : null, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 42, + vertical: 5 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + label, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + useGlobalSettingsFiltering == false + ? Switch( + value: value!, + onChanged: onChange, + ) + : Padding( + padding: const EdgeInsets.symmetric( + vertical: 14, + horizontal: 12 + ), + child: Text( + "Global", + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ) + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/tags_modal.dart b/lib/screens/clients/client/tags_modal.dart similarity index 100% rename from lib/screens/clients/tags_modal.dart rename to lib/screens/clients/client/tags_modal.dart diff --git a/lib/screens/clients/client/tags_section.dart b/lib/screens/clients/client/tags_section.dart new file mode 100644 index 0000000..a6fa67c --- /dev/null +++ b/lib/screens/clients/client/tags_section.dart @@ -0,0 +1,63 @@ +import 'package:adguard_home_manager/screens/clients/client/client_screen_functions.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class TagsSection extends StatelessWidget { + final List selectedTags; + final void Function(List) onTagsSelected; + + const TagsSection({ + Key? key, + required this.selectedTags, + required this.onTagsSelected + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () => openTagsModal( + context: context, + selectedTags: selectedTags, + onSelectedTags: onTagsSelected + ) , + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 0, horizontal: 24 + ), + child: Row( + children: [ + Icon( + Icons.label_rounded, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.selectTags, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 3), + Text( + selectedTags.isNotEmpty + ? "${selectedTags.length} ${AppLocalizations.of(context)!.tagsSelected}" + : AppLocalizations.of(context)!.noTagsSelected, + style: TextStyle( + color: Theme.of(context).listTileTheme.iconColor + ), + ) + ], + ) + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/client/upstream_servers_section.dart b/lib/screens/clients/client/upstream_servers_section.dart new file mode 100644 index 0000000..47dd41d --- /dev/null +++ b/lib/screens/clients/client/upstream_servers_section.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:uuid/uuid.dart'; +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 void Function() onCheckValidValues; + final void Function(List>) onUpdateUpstreamServers; + + const UpstreamServersSection({ + Key? key, + required this.upstreamServers, + required this.onCheckValidValues, + required this.onUpdateUpstreamServers + }) : super(key: key); + + @override + State createState() => _UpstreamServersSectionState(); +} + +class _UpstreamServersSectionState extends State { + final Uuid uuid = const Uuid(); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SectionLabel( + label: AppLocalizations.of(context)!.upstreamServers, + padding: const EdgeInsets.all(24), + ), + Padding( + padding: const EdgeInsets.only(right: 20), + child: IconButton( + onPressed: () => setState(() => widget.upstreamServers.add( + Map.from({ + 'id': uuid.v4(), + 'controller': TextEditingController() + }) + )), + icon: const Icon(Icons.add) + ), + ) + ], + ), + if (widget.upstreamServers.isNotEmpty) ...widget.upstreamServers.map((controller) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Padding( + padding: const EdgeInsets.only(bottom: 20), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: TextFormField( + controller: controller['controller'], + onChanged: (_) => widget.onCheckValidValues, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.dns_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.serverAddress, + ), + ), + ), + const SizedBox(width: 20), + IconButton( + onPressed: () => widget.onUpdateUpstreamServers( + widget.upstreamServers.where((e) => e['id'] != controller['id']).toList() + ), + icon: const Icon(Icons.remove_circle_outline_outlined) + ) + ], + ), + ), + )).toList(), + if (widget.upstreamServers.isEmpty) Container( + padding: const EdgeInsets.only(top: 12), + child: Column( + children: [ + Text( + AppLocalizations.of(context)!.noUpstreamServers, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 10), + Text( + AppLocalizations.of(context)!.willBeUsedGeneralServers, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ], + ), + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart deleted file mode 100644 index c40a6d4..0000000 --- a/lib/screens/clients/client_screen.dart +++ /dev/null @@ -1,838 +0,0 @@ -import 'package:flutter/material.dart'; -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/remove_client_modal.dart'; -import 'package:adguard_home_manager/screens/clients/safe_search_modal.dart'; -import 'package:adguard_home_manager/screens/clients/services_modal.dart'; -import 'package:adguard_home_manager/screens/clients/tags_modal.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'; -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 ClientScreen extends StatefulWidget { - final Client? client; - final String serverVersion; - final void Function(Client) onConfirm; - final void Function(Client)? onDelete; - final bool dialog; - - const ClientScreen({ - Key? key, - this.client, - required this.serverVersion, - required this.onConfirm, - this.onDelete, - required this.dialog - }) : super(key: key); - - @override - State createState() => _ClientScreenState(); -} - -class _ClientScreenState extends State { - final Uuid uuid = const Uuid(); - bool editMode = true; - - bool validValues = false; - - TextEditingController nameController = TextEditingController(); - - List selectedTags = []; - - List> identifiersControllers = [ - { - 'id': 0, - 'controller': TextEditingController() - } - ]; - - bool useGlobalSettingsFiltering = true; - bool? enableFiltering; - bool? enableSafeBrowsing; - bool? enableParentalControl; - bool? enableSafeSearch; - SafeSearch? safeSearch; - - final SafeSearch defaultSafeSearch = SafeSearch( - enabled: false, - bing: false, - duckduckgo: false, - google: false, - pixabay: false, - yandex: false, - youtube: false - ); - - bool useGlobalSettingsServices = true; - List blockedServices = []; - - List> upstreamServers = []; - - - void checkValidValues() { - if ( - nameController.text != '' && - identifiersControllers.isNotEmpty && - identifiersControllers[0]['controller'].text != '' - ) { - setState(() => validValues = true); - } - else { - setState(() => validValues = false); - } - } - - bool version = false; - - @override - void initState() { - version = serverVersionIsAhead( - currentVersion: widget.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ); - - if (widget.client != null) { - editMode = false; - - validValues = true; - - nameController.text = widget.client!.name; - selectedTags = widget.client!.tags; - identifiersControllers = widget.client!.ids.map((e) => { - 'id': uuid.v4(), - 'controller': TextEditingController(text: e) - }).toList(); - useGlobalSettingsFiltering = widget.client!.useGlobalSettings; - enableFiltering = widget.client!.filteringEnabled; - enableParentalControl = widget.client!.parentalEnabled; - enableSafeBrowsing = widget.client!.safebrowsingEnabled; - if (version == true) { - safeSearch = widget.client!.safeSearch; - } - else { - enableSafeSearch = widget.client!.safesearchEnabled ?? false; - } - useGlobalSettingsServices = widget.client!.useGlobalBlockedServices; - blockedServices = widget.client!.blockedServices; - upstreamServers = widget.client!.upstreams.map((e) => { - 'id': uuid.v4(), - 'controller': TextEditingController(text: e) - }).toList(); - } - super.initState(); - } - - @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)), - useGlobalSettings: useGlobalSettingsFiltering, - filteringEnabled: enableFiltering ?? false, - parentalEnabled: enableParentalControl ?? false, - safebrowsingEnabled: enableSafeBrowsing ?? false, - safesearchEnabled: version == false ? enableSafeSearch : null, - safeSearch: version == true ? safeSearch : null, - useGlobalBlockedServices: useGlobalSettingsServices, - blockedServices: blockedServices, - upstreams: List.from(upstreamServers.map((e) => e['controller'].text)), - tags: selectedTags - ); - widget.onConfirm(client); - } - - Widget sectionLabel({ - required String label, - EdgeInsets? padding - }) { - return Padding( - padding: padding ?? const EdgeInsets.symmetric( - vertical: 24, - horizontal: 24 - ), - child: Text( - label, - style: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 16, - color: Theme.of(context).colorScheme.primary - ), - ), - ); - } - - 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 openTagsModal() { - showDialog( - context: context, - builder: (context) => TagsModal( - selectedTags: selectedTags, - tags: clientsProvider.clients!.supportedTags, - onConfirm: (selected) => setState(() => selectedTags = selected), - ) - ); - } - - void openServicesModal() { - showDialog( - context: context, - builder: (context) => ServicesModal( - blockedServices: blockedServices, - onConfirm: (values) => setState(() => blockedServices = values), - ) - ); - } - - void updateServicesGlobalSettings(bool value) { - if (value == true) { - setState(() { - blockedServices = []; - useGlobalSettingsServices = true; - }); - } - else if (value == false) { - setState(() { - useGlobalSettingsServices = false; - }); - } - } - - void openDeleteClientScreen() { - showDialog( - context: context, - builder: (ctx) => RemoveClientModal( - onConfirm: () { - Navigator.pop(context); - widget.onDelete!(widget.client!); - } - ) - ); - } - - void openSafeSearchModal() { - showDialog( - context: context, - builder: (context) => SafeSearchModal( - safeSearch: safeSearch ?? defaultSafeSearch, - disabled: !editMode, - onConfirm: (s) => setState(() => safeSearch = s) - ) - ); - } - - Widget settignsTile({ - required String label, - required bool? value, - void Function(bool)? onChange - }) { - return Material( - color: Colors.transparent, - child: InkWell( - onTap: onChange != null - ? value != null ? () => onChange(!value) : null - : null, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 42, - vertical: 5 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - label, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - useGlobalSettingsFiltering == false - ? Switch( - value: value!, - onChanged: onChange, - ) - : Padding( - padding: const EdgeInsets.symmetric( - vertical: 14, - horizontal: 12 - ), - child: Text( - "Global", - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ) - ], - ), - ), - ), - ); - } - - 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: (_) => checkValidValues(), - 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), - Material( - color: Colors.transparent, - child: InkWell( - onTap: editMode == true ? () => openTagsModal() : null, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 0, horizontal: 24 - ), - child: Row( - children: [ - Icon( - Icons.label_rounded, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.selectTags, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 3), - Text( - selectedTags.isNotEmpty - ? "${selectedTags.length} ${AppLocalizations.of(context)!.tagsSelected}" - : AppLocalizations.of(context)!.noTagsSelected, - style: TextStyle( - color: Theme.of(context).listTileTheme.iconColor - ), - ) - ], - ) - ], - ), - ), - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - sectionLabel( - label: AppLocalizations.of(context)!.identifiers, - padding: const EdgeInsets.only( - left: 24, right: 24, top: 24, bottom: 12 - ) - ), - if (editMode == true) Padding( - padding: const EdgeInsets.only(right: 20), - child: IconButton( - onPressed: () => setState(() => identifiersControllers.add( - Map.from({ - 'id': uuid.v4(), - 'controller': TextEditingController() - }) - )), - icon: const Icon(Icons.add) - ), - ) - ], - ), - if (identifiersControllers.isNotEmpty) ...identifiersControllers.map((controller) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: TextFormField( - enabled: editMode, - controller: controller['controller'], - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.tag), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - helperText: AppLocalizations.of(context)!.identifierHelper, - labelText: AppLocalizations.of(context)!.identifier, - ), - ), - ), - if (editMode == true) ...[ - const SizedBox(width: 20), - Padding( - padding: const EdgeInsets.only(bottom: 25), - child: IconButton( - onPressed: () => setState( - () => identifiersControllers = identifiersControllers.where((e) => e['id'] != controller['id']).toList() - ), - icon: const Icon(Icons.remove_circle_outline_outlined) - ), - ) - ] - ], - ), - )).toList(), - if (identifiersControllers.isEmpty) Container( - padding: const EdgeInsets.only(top: 10), - child: Text( - AppLocalizations.of(context)!.noIdentifiers, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 18, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - 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: editMode - ? () => enableDisableGlobalSettingsFiltering() - : null, - 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: editMode == true - ? (value) => enableDisableGlobalSettingsFiltering() - : null, - ) - ], - ), - ), - ), - ), - ), - const SizedBox(height: 10), - settignsTile( - label: AppLocalizations.of(context)!.enableFiltering, - value: enableFiltering, - onChange: editMode == true - ? (value) => setState(() => enableFiltering = value) - : null - ), - settignsTile( - label: AppLocalizations.of(context)!.enableSafeBrowsing, - value: enableSafeBrowsing, - onChange: editMode == true - ? (value) => setState(() => enableSafeBrowsing = value) - : null - ), - settignsTile( - label: AppLocalizations.of(context)!.enableParentalControl, - value: enableParentalControl, - onChange: editMode == true - ? (value) => setState(() => enableParentalControl = value) - : null - ), - 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() - : null, - ), - if ( - serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == false - ) settignsTile( - label: AppLocalizations.of(context)!.enableSafeSearch, - value: enableSafeSearch, - onChange: editMode == true - ? (value) => setState(() => enableSafeSearch = value) - : null - ), - sectionLabel(label: AppLocalizations.of(context)!.blockedServices), - 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: editMode == true - ? () => updateServicesGlobalSettings(!useGlobalSettingsServices) - : null, - 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: useGlobalSettingsServices, - onChanged: editMode == true - ? (value) => updateServicesGlobalSettings(value) - : null, - ) - ], - ), - ), - ), - ), - ), - const SizedBox(height: 10), - Material( - color: Colors.transparent, - child: InkWell( - onTap: editMode == true - ? useGlobalSettingsServices == false - ? openServicesModal - : null - : null, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 24 - ), - child: Row( - children: [ - Icon( - Icons.public, - color: useGlobalSettingsServices == false - ? Theme.of(context).listTileTheme.iconColor - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38), - ), - const SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.selectBlockedServices, - style: TextStyle( - fontSize: 16, - color: useGlobalSettingsServices == false - ? Theme.of(context).colorScheme.onSurface - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38), - ), - ), - if (useGlobalSettingsServices == false) ...[ - const SizedBox(height: 5), - Text( - blockedServices.isNotEmpty - ? "${blockedServices.length} ${AppLocalizations.of(context)!.servicesBlocked}" - : AppLocalizations.of(context)!.noBlockedServicesSelected, - style: TextStyle( - color: Theme.of(context).listTileTheme.iconColor - ), - ) - ] - ], - ) - ], - ), - ), - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - sectionLabel(label: AppLocalizations.of(context)!.upstreamServers), - if (editMode == true) Padding( - padding: const EdgeInsets.only(right: 20), - child: IconButton( - onPressed: () => setState(() => upstreamServers.add( - Map.from({ - 'id': uuid.v4(), - 'controller': TextEditingController() - }) - )), - icon: const Icon(Icons.add) - ), - ) - ], - ), - if (upstreamServers.isNotEmpty) ...upstreamServers.map((controller) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Padding( - padding: const EdgeInsets.only(bottom: 20), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: TextFormField( - enabled: editMode, - controller: controller['controller'], - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.dns_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.serverAddress, - ), - ), - ), - if (editMode == true) ...[ - const SizedBox(width: 20), - IconButton( - onPressed: () => setState( - () => upstreamServers = upstreamServers.where((e) => e['id'] != controller['id']).toList() - ), - icon: const Icon(Icons.remove_circle_outline_outlined) - ) - ] - ], - ), - ), - )).toList(), - if (upstreamServers.isEmpty) Container( - padding: const EdgeInsets.only(top: 12), - child: Column( - children: [ - Text( - AppLocalizations.of(context)!.noUpstreamServers, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 18, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 10), - Text( - AppLocalizations.of(context)!.willBeUsedGeneralServers, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ], - ), - ), - const SizedBox(height: 20) - ], - ); - } - - if (widget.dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.clear_rounded) - ), - const SizedBox(width: 8), - Text( - widget.client != null - ? AppLocalizations.of(context)!.client - : AppLocalizations.of(context)!.addClient, - style: const TextStyle( - fontSize: 22 - ), - ), - ], - ), - Row( - children: [ - if (widget.client == null || (widget.client != null && editMode == true)) IconButton( - onPressed: validValues == true - ? () { - createClient(); - Navigator.pop(context); - } - : null, - icon: Icon( - widget.client != null && editMode == true - ? Icons.save_rounded - : Icons.check_rounded - ), - tooltip: widget.client != null && editMode == true - ? AppLocalizations.of(context)!.save - : AppLocalizations.of(context)!.confirm, - ), - if (widget.client != null && editMode == false) IconButton( - onPressed: () => setState(() => editMode = true), - icon: const Icon(Icons.edit_rounded), - tooltip: AppLocalizations.of(context)!.edit, - ), - if (widget.client != null) IconButton( - onPressed: openDeleteClientScreen, - icon: const Icon(Icons.delete_rounded), - tooltip: AppLocalizations.of(context)!.delete, - ), - const SizedBox(width: 10), - ], - ) - ], - ), - ), - Flexible( - child: content(false) - ) - ], - ), - ), - ); - } - else { - return Scaffold( - appBar: AppBar( - leading: IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.close) - ), - title: Text( - widget.client != null - ? AppLocalizations.of(context)!.client - : AppLocalizations.of(context)!.addClient - ), - actions: [ - if (widget.client == null || (widget.client != null && editMode == true)) IconButton( - onPressed: validValues == true - ? () { - createClient(); - Navigator.pop(context); - } - : null, - icon: Icon( - widget.client != null && editMode == true - ? Icons.save_rounded - : Icons.check_rounded - ), - tooltip: widget.client != null && editMode == true - ? AppLocalizations.of(context)!.save - : AppLocalizations.of(context)!.confirm, - ), - if (widget.client != null && editMode == false) IconButton( - onPressed: () => setState(() => editMode = true), - icon: const Icon(Icons.edit_rounded), - tooltip: AppLocalizations.of(context)!.edit, - ), - if (widget.client != null) IconButton( - onPressed: openDeleteClientScreen, - icon: const Icon(Icons.delete_rounded), - tooltip: AppLocalizations.of(context)!.delete, - ), - const SizedBox(width: 10), - ], - ), - body: content(true) - ); - } - } -} \ No newline at end of file diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 1dada10..4762e5b 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -7,7 +7,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/clients_list.dart'; import 'package:adguard_home_manager/screens/clients/search_clients.dart'; -import 'package:adguard_home_manager/screens/clients/logs_list_client.dart'; +import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dart'; import 'package:adguard_home_manager/screens/clients/clients_desktop_view.dart'; import 'package:adguard_home_manager/screens/clients/added_list.dart'; @@ -195,7 +195,8 @@ class _ClientsState extends State with TickerProviderStateMixin { clientsProvider.setSearchTermClients(null); }); }, - icon: const Icon(Icons.arrow_back_rounded) + icon: const Icon(Icons.arrow_back_rounded), + tooltip: AppLocalizations.of(context)!.exitSearch, ), const SizedBox(width: 16), Expanded( @@ -223,6 +224,7 @@ class _ClientsState extends State with TickerProviderStateMixin { fontWeight: FontWeight.normal, fontSize: 18 ), + autofocus: true, ), ) ], diff --git a/lib/screens/clients/clients_desktop_view.dart b/lib/screens/clients/clients_desktop_view.dart index d6707ad..9e261ff 100644 --- a/lib/screens/clients/clients_desktop_view.dart +++ b/lib/screens/clients/clients_desktop_view.dart @@ -5,7 +5,7 @@ import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/clients/logs_list_client.dart'; +import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dart'; import 'package:adguard_home_manager/screens/clients/added_list.dart'; import 'package:adguard_home_manager/screens/clients/clients_list.dart'; diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index 4ecd98c..f3ee547 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -2,7 +2,7 @@ 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/active_client_tile.dart'; +import 'package:adguard_home_manager/screens/clients/client/active_client_tile.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 8d73050..34dee54 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -6,7 +6,7 @@ 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_screen.dart'; +import 'package:adguard_home_manager/screens/clients/client/client_screen.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index 4d2c754..a70923f 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -7,8 +7,8 @@ import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; -import 'package:adguard_home_manager/screens/clients/client_screen.dart'; +import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.dart'; +import 'package:adguard_home_manager/screens/clients/client/client_screen.dart'; import 'package:adguard_home_manager/screens/clients/options_modal.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 2466e11..31c01a7 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -8,7 +8,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/access_settings/add_client_modal.dart'; -import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; +import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; From 5b715d04561788fc41cb5cdb606392b0c5d91ecb Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 7 Oct 2023 23:03:40 +0200 Subject: [PATCH 314/676] Autofocus search top items --- lib/screens/top_items/top_items.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index f536b47..26b84d5 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -85,6 +85,7 @@ class _TopItemsScreenState extends State { fontWeight: FontWeight.normal, fontSize: 18 ), + autofocus: true, ), ) : Text(widget.title), From 2ad99e737d7eec417a46bd109a0c2aaca4bc4b7c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 7 Oct 2023 23:16:52 +0200 Subject: [PATCH 315/676] Change opening client modal --- lib/screens/clients/added_list.dart | 33 +++---------- lib/screens/clients/client/client_screen.dart | 46 +++++++++---------- .../client/client_screen_functions.dart | 39 ++++++++++++++++ .../clients/client/identifiers_section.dart | 1 - lib/screens/clients/fab.dart | 27 +++-------- lib/screens/clients/search_clients.dart | 35 +++----------- 6 files changed, 82 insertions(+), 99 deletions(-) diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index c49667d..08621ce 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -9,7 +9,7 @@ import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.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/added_client_tile.dart'; import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/fab.dart'; @@ -128,31 +128,12 @@ class _AddedListState extends State { } void openClientModal(Client client) { - if (width > 900 || !(Platform.isAndroid | Platform.isIOS)) { - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) => ClientScreen( - onConfirm: confirmEditClient, - serverVersion: statusProvider.serverStatus!.serverVersion, - onDelete: deleteClient, - client: client, - dialog: true, - ) - ); - } - else { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => ClientScreen( - onConfirm: confirmEditClient, - serverVersion: statusProvider.serverStatus!.serverVersion, - onDelete: deleteClient, - client: client, - dialog: false, - ) - )); - } + openClientFormModal( + context: context, + width: width, + onConfirm: confirmEditClient, + onDelete: deleteClient + ); } void openDeleteModal(Client client) { diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index 5994767..4fcee53 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -20,18 +20,16 @@ import 'package:adguard_home_manager/models/clients.dart'; class ClientScreen extends StatefulWidget { final Client? client; - final String serverVersion; final void Function(Client) onConfirm; final void Function(Client)? onDelete; - final bool dialog; + final bool fullScreen; const ClientScreen({ Key? key, this.client, - required this.serverVersion, required this.onConfirm, this.onDelete, - required this.dialog + required this.fullScreen }) : super(key: key); @override @@ -81,7 +79,7 @@ class _ClientScreenState extends State { @override void initState() { version = serverVersionIsAhead( - currentVersion: widget.serverVersion, + currentVersion: Provider.of(context, listen: false).serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ); @@ -380,7 +378,26 @@ class _ClientScreenState extends State { } - if (widget.dialog == true) { + if (widget.fullScreen == true) { + return Dialog.fullscreen( + child: Scaffold( + appBar: AppBar( + leading: IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.close) + ), + title: Text( + widget.client != null + ? AppLocalizations.of(context)!.client + : AppLocalizations.of(context)!.addClient + ), + actions: actions(), + ), + body: content(true) + ), + ); + } + else { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( @@ -421,22 +438,5 @@ class _ClientScreenState extends State { ), ); } - else { - return Scaffold( - appBar: AppBar( - leading: IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.close) - ), - title: Text( - widget.client != null - ? AppLocalizations.of(context)!.client - : AppLocalizations.of(context)!.addClient - ), - actions: actions(), - ), - body: content(true) - ); - } } } \ 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 1bbfd24..4b84b2b 100644 --- a/lib/screens/clients/client/client_screen_functions.dart +++ b/lib/screens/clients/client/client_screen_functions.dart @@ -1,11 +1,15 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:adguard_home_manager/screens/clients/client/client_screen.dart'; import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/client/safe_search_modal.dart'; import 'package:adguard_home_manager/screens/clients/client/services_modal.dart'; import 'package:adguard_home_manager/screens/clients/client/tags_modal.dart'; +import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/safe_search.dart'; @@ -85,3 +89,38 @@ bool checkValidValues({ return false; } } + +void openClientFormModal({ + required BuildContext context, + required double width, + Client? client, + required void Function(Client) onConfirm, + void Function(Client)? onDelete, +}) { + showGeneralDialog( + context: context, + barrierColor: !(width > 900 || !(Platform.isAndroid | Platform.isIOS)) + ?Colors.transparent + : Colors.black54, + transitionBuilder: (context, anim1, anim2, child) { + return SlideTransition( + position: Tween( + begin: const Offset(0, 1), + end: const Offset(0, 0) + ).animate( + CurvedAnimation( + parent: anim1, + curve: Curves.easeInOutCubicEmphasized + ) + ), + child: child, + ); + }, + pageBuilder: (context, animation, secondaryAnimation) => ClientScreen( + fullScreen: !(width > 900 || !(Platform.isAndroid | Platform.isIOS)), + client: client, + onConfirm: onConfirm, + onDelete: onDelete, + ), + ); +} \ No newline at end of file diff --git a/lib/screens/clients/client/identifiers_section.dart b/lib/screens/clients/client/identifiers_section.dart index 08b044b..3d9acf2 100644 --- a/lib/screens/clients/client/identifiers_section.dart +++ b/lib/screens/clients/client/identifiers_section.dart @@ -1,4 +1,3 @@ -import 'package:adguard_home_manager/screens/clients/client/client_screen_functions.dart'; import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 34dee54..f9697f6 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -8,6 +8,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.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/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; @@ -51,27 +52,11 @@ class ClientsFab extends StatelessWidget { } void openAddClient() { - if (width > 900 || !(Platform.isAndroid | Platform.isIOS)) { - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) => ClientScreen( - onConfirm: confirmAddClient, - serverVersion: statusProvider.serverStatus!.serverVersion, - dialog: true, - ) - ); - } - else { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => ClientScreen( - onConfirm: confirmAddClient, - serverVersion: statusProvider.serverStatus!.serverVersion, - dialog: false, - ) - )); - } + openClientFormModal( + context: context, + width: width, + onConfirm: confirmAddClient + ); } return FloatingActionButton( diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index a70923f..37544f8 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -1,14 +1,12 @@ // ignore_for_file: use_build_context_synchronously -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.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/options_modal.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; @@ -137,31 +135,12 @@ class _SearchClientsState extends State { } void openClientModal(Client client) { - if (width > 900 || !(Platform.isAndroid | Platform.isIOS)) { - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) => ClientScreen( - onConfirm: confirmEditClient, - serverVersion: statusProvider.serverStatus!.serverVersion, - onDelete: deleteClient, - client: client, - dialog: true, - ) - ); - } - else { - Navigator.push(context, MaterialPageRoute( - fullscreenDialog: true, - builder: (BuildContext context) => ClientScreen( - onConfirm: confirmEditClient, - serverVersion: statusProvider.serverStatus!.serverVersion, - onDelete: deleteClient, - client: client, - dialog: false, - ) - )); - } + openClientFormModal( + context: context, + width: width, + onConfirm: confirmEditClient, + onDelete: deleteClient + ); } void openDeleteModal(Client client) { From 9d1ae22bdd88327eaac36c01712fb9c95714d0b5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Oct 2023 00:05:38 +0200 Subject: [PATCH 316/676] Changes --- lib/screens/clients/added_list.dart | 4 +++- .../clients/client/added_client_tile.dart | 12 +++++----- lib/screens/clients/fab.dart | 22 ++++++++++--------- lib/screens/clients/options_modal.dart | 6 ++++- lib/screens/clients/search_clients.dart | 4 +++- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 08621ce..8f27491 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -185,7 +185,9 @@ class _AddedListState extends State { client: widget.data[index], onTap: widget.onClientSelected, onLongPress: openOptionsModal, - onEdit: openClientModal, + onEdit: statusProvider.serverStatus != null + ? (c) => openClientModal(c) + : null, onDelete: openDeleteModal, splitView: widget.splitView, serverVersion: statusProvider.serverStatus!.serverVersion, diff --git a/lib/screens/clients/client/added_client_tile.dart b/lib/screens/clients/client/added_client_tile.dart index 356d7be..9db4edb 100644 --- a/lib/screens/clients/client/added_client_tile.dart +++ b/lib/screens/clients/client/added_client_tile.dart @@ -14,7 +14,7 @@ class AddedClientTile extends StatelessWidget { final Client client; final void Function(Client) onTap; final void Function(Client) onLongPress; - final void Function(Client) onEdit; + final void Function(Client)? onEdit; final void Function(Client) onDelete; final Client? selectedClient; final bool? splitView; @@ -25,7 +25,7 @@ class AddedClientTile extends StatelessWidget { required this.client, required this.onTap, required this.onLongPress, - required this.onEdit, + this.onEdit, required this.onDelete, this.selectedClient, required this.splitView, @@ -44,12 +44,12 @@ class AddedClientTile extends StatelessWidget { borderRadius: BorderRadius.circular(28), child: ContextMenuArea( builder: (context) => [ - CustomListTile( + if (onEdit != null) CustomListTile( title: AppLocalizations.of(context)!.edit, icon: Icons.edit_rounded, onTap: () { Navigator.pop(context); - onEdit(client); + onEdit!(client); } ), CustomListTile( @@ -185,12 +185,12 @@ class AddedClientTile extends StatelessWidget { else { return ContextMenuArea( builder: (context) => [ - CustomListTile( + if (onEdit != null) CustomListTile( title: AppLocalizations.of(context)!.seeDetails, icon: Icons.file_open_rounded, onTap: () { Navigator.pop(context); - onEdit(client); + onEdit!(client); } ), CustomListTile( diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index f9697f6..ce291c2 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -1,19 +1,16 @@ // ignore_for_file: use_build_context_synchronously -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/client_screen.dart'; - import 'package:adguard_home_manager/screens/clients/client/client_screen_functions.dart'; + import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class ClientsFab extends StatelessWidget { @@ -21,8 +18,8 @@ class ClientsFab extends StatelessWidget { @override Widget build(BuildContext context) { - final appConfigProvider = Provider.of(context); final statusProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); final clientsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -59,9 +56,14 @@ class ClientsFab extends StatelessWidget { ); } - return FloatingActionButton( - onPressed: openAddClient, - child: const Icon(Icons.add), - ); + if (statusProvider.serverStatus != null) { + return FloatingActionButton( + onPressed: openAddClient, + child: const Icon(Icons.add), + ); + } + else { + return const SizedBox(); + } } } \ No newline at end of file diff --git a/lib/screens/clients/options_modal.dart b/lib/screens/clients/options_modal.dart index 61dea10..d779aae 100644 --- a/lib/screens/clients/options_modal.dart +++ b/lib/screens/clients/options_modal.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile_dialog.dart'; class OptionsModal extends StatelessWidget { @@ -15,6 +17,8 @@ class OptionsModal extends StatelessWidget { @override Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + return AlertDialog( contentPadding: const EdgeInsets.symmetric( horizontal: 0, @@ -39,7 +43,7 @@ class OptionsModal extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 24), - CustomListTileDialog( + if (statusProvider.serverStatus != null) CustomListTileDialog( onTap: () { Navigator.pop(context); onEdit(); diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index 37544f8..99d430c 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -231,7 +231,9 @@ class _SearchClientsState extends State { : const EdgeInsets.symmetric(horizontal: 20, vertical: 15), isThreeLine: true, onLongPress: () => openOptionsModal(clientsScreen[index]), - onTap: () => openClientModal(clientsScreen[index]), + onTap: statusProvider.serverStatus != null + ? () => openClientModal(clientsScreen[index]) + : null, title: Padding( padding: const EdgeInsets.only(bottom: 5), child: Text( From 7690d5f1bc88233bdf77f1b1667fc58a54111171 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Oct 2023 00:13:00 +0200 Subject: [PATCH 317/676] Refactor blocked services modal --- .../filters/blocked_services_screen.dart | 100 ++++++++++++------ lib/screens/filters/filters.dart | 23 +--- 2 files changed, 70 insertions(+), 53 deletions(-) diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/blocked_services_screen.dart index 75d941b..cefdda5 100644 --- a/lib/screens/filters/blocked_services_screen.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -1,5 +1,7 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -12,11 +14,11 @@ import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class BlockedServicesScreen extends StatefulWidget { - final bool dialog; + final bool fullScreen; const BlockedServicesScreen({ Key? key, - required this.dialog + required this.fullScreen }) : super(key: key); @override @@ -180,7 +182,40 @@ class _BlockedServicesScreenStateWidget extends State { } } - if (widget.dialog == true) { + if (widget.fullScreen == true) { + return Dialog.fullscreen( + child: Scaffold( + appBar: AppBar( + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.blockedServices), + actions: [ + IconButton( + onPressed: updateBlockedServices, + icon: const Icon( + Icons.save_rounded + ), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 10) + ], + ), + body: RefreshIndicator( + onRefresh: () async { + final result = await filteringProvider.loadBlockedServices(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.blockedServicesListNotLoaded, + color: Colors.red + ); + } + }, + child: body() + ), + ), + ); + } + else { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( @@ -228,35 +263,34 @@ class _BlockedServicesScreenStateWidget extends State { ), ); } - else { - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.blockedServices), - actions: [ - IconButton( - onPressed: updateBlockedServices, - icon: const Icon( - Icons.save_rounded - ), - tooltip: AppLocalizations.of(context)!.save, - ), - const SizedBox(width: 10) - ], - ), - body: RefreshIndicator( - onRefresh: () async { - final result = await filteringProvider.loadBlockedServices(); - if (result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.blockedServicesListNotLoaded, - color: Colors.red - ); - } - }, - child: body() - ), - ); - } } +} + +void openBlockedServicesModal({ + required BuildContext context, + required double width, +}) { + showGeneralDialog( + context: context, + barrierColor: !(width > 700 || !(Platform.isAndroid || Platform.isIOS)) + ?Colors.transparent + : Colors.black54, + transitionBuilder: (context, anim1, anim2, child) { + return SlideTransition( + position: Tween( + begin: const Offset(0, 1), + end: const Offset(0, 0) + ).animate( + CurvedAnimation( + parent: anim1, + curve: Curves.easeInOutCubicEmphasized + ) + ), + child: child, + ); + }, + pageBuilder: (context, animation, secondaryAnimation) => BlockedServicesScreen( + fullScreen: !(width > 700 || !(Platform.isAndroid || Platform.isIOS)), + ), + ); } \ No newline at end of file diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 00cc214..c4e6d9b 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -149,26 +149,9 @@ class _FiltersState extends State { } } - void openBlockedServicesModal() { + void openBlockedServices() { Future.delayed(const Duration(seconds: 0), () { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => const BlockedServicesScreen( - dialog: true, - ), - barrierDismissible: false - ); - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const BlockedServicesScreen( - dialog: false, - ), - ) - ); - } + openBlockedServicesModal(context: context, width: width); }); } @@ -312,7 +295,7 @@ class _FiltersState extends State { ) ), PopupMenuItem( - onTap: openBlockedServicesModal, + onTap: openBlockedServices, child: Row( children: [ const Icon(Icons.block), From 24dc69d0849a06013981279d1c0e2b708f8e95f7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Oct 2023 00:14:53 +0200 Subject: [PATCH 318/676] Improvements --- lib/screens/filters/filters_triple_column.dart | 3 ++- lib/widgets/process_dialog.dart | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index de0ffb0..2f7979d 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -276,7 +276,8 @@ class FiltersTripleColumn extends StatelessWidget { subtitleWidget: generateSubtitle(filteringProvider.filtering!.userRules[index]), trailing: IconButton( onPressed: () => onRemoveCustomRule(filteringProvider.filtering!.userRules[index]), - icon: const Icon(Icons.delete) + icon: const Icon(Icons.delete), + tooltip: AppLocalizations.of(context)!.delete, ), ), ), diff --git a/lib/widgets/process_dialog.dart b/lib/widgets/process_dialog.dart index e821696..0c91442 100644 --- a/lib/widgets/process_dialog.dart +++ b/lib/widgets/process_dialog.dart @@ -24,7 +24,7 @@ class ProcessDialog extends StatelessWidget { children: [ const CircularProgressIndicator(), const SizedBox(width: 40), - Expanded( + Flexible( child: Text( message, style: TextStyle( From 95aec4b3a5efe3c004b5db556fd2533bdde1d37d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Oct 2023 00:19:32 +0200 Subject: [PATCH 319/676] Adapted more modals --- lib/screens/filters/add_button.dart | 43 ++++++++++--------- lib/screens/filters/add_custom_rule.dart | 53 +++++++++++++----------- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 3cbedc9..195d7af 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -56,27 +56,30 @@ class AddFiltersButton extends StatelessWidget { } void openAddCustomRule() { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => AddCustomRule( - onConfirm: confirmAddRule, - dialog: true, - ), - barrierDismissible: false - ); - } - else { - Navigator.of(context).push( - MaterialPageRoute( - fullscreenDialog: true, - builder: (context) => AddCustomRule( - onConfirm: confirmAddRule, - dialog: false, + showGeneralDialog( + context: context, + barrierColor: !(width > 700 || !(Platform.isAndroid || Platform.isIOS)) + ?Colors.transparent + : Colors.black54, + transitionBuilder: (context, anim1, anim2, child) { + return SlideTransition( + position: Tween( + begin: const Offset(0, 1), + end: const Offset(0, 0) + ).animate( + CurvedAnimation( + parent: anim1, + curve: Curves.easeInOutCubicEmphasized + ) ), - ) - ); - } + child: child, + ); + }, + pageBuilder: (context, animation, secondaryAnimation) => AddCustomRule( + fullScreen: !(width > 700 || !(Platform.isAndroid || Platform.isIOS)), + onConfirm: confirmAddRule, + ), + ); } void confirmAddList({required String name, required String url, required String type}) async { diff --git a/lib/screens/filters/add_custom_rule.dart b/lib/screens/filters/add_custom_rule.dart index dfb5753..4b79fc4 100644 --- a/lib/screens/filters/add_custom_rule.dart +++ b/lib/screens/filters/add_custom_rule.dart @@ -6,12 +6,12 @@ import 'package:adguard_home_manager/constants/urls.dart'; class AddCustomRule extends StatefulWidget { final void Function(String) onConfirm; - final bool dialog; + final bool fullScreen; const AddCustomRule({ Key? key, required this.onConfirm, - required this.dialog + required this.fullScreen }) : super(key: key); @override @@ -328,7 +328,32 @@ class _AddCustomRuleState extends State { ]; } - if (widget.dialog == true) { + if (widget.fullScreen == true) { + return Dialog.fullscreen( + child: Scaffold( + appBar: AppBar( + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.addCustomRule), + actions: [ + IconButton( + onPressed: checkValidValues() == true + ? () { + Navigator.pop(context); + widget.onConfirm(buildRule()); + } + : null, + icon: const Icon(Icons.check) + ), + const SizedBox(width: 10) + ], + ), + body: ListView( + children: content(), + ) + ), + ); + } + else { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( @@ -383,27 +408,5 @@ class _AddCustomRuleState extends State { ), ); } - else { - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.addCustomRule), - actions: [ - IconButton( - onPressed: checkValidValues() == true - ? () { - Navigator.pop(context); - widget.onConfirm(buildRule()); - } - : null, - icon: const Icon(Icons.check) - ), - const SizedBox(width: 10) - ], - ), - body: ListView( - children: content(), - ) - ); - } } } \ No newline at end of file From bb5cdc13d1d95bdd867d319ecd98d1efaa99a6d3 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Oct 2023 00:26:48 +0200 Subject: [PATCH 320/676] Updated optionbox styles --- .../filters/update_interval_lists_modal.dart | 86 ++----------------- lib/widgets/option_box.dart | 28 +++--- 2 files changed, 26 insertions(+), 88 deletions(-) diff --git a/lib/screens/filters/update_interval_lists_modal.dart b/lib/screens/filters/update_interval_lists_modal.dart index c168793..deb714f 100644 --- a/lib/screens/filters/update_interval_lists_modal.dart +++ b/lib/screens/filters/update_interval_lists_modal.dart @@ -94,19 +94,7 @@ class _UpdateIntervalListsModalState extends State { optionsValue: selectedOption, itemValue: 0, onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 0 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.never), - ), - ), + label: AppLocalizations.of(context)!.never, ), ), ), @@ -118,19 +106,7 @@ class _UpdateIntervalListsModalState extends State { optionsValue: selectedOption, itemValue: 1, onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 1 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.hour1), - ), - ), + label: AppLocalizations.of(context)!.hour1, ), ), ), @@ -142,19 +118,7 @@ class _UpdateIntervalListsModalState extends State { optionsValue: selectedOption, itemValue: 12, onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 12 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.hours12), - ), - ), + label: AppLocalizations.of(context)!.hours12, ), ), ), @@ -166,19 +130,8 @@ class _UpdateIntervalListsModalState extends State { optionsValue: selectedOption, itemValue: 24, onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 24 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.hours24), - ), - ), + label: AppLocalizations.of(context)!.hours24, + ), ), ), @@ -190,19 +143,8 @@ class _UpdateIntervalListsModalState extends State { optionsValue: selectedOption, itemValue: 72, onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 72 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.days3), - ), - ), + label: AppLocalizations.of(context)!.days3, + ), ), ), @@ -214,19 +156,7 @@ class _UpdateIntervalListsModalState extends State { optionsValue: selectedOption, itemValue: 168, onTap: _updateRadioValue, - child: Center( - child: AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 250), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: selectedOption == 168 - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.onSurface - ), - child: Text(AppLocalizations.of(context)!.days7), - ), - ), + label: AppLocalizations.of(context)!.days7, ), ), ), diff --git a/lib/widgets/option_box.dart b/lib/widgets/option_box.dart index 7c05a67..f19a88f 100644 --- a/lib/widgets/option_box.dart +++ b/lib/widgets/option_box.dart @@ -1,17 +1,17 @@ import 'package:flutter/material.dart'; class OptionBox extends StatelessWidget { - final Widget child; final dynamic optionsValue; final dynamic itemValue; final void Function(dynamic) onTap; + final String label; const OptionBox({ Key? key, - required this.child, required this.optionsValue, required this.itemValue, required this.onTap, + required this.label, }) : super(key: key); @override @@ -25,19 +25,27 @@ class OptionBox extends StatelessWidget { child: AnimatedContainer( duration: const Duration(milliseconds: 250), curve: Curves.easeInOut, - padding: const EdgeInsets.all(15), + padding: const EdgeInsets.symmetric(vertical: 16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(50), - border: Border.all( - color: optionsValue == itemValue - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurfaceVariant - ), color: optionsValue == itemValue ? Theme.of(context).colorScheme.primary - : Colors.transparent, + : Theme.of(context).colorScheme.primaryContainer, + ), + child: AnimatedDefaultTextStyle( + duration: const Duration(milliseconds: 250), + style: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 14, + color: optionsValue == itemValue + ? Theme.of(context).colorScheme.onInverseSurface + : Theme.of(context).colorScheme.onSurface + ), + child: Text( + label, + textAlign: TextAlign.center, + ), ), - child: child, ), ), ); From 151cbb996e96eb0a07cdf7d1ebfaa11836acb7ed Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Oct 2023 14:22:03 +0200 Subject: [PATCH 321/676] Bug fixes --- lib/models/dns_info.dart | 2 +- .../settings/dns/private_reverse_servers.dart | 2 +- lib/services/http_requests.dart | 250 +++++++++++------- 3 files changed, 153 insertions(+), 101 deletions(-) diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 5ab3cc2..67103f7 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -13,7 +13,7 @@ class DnsInfo { int? cacheTtlMin; int? cacheTtlMax; bool? cacheOptimistic; - bool resolveClients; + bool? resolveClients; bool usePrivatePtrResolvers; List localPtrUpstreams; String blockingIpv4; diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index bf6f63b..cd02684 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -79,7 +79,7 @@ class _PrivateReverseDnsServersScreenState extends State res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -636,22 +650,21 @@ class ApiClient { 'log': AppLog( type: 'get_clients', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: 'no_response', statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } - } - else { + } catch (e) { + Sentry.captureException(e); return { 'result': 'error', 'log': AppLog( type: 'get_clients', dateTime: DateTime.now(), message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), + resBody: e.toString() ) }; } @@ -701,68 +714,94 @@ class ApiClient { String? responseStatus, String? search }) async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/querylog?limit=$count${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}', - type: 'get_logs' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': LogsData.fromJson(jsonDecode(result['body'])) - }; + try { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/querylog?limit=$count${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}', + type: 'get_logs' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': LogsData.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_logs', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_logs', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } - } - else { - return result; + } catch (e) { + Sentry.captureException(e); + return { + 'result': 'error', + 'log': AppLog( + type: 'get_logs', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + resBody: e.toString() + ) + }; } } Future getFilteringRules() async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/filtering/status', - type: 'get_filtering_rules' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': FilteringStatus.fromJson(jsonDecode(result['body'])) - }; + try { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/filtering/status', + type: 'get_filtering_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': FilteringStatus.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_filtering_rules', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } - } - else { - return result; + } catch (e) { + Sentry.captureException(e); + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + resBody: e.toString() + ) + }; } } @@ -899,32 +938,46 @@ class ApiClient { } Future getFiltering() async { - final result = await Future.wait([ - apiRequest( - urlPath: '/filtering/status', - method: 'get', - server: server, - type: 'get_filtering_status' - ), - apiRequest( - urlPath: '/blocked_services/list', - method: 'get', - server: server, - type: 'get_filtering_status' - ), - ]); + try { + final result = await Future.wait([ + apiRequest( + urlPath: '/filtering/status', + method: 'get', + server: server, + type: 'get_filtering_status' + ), + apiRequest( + urlPath: '/blocked_services/list', + method: 'get', + server: server, + type: 'get_filtering_status' + ), + ]); - if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { - return { - 'result': 'success', - 'data': Filtering.fromJson({ - ...jsonDecode(result[0]['body']), - "blocked_services": result[1]['body'] != null - ? jsonDecode(result[1]['body']) - : [] - }) - }; + if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { + return { + 'result': 'success', + 'data': Filtering.fromJson({ + ...jsonDecode(result[0]['body']), + "blocked_services": result[1]['body'] != null + ? jsonDecode(result[1]['body']) + : [] + }) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -932,22 +985,21 @@ class ApiClient { 'log': AppLog( type: 'get_filtering_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: 'no_response', statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } - } - else { + } catch (e) { + Sentry.captureException(e); return { 'result': 'error', 'log': AppLog( type: 'get_filtering_status', dateTime: DateTime.now(), message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), + resBody: e.toString(), ) }; } From 48fc96a16a4d2544823b9acbb111776da9098027 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Oct 2023 14:37:18 +0200 Subject: [PATCH 322/676] Add lists fixes --- lib/providers/filtering_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/filtering_provider.dart b/lib/providers/filtering_provider.dart index 8b2d459..d416455 100644 --- a/lib/providers/filtering_provider.dart +++ b/lib/providers/filtering_provider.dart @@ -325,14 +325,14 @@ class FilteringProvider with ChangeNotifier { }; } } - else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains("Couldn't fetch filter from url")) { + else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains("data is HTML, not plain text")) { notifyListeners(); return { 'success': false, 'error': 'invalid_url' }; } - else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains('Filter URL already added')) { + else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains('url already exists')) { notifyListeners(); return { 'success': false, From ddd0fe177bc3931a3a8e7fa52e4f57c2298b02d6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Oct 2023 14:52:08 +0200 Subject: [PATCH 323/676] Fixed update lists --- lib/l10n/app_en.arb | 1 + lib/l10n/app_es.arb | 1 + lib/screens/filters/list_details_screen.dart | 31 +++++++++++++------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 84a22f6..41fb9ba 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -317,6 +317,7 @@ "deletingRule": "Deleting rule...", "enablingList": "Enabling list...", "disablingList": "Disabling list...", + "savingList": "Saving list...", "disableFiltering": "Disable filtering", "enablingFiltering": "Enabling filtering...", "disablingFiltering": "Disabling filtering...", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 9b97a3a..2e0734c 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -317,6 +317,7 @@ "deletingRule": "Eliminando regla...", "enablingList": "Habilitando lista...", "disablingList": "Deshabilitando lista...", + "savingList": "Guardando lista...", "disableFiltering": "Deshabilitar filtrado", "enablingFiltering": "Habilitando filtrado...", "disablingFiltering": "Deshabilitando filtrado...", diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 42464ec..e98c759 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -76,15 +76,20 @@ class _ListDetailsScreenState extends State { // ------- // } - void updateList(FilteringListActions action) async { + void updateList({ + required FilteringListActions action, + required Filter filterList, + }) async { ProcessModal processModal = ProcessModal(context: context); processModal.open( - list!.enabled == true - ? AppLocalizations.of(context)!.disablingList - : AppLocalizations.of(context)!.enablingList, + action == FilteringListActions.edit + ? AppLocalizations.of(context)!.savingList + : action == FilteringListActions.disable + ? AppLocalizations.of(context)!.disablingList + : AppLocalizations.of(context)!.enablingList, ); final result = await filteringProvider.updateList( - list: list, + list: filterList, type: widget.type, action: action ); @@ -204,7 +209,8 @@ class _ListDetailsScreenState extends State { list: list, type: widget.type, onEdit: ({required Filter list, required String type}) async => updateList( - FilteringListActions.edit + action: FilteringListActions.edit, + filterList: list ), dialog: true, ), @@ -217,7 +223,8 @@ class _ListDetailsScreenState extends State { list: list, type: widget.type, onEdit: ({required Filter list, required String type}) async => updateList( - FilteringListActions.edit + action: FilteringListActions.edit, + filterList: list ), dialog: false, ), @@ -302,9 +309,10 @@ class _ListDetailsScreenState extends State { children: [ IconButton( onPressed: () => updateList( - list!.enabled == true + action: list!.enabled == true ? FilteringListActions.disable - : FilteringListActions.enable + : FilteringListActions.enable, + filterList: list ), icon: Icon( list.enabled == true @@ -371,9 +379,10 @@ class _ListDetailsScreenState extends State { right: 20, child: FloatingActionButton( onPressed: () => updateList( - list!.enabled == true + action: list!.enabled == true ? FilteringListActions.disable - : FilteringListActions.enable + : FilteringListActions.enable, + filterList: list ), child: Icon( list.enabled == true From f84b217d919e07e50e575bb2d64b4580fc8d50e7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Oct 2023 21:46:18 +0200 Subject: [PATCH 324/676] Updated dhcp interfaces list --- lib/screens/settings/dhcp/dhcp.dart | 4 +- .../settings/dhcp/dhcp_interface_item.dart | 136 ++++++++ .../settings/dhcp/select_interface_modal.dart | 316 +++++++----------- 3 files changed, 266 insertions(+), 190 deletions(-) create mode 100644 lib/screens/settings/dhcp/dhcp_interface_item.dart diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index a93a338..724a33a 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -345,7 +345,9 @@ class _DhcpScreenState extends State { }), dialog: false, ), - isScrollControlled: true + isScrollControlled: true, + useSafeArea: true, + backgroundColor: Colors.transparent ); } }); diff --git a/lib/screens/settings/dhcp/dhcp_interface_item.dart b/lib/screens/settings/dhcp/dhcp_interface_item.dart new file mode 100644 index 0000000..900328e --- /dev/null +++ b/lib/screens/settings/dhcp/dhcp_interface_item.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/models/dhcp.dart'; + +class DhcpInterfaceItem extends StatelessWidget { + final NetworkInterface networkInterface; + final void Function(NetworkInterface) onSelect; + + const DhcpInterfaceItem({ + Key? key, + required this.networkInterface, + required this.onSelect + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Navigator.pop(context); + onSelect(networkInterface); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + networkInterface.name, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.hardwareAddress}: ", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + Text( + networkInterface.hardwareAddress, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ], + ), + const SizedBox(height: 5), + if (networkInterface.flags.isNotEmpty) ...[ + Row( + children: [ + Text( + "Flags: ", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + Text( + networkInterface.flags.join(', '), + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ], + ), + const SizedBox(height: 5), + ], + if (networkInterface.gatewayIp != null && networkInterface.gatewayIp != '') ...[ + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.gatewayIp}: ", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + Text( + networkInterface.gatewayIp!, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ], + ), + const SizedBox(height: 5), + ], + if (networkInterface.ipv4Addresses.isNotEmpty) ...[ + Row( + children: [ + Flexible( + child: Text( + "${AppLocalizations.of(context)!.ipv4addresses}: ${networkInterface.ipv4Addresses.join(', ')}", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), + const SizedBox(height: 5), + ], + if (networkInterface.ipv6Addresses.isNotEmpty) ...[ + Row( + children: [ + Flexible( + child: Text( + "${AppLocalizations.of(context)!.ipv6addresses}: ${networkInterface.ipv6Addresses.join(', ')}", + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), + ] + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/dhcp/select_interface_modal.dart b/lib/screens/settings/dhcp/select_interface_modal.dart index 01b7e06..668548d 100644 --- a/lib/screens/settings/dhcp/select_interface_modal.dart +++ b/lib/screens/settings/dhcp/select_interface_modal.dart @@ -3,6 +3,8 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_interface_item.dart'; + import 'package:adguard_home_manager/models/dhcp.dart'; class SelectInterfaceModal extends StatelessWidget { @@ -19,205 +21,141 @@ class SelectInterfaceModal extends StatelessWidget { @override Widget build(BuildContext context) { - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.settings_ethernet_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.selectInterface, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ], - ), - const SizedBox(height: 16), - ListView.builder( - primary: false, - shrinkWrap: true, - itemCount: interfaces.length, - itemBuilder: (context, index) => Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Navigator.pop(context); - onSelect(interfaces[index]); - }, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - interfaces[index].name, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.hardwareAddress}: ", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - Text( - interfaces[index].hardwareAddress, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ], - ), - const SizedBox(height: 5), - if (interfaces[index].flags.isNotEmpty) ...[ - Row( - children: [ - Text( - "Flags: ", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - Text( - interfaces[index].flags.join(', '), - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ], - ), - const SizedBox(height: 5), - ], - if (interfaces[index].gatewayIp != null && interfaces[index].gatewayIp != '') ...[ - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.gatewayIp}: ", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - Text( - interfaces[index].gatewayIp!, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ], - ), - const SizedBox(height: 5), - ], - if (interfaces[index].ipv4Addresses.isNotEmpty) ...[ - Row( - children: [ - Flexible( - child: Text( - "${AppLocalizations.of(context)!.ipv4addresses}: ${interfaces[index].ipv4Addresses.join(', ')}", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ) - ], - ), - const SizedBox(height: 5), - ], - if (interfaces[index].ipv6Addresses.isNotEmpty) ...[ - Row( - children: [ - Flexible( - child: Text( - "${AppLocalizations.of(context)!.ipv6addresses}: ${interfaces[index].ipv6Addresses.join(', ')}", - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ) - ], - ), - ] - ], - ), - ), - ), - ) - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(20), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ) - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ); - } - if (dialog == true) { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( - maxWidth: 500 + maxWidth: 500, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Icon( + Icons.settings_ethernet_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.selectInterface, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ], + ), + const SizedBox(height: 16), + ], + ), + ), + Expanded( + child: ListView.builder( + itemCount: interfaces.length, + itemBuilder: (context, index) => DhcpInterfaceItem( + networkInterface: interfaces[index], + onSelect: onSelect + ) + ), + ), + Padding( + padding: const EdgeInsets.all(20), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ) + ], + ), + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], ), - child: content() ), ); } else { - return Container( - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ) + return GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: Container( + color: Colors.transparent, + child: DraggableScrollableSheet( + initialChildSize: 0.6, + minChildSize: 0.3, + maxChildSize: 1, + builder: (context, controller) { + return Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28), + ), + ), + child: Column( + children: [ + Container( + margin: const EdgeInsets.all(16), + width: 36, + height: 4, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.grey + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Column( + children: [ + Icon( + Icons.settings_ethernet_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.selectInterface, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ), + Expanded( + child: ListView.builder( + controller: controller, + itemCount: interfaces.length, + itemBuilder: (context, index) => DhcpInterfaceItem( + networkInterface: interfaces[index], + onSelect: onSelect + ) + ) + ), + const SizedBox(height: 16) + ], + ), + ); + }, ), - child: content() - ); + ), + ); } } } \ No newline at end of file From 4b03dbeb18819fc19b4f023d3245218208ec628f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Oct 2023 22:11:08 +0200 Subject: [PATCH 325/676] Fixed issue edit client --- lib/screens/clients/added_list.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 8f27491..24b69ae 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -131,6 +131,7 @@ class _AddedListState extends State { openClientFormModal( context: context, width: width, + client: client, onConfirm: confirmEditClient, onDelete: deleteClient ); From 9e57b57ddf64820a83c3f587fbfcffa267db0ded Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Oct 2023 22:14:32 +0200 Subject: [PATCH 326/676] Added loading indicator edit connection --- lib/widgets/add_server/add_server_modal.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index 294cd7d..c587c7e 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -126,6 +126,8 @@ class _AddServerModalState extends State { } void connect() async { + setState(() => isConnecting = true); + Server serverObj = Server( id: uuid.v4(), name: nameController.text, @@ -140,7 +142,6 @@ class _AddServerModalState extends State { : null, runningOnHa: homeAssistant ); - setState(() => isConnecting = true); final result = homeAssistant == true ? await loginHA(serverObj) @@ -211,10 +212,11 @@ class _AddServerModalState extends State { else { Navigator.pop(context); } - return; } void edit() async { + setState(() => isConnecting = true); + final Server serverObj = Server( id: widget.server!.id, name: nameController.text, @@ -286,7 +288,6 @@ class _AddServerModalState extends State { else { Navigator.pop(context); } - return; } Widget actions() { From 077727c1be8ba372083b92ef2b25415744e5e9fd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 15 Oct 2023 23:47:42 +0200 Subject: [PATCH 327/676] Fixed spelling issue --- .gitignore | 4 +++- l10n.yaml | 3 ++- lib/l10n/app_en.arb | 4 ++-- lib/l10n/app_es.arb | 4 ++-- lib/l10n/app_pl.arb | 4 ++-- lib/l10n/app_zh.arb | 4 ++-- lib/l10n/app_zh_CN.arb | 4 ++-- lib/screens/home/combined_chart.dart | 4 ++-- lib/screens/home/home.dart | 2 +- 9 files changed, 18 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 429a1bd..6f4a17f 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,6 @@ app.*.map.json /android/app/profile /android/app/release -/debian/packages \ No newline at end of file +/debian/packages + +untranslated.json \ No newline at end of file diff --git a/l10n.yaml b/l10n.yaml index 4e6692e..764d005 100644 --- a/l10n.yaml +++ b/l10n.yaml @@ -1,3 +1,4 @@ arb-dir: lib/l10n template-arb-file: app_en.arb -output-localization-file: app_localizations.dart \ No newline at end of file +output-localization-file: app_localizations.dart +untranslated-messages-file: untranslated.json \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 41fb9ba..f54e491 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -171,7 +171,7 @@ "dnsQueries": "DNS queries", "average": "Average", "blockedFilters": "Blocked by filters", - "malwarePhisingBlocked": "Blocked malware/phising", + "malwarePhishingBlocked": "Blocked malware/phishing", "blockedAdultWebsites": "Blocked adult websites", "generalSettings": "General settings", "generalSettingsDescription": "Various different settings", @@ -651,7 +651,7 @@ "october": "October", "november": "November", "december": "December", - "malwarePhising": "Malware/phising", + "malwarePhishing": "Malware/phishing", "queries": "Queries", "adultSites": "Adult sites", "quickFilters": "Quick filters", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 2e0734c..d0c7a15 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -171,7 +171,7 @@ "dnsQueries": "Consultas DNS", "average": "Promedio", "blockedFilters": "Bloqueado por filtros", - "malwarePhisingBlocked": "Malware/phising bloqueado", + "malwarePhishingBlocked": "Malware/phising bloqueado", "blockedAdultWebsites": "Sitios para adultos bloqueados", "generalSettings": "Ajustes generales", "generalSettingsDescription": "Varios ajustes generales", @@ -651,7 +651,7 @@ "october": "Octubre", "november": "Noviembre", "december": "Diciembre", - "malwarePhising": "Malware/phising", + "malwarePhishing": "Malware/phising", "queries": "Peticiones", "adultSites": "Sitios de adultos", "quickFilters": "Filtros rápidos", diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index a3dabaa..077fcbb 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -170,7 +170,7 @@ "dnsQueries": "Zapytania DNS", "average": "Åšrednia", "blockedFilters": "Zablokowane przez filtry", - "malwarePhisingBlocked": "Zablokowane zÅ‚oÅ›liwe oprogramowanie/phishing", + "malwarePhishingBlocked": "Zablokowane zÅ‚oÅ›liwe oprogramowanie/phishing", "blockedAdultWebsites": "Zablokowane witryny dla dorosÅ‚ych", "generalSettings": "Ustawienia główne", "generalSettingsDescription": "Różne ustawienia", @@ -649,7 +649,7 @@ "october": "Październik", "november": "Listopad", "december": "GrudzieÅ„", - "malwarePhising": "ZÅ‚oÅ›liwe oprogramowanie / wyÅ‚udzanie informacji", + "malwarePhishing": "ZÅ‚oÅ›liwe oprogramowanie / wyÅ‚udzanie informacji", "queries": "Zapytania", "adultSites": "Strony dla dorosÅ‚ych", "quickFilters": "Szybkie filtry", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 796a6c6..8d246eb 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -170,7 +170,7 @@ "dnsQueries": "DNS 查询", "average": "å¹³å‡å€¼", "blockedFilters": "被过滤器拦截", - "malwarePhisingBlocked": "è¢«æ‹¦æˆªçš„æ¶æ„/钓鱼网站", + "malwarePhishingBlocked": "è¢«æ‹¦æˆªçš„æ¶æ„/钓鱼网站", "blockedAdultWebsites": "被拦截的æˆäººç½‘ç«™", "generalSettings": "常规设置", "generalSettingsDescription": "å„ç§ä¸åŒçš„设置", @@ -649,7 +649,7 @@ "october": "10月", "november": "11月", "december": "12月", - "malwarePhising": "æ¶æ„/钓鱼网站", + "malwarePhishing": "æ¶æ„/钓鱼网站", "queries": "查询", "adultSites": "æˆäººç½‘ç«™", "quickFilters": "状æ€è¿‡æ»¤å™¨", diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb index 796a6c6..8d246eb 100644 --- a/lib/l10n/app_zh_CN.arb +++ b/lib/l10n/app_zh_CN.arb @@ -170,7 +170,7 @@ "dnsQueries": "DNS 查询", "average": "å¹³å‡å€¼", "blockedFilters": "被过滤器拦截", - "malwarePhisingBlocked": "è¢«æ‹¦æˆªçš„æ¶æ„/钓鱼网站", + "malwarePhishingBlocked": "è¢«æ‹¦æˆªçš„æ¶æ„/钓鱼网站", "blockedAdultWebsites": "被拦截的æˆäººç½‘ç«™", "generalSettings": "常规设置", "generalSettingsDescription": "å„ç§ä¸åŒçš„设置", @@ -649,7 +649,7 @@ "october": "10月", "november": "11月", "december": "12月", - "malwarePhising": "æ¶æ„/钓鱼网站", + "malwarePhishing": "æ¶æ„/钓鱼网站", "queries": "查询", "adultSites": "æˆäººç½‘ç«™", "quickFilters": "状æ€è¿‡æ»¤å™¨", diff --git a/lib/screens/home/combined_chart.dart b/lib/screens/home/combined_chart.dart index d7328d1..f781b7d 100644 --- a/lib/screens/home/combined_chart.dart +++ b/lib/screens/home/combined_chart.dart @@ -79,13 +79,13 @@ class CombinedHomeChart extends StatelessWidget { replacedSafeBrowsing: appConfigProvider.hideZeroValues == true ? removeZero(statusProvider.serverStatus!.stats.replacedSafebrowsing) != null ? CombinedChartItem( - label: AppLocalizations.of(context)!.malwarePhisingBlocked, + label: AppLocalizations.of(context)!.malwarePhishingBlocked, color: Colors.green, data: statusProvider.serverStatus!.stats.replacedSafebrowsing ) : null : CombinedChartItem( - label: AppLocalizations.of(context)!.malwarePhisingBlocked, + label: AppLocalizations.of(context)!.malwarePhishingBlocked, color: Colors.green, data: statusProvider.serverStatus!.stats.replacedSafebrowsing ) , diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 7acfa63..01d251d 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -149,7 +149,7 @@ class _HomeState extends State { widthFactor: width > 700 ? 0.5 : 1, child: HomeChart( data: statusProvider.serverStatus!.stats.replacedSafebrowsing, - label: AppLocalizations.of(context)!.malwarePhisingBlocked, + label: AppLocalizations.of(context)!.malwarePhishingBlocked, primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.green, From 3ff179d24b4d772c34a6060f1c14ec2f8f7e0166 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 21 Oct 2023 18:54:40 +0200 Subject: [PATCH 328/676] Added turkish translation --- lib/l10n/app_tr.arb | 666 ++++++++++++++++++++++++++++++++++++++++++++ lib/main.dart | 3 +- 2 files changed, 668 insertions(+), 1 deletion(-) create mode 100644 lib/l10n/app_tr.arb diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb new file mode 100644 index 0000000..b7b3c93 --- /dev/null +++ b/lib/l10n/app_tr.arb @@ -0,0 +1,666 @@ +{ + "home": "Anasayfa", + "settings": "Ayarlar", + "connect": "BaÄŸlan", + "servers": "Sunucular", + "createConnection": "BaÄŸlantı oluÅŸtur", + "editConnection": "BaÄŸlantıyı düzenle", + "name": "Ad", + "ipDomain": "IP adresi veya alan adı", + "path": "Dosya Yolu", + "port": "BaÄŸlantı noktası", + "username": "Kullanıcı adı", + "password": "Åžifre", + "defaultServer": "Varsayılan sunucu", + "general": "Genel", + "connection": "BaÄŸlantı", + "authentication": "Kimlik doÄŸrulama", + "other": "DiÄŸer", + "invalidPort": "Geçersiz baÄŸlantı noktası", + "invalidPath": "Geçersiz dosya yolu", + "invalidIpDomain": "Geçersiz IP veya alan adı", + "ipDomainNotEmpty": "IP veya alan adı boÅŸ olamaz", + "nameNotEmpty": "Ad boÅŸ bırakılamaz", + "invalidUsernamePassword": "Geçersiz kullanıcı adı veya ÅŸifre", + "tooManyAttempts": "Çok fazla deneme yapıldı. Daha sonra tekrar deneyin.", + "cantReachServer": "Sunucuya ulaşılamıyor. BaÄŸlantınızı kontrol edin.", + "sslError": "SSL hatası. Ayarlar > GeliÅŸmiÅŸ ayarlar bölümüne gidin ve SSL doÄŸrulamasını geçersiz kıl seçeneÄŸini etkinleÅŸtirin.", + "unknownError": "Bilinmeyen hata", + "connectionNotCreated": "BaÄŸlantı kurulamadı", + "connecting": "BaÄŸlanılıyor...", + "connected": "BaÄŸlantı kuruldu", + "selectedDisconnected": "Seçildi ancak baÄŸlantı kesildi", + "connectionDefaultSuccessfully": "BaÄŸlantı baÅŸarıyla varsayılan olarak ayarlandı.", + "connectionDefaultFailed": "BaÄŸlantı varsayılan olarak ayarlanamadı.", + "noSavedConnections": "KaydedilmiÅŸ baÄŸlantı yok", + "cannotConnect": "Sunucuya baÄŸlanılamıyor", + "connectionRemoved": "BaÄŸlantı baÅŸarıyla kaldırıldı", + "connectionCannotBeRemoved": "BaÄŸlantı kaldırılamaz.", + "remove": "Kaldır", + "removeWarning": "Bu AdGuard Home sunucusuyla baÄŸlantıyı kaldırmak istediÄŸinizden emin misiniz?", + "cancel": "İptal", + "defaultConnection": "Varsayılan baÄŸlantı", + "setDefault": "Varsayılan ayarla", + "edit": "Düzenle", + "delete": "Sil", + "save": "Kaydet", + "serverStatus": "Sunucu durumu", + "connectionNotUpdated": "BaÄŸlantı güncellenmedi", + "ruleFilteringWidget": "Kural filtreleme bileÅŸeni", + "safeBrowsingWidget": "Güvenli gezinti bileÅŸeni", + "parentalFilteringWidget": "Ebeveyn filtreleme bileÅŸeni", + "safeSearchWidget": "Güvenli arama bileÅŸeni", + "ruleFiltering": "Kural filtreleme", + "safeBrowsing": "Güvenli gezinti", + "parentalFiltering": "Ebeveyn filtreleme", + "safeSearch": "Güvenli arama", + "serverStatusNotRefreshed": "Sunucu durumu yenilenemedi", + "loadingStatus": "Durum yükleniyor...", + "errorLoadServerStatus": "Sunucu durumu yüklenemedi", + "topQueriedDomains": "En çok sorgulanan alan adları", + "viewMore": "Daha fazla göster", + "topClients": "Öne çıkan istemciler", + "topBlockedDomains": "En çok engellenen alan adları", + "appSettings": "Uygulama ayarları", + "theme": "Tema", + "light": "Aydınlık", + "dark": "Karanlık", + "systemDefined": "Tanımlanmış sistem", + "close": "Kapat", + "connectedTo": "BaÄŸlandı:", + "selectedServer": "Seçili sunucu:", + "noServerSelected": "Seçili sunucu yok", + "manageServer": "Sunucuyu yönet", + "allProtections": "Tüm korumalar", + "userNotEmpty": "Kullanıcı adı boÅŸ bırakılamaz", + "passwordNotEmpty": "Åžifre boÅŸ bırakılamaz", + "examplePath": "Örnek: /adguard", + "helperPath": "Ters proxy kullanıyorsanız", + "aboutApp": "Uygulama hakkında", + "appVersion": "Uygulama sürümü", + "createdBy": "Tarafından oluÅŸturuldu", + "clients": "İstemciler", + "allowed": "İzin verildi", + "blocked": "Engellendi", + "noClientsList": "Bu listede hiç istemci yok", + "activeClients": "Etkin", + "removeClient": "İstemciyi kaldır", + "removeClientMessage": "Bu istemciyi listeden çıkarmak istediÄŸinize emin misiniz?", + "confirm": "Onayla", + "removingClient": "İstemci kaldırılıyor...", + "clientNotRemoved": "İstemci listeden çıkarılamadı", + "addClient": "İstemci ekle", + "list": "Liste", + "ipAddress": "IP adresi", + "ipNotValid": "IP adresi geçersiz", + "clientAddedSuccessfully": "İstemci listeye baÅŸarıyla eklendi", + "addingClient": "İstemci ekleniyor...", + "clientNotAdded": "İstemci listeye eklenemedi", + "clientAnotherList": "Bu istemci henüz baÅŸka bir listede", + "noSavedLogs": "Kayıtlı günlük yok", + "logs": "Günlükler", + "copyLogsClipboard": "Günlükleri panoya kopyala", + "logsCopiedClipboard": "Günlükler panoya kopyalandı", + "advancedSettings": "GeliÅŸmiÅŸ ayarlar", + "dontCheckCertificate": "SSL sertifikasını kontrol etme", + "dontCheckCertificateDescription": "Sunucunun SSL sertifikası doÄŸrulamasını geçersiz kılar", + "advancedSetupDescription": "GeliÅŸmiÅŸ seçenekler", + "settingsUpdatedSuccessfully": "Ayarlar baÅŸarıyla güncellendi.", + "cannotUpdateSettings": "Ayarlar güncellenemiyor.", + "restartAppTakeEffect": "Uygulamayı yeniden baÅŸlat", + "loadingLogs": "Günlükler yükleniyor...", + "logsNotLoaded": "Günlüklerin listesi yüklenemedi", + "processed": "İşlendi\nListe yok", + "processedRow": "İşlendi (Liste yok)", + "blockedBlacklist": "Engellendi\nKara Liste", + "blockedBlacklistRow": "Engellendi (Kara liste)", + "blockedSafeBrowsing": "Engellendi\nGüvenli gezinti", + "blockedSafeBrowsingRow": "Engellendi (Güvenli gezinti)", + "blockedParental": "Engellendi\nEbeveyn filtreleme", + "blockedParentalRow": "Engellendi (Ebeveyn filtreleme)", + "blockedInvalid": "Engellendi\nGeçersiz", + "blockedInvalidRow": "Engellendi (Geçersiz)", + "blockedSafeSearch": "Engellendi\nGüvenli arama", + "blockedSafeSearchRow": "Engellendi (Güvenli arama)", + "blockedService": "Engellendi\nBelirlenen hizmet", + "blockedServiceRow": "Engellendi (Belirlenen hizmet)", + "processedWhitelist": "İşlendi\nBeyaz liste", + "processedWhitelistRow": "İşlendi (Beyaz liste)", + "processedError": "İşlendi\nHata", + "processedErrorRow": "İşlendi (Hata)", + "rewrite": "Yeniden Yaz", + "status": "Durum", + "result": "Sonuç", + "time": "Zaman", + "blocklist": "Engelleme Listesi", + "request": "İstek", + "domain": "Alan adı", + "type": "Tür", + "clas": "Sınıf", + "response": "Yanıt", + "dnsServer": "DNS sunucusu", + "elapsedTime": "Zaman aşımı", + "responseCode": "Yanıt kodu", + "client": "İstemci", + "deviceIp": "IP adresi", + "deviceName": "Ad", + "logDetails": "Günlük detayları", + "blockingRule": "Engelleme kuralı", + "blockDomain": "Alan adını engelle", + "couldntGetFilteringStatus": "Filtreleme durumu alınamıyor", + "unblockDomain": "Alan adı engelini kaldır", + "userFilteringRulesNotUpdated": "Kullanıcı filtreleme kuralları güncellenemedi", + "userFilteringRulesUpdated": "Kullanıcı filtreleme kuralları baÅŸarıyla güncellendi", + "savingUserFilters": "Kullanıcı filtreleri kaydediliyor...", + "filters": "Filtreler", + "logsOlderThan": "Daha eski günlükler", + "responseStatus": "Yanıt durumu", + "selectTime": "Zaman seç", + "notSelected": "Seçili deÄŸil", + "resetFilters": "Filtreleri sıfırla", + "noLogsDisplay": "Gösterilecek günlük yok", + "noLogsThatOld": "Seçilen zamanda kaydedilmiÅŸ herhangi bir kayıt olmayabilir. Daha yakın bir zamanı seçmeyi deneyin.", + "apply": "Uygula", + "selectAll": "Hepsini seç", + "unselectAll": "Seçimleri kaldır", + "all": "Hepsi", + "filtered": "FiltrelenmiÅŸ", + "checkAppLogs": "Uygulama günlüklerini kontrol edin", + "refresh": "Yenile", + "search": "Ara", + "dnsQueries": "DNS sorguları", + "average": "Ortalama", + "blockedFilters": "Filtreler tarafından engellenen", + "malwarePhisingBlocked": "Engellenen zararlı yazılım/oltalama ", + "blockedAdultWebsites": "Engellenen yetiÅŸkin siteleri", + "generalSettings": "Genel ayarlar", + "generalSettingsDescription": "ÇeÅŸitli farklı ayarlar", + "hideZeroValues": "Sıfır deÄŸerlerini gizle", + "hideZeroValuesDescription": "Ana ekranda, deÄŸeri sıfır olan blokları gizle", + "webAdminPanel": "Web yönetim paneli", + "visitGooglePlay": "Google Play sayfasını ziyaret et", + "gitHub": "Kaynak kodlarına GitHub'dan ulaÅŸabilirsiniz", + "blockClient": "İstemciyi engelle", + "selectTags": "Etiketleri seçin", + "noTagsSelected": "Seçili etiket yok", + "tags": "Etiketler", + "identifiers": "Tanımlayıcılar", + "identifier": "Tanımlayıcı", + "identifierHelper": "IP adresi, CIDR, MAC adresi veya ClientID", + "noIdentifiers": "Tanımlayıcı eklenmedi", + "useGlobalSettings": "Küresel ayarları kullan", + "enableFiltering": "Filtrelemeyi etkinleÅŸtir", + "enableSafeBrowsing": "Güvenli gezintiyi etkinleÅŸtirin", + "enableParentalControl": "Ebeveyn kontrolünü etkinleÅŸtirinl", + "enableSafeSearch": "Güvenli aramayı etkinleÅŸtirin", + "blockedServices": "Engellenen hizmetler", + "selectBlockedServices": "Engellenen hizmetleri seç", + "noBlockedServicesSelected": "Engellenen hizmetler seçilmedi", + "services": "Hizmetler", + "servicesBlocked": "Hizmetler engellendi", + "tagsSelected": "Seçilen etiketler", + "upstreamServers": "Üst akış sunucuları", + "serverAddress": "Sunucu adresi", + "noUpstreamServers": "Üst akış sunucusu yok.", + "willBeUsedGeneralServers": "Genel üst akış sunucuları kullanılacak.", + "added": "Eklenenler", + "clientUpdatedSuccessfully": "İstemci baÅŸarıyla güncellendi", + "clientNotUpdated": "İstemci güncellenemedi", + "clientDeletedSuccessfully": "İstemci baÅŸarıyla kaldırıldı", + "clientNotDeleted": "İstemci silinemedi", + "options": "Seçenekler", + "loadingFilters": "Filtreler yükleniyor...", + "filtersNotLoaded": "Filtreler yüklenemedi.", + "whitelists": "Beyaz listeler", + "blacklists": "Kara listeler", + "rules": "Kurallar", + "customRules": "Özel kural", + "enabledRules": "Etkin kural", + "enabled": "Etkin", + "disabled": "Devre dışı", + "rule": "Kural", + "addCustomRule": "Özel kural ekle", + "removeCustomRule": "Özel kuralı kaldır", + "removeCustomRuleMessage": "Bu özel kuralı kaldırmak istediÄŸinizden emin misiniz?", + "updatingRules": "Özel kurallar güncelleniyor...", + "ruleRemovedSuccessfully": "Kural baÅŸarıyla kaldırıldı", + "ruleNotRemoved": "Kural kaldırılamadı", + "ruleAddedSuccessfully": "Kural baÅŸarıyla eklendi", + "ruleNotAdded": "Kural eklenemedi", + "noCustomFilters": "Özel filtreler yok", + "noBlockedClients": "EngellenmiÅŸ istemci yok", + "noBlackLists": "Kara listeler yok", + "noWhiteLists": "Beyaz listeler yok", + "addWhitelist": "Beyaz liste ekle", + "addBlacklist": "Kara liste ekle", + "urlNotValid": "URL geçerli deÄŸil", + "urlAbsolutePath": "URL veya kesin dosya yolu", + "addingList": "Liste ekleniyor...", + "listAdded": "Liste baÅŸarıyla eklendi. Eklenen öğeler:", + "listAlreadyAdded": "Liste zaten eklenmiÅŸ", + "listUrlInvalid": "Liste URL'si geçersiz", + "listNotAdded": "Liste eklenemedi", + "listDetails": "Liste detayları", + "listType": "Liste türü", + "whitelist": "Beyaz liste", + "blacklist": "Kara liste", + "latestUpdate": "Son güncelleme", + "disable": "Devre dışı bırak", + "enable": "EtkinleÅŸtir", + "currentStatus": "Mevcut durum", + "listDataUpdated": "Liste verileri baÅŸarıyla güncellendi", + "listDataNotUpdated": "Liste verileri güncellenemedi", + "updatingListData": "Liste verileri güncelleniyor...", + "editWhitelist": "Beyaz listeyi düzenle", + "editBlacklist": "Kara listeyi düzenle", + "deletingList": "Liste siliniyor...", + "listDeleted": "Liste baÅŸarıyla silindi", + "listNotDeleted": "Liste silinemedi", + "deleteList": "Listeyi sil", + "deleteListMessage": "Bu listeyi silmek istediÄŸinizden emin misiniz? Bu iÅŸlem geri alınamaz.", + "serverSettings": "Sunucu ayarları", + "serverInformation": "Sunucu bilgisi", + "serverInformationDescription": "Sunucu bilgisi ve durumu", + "loadingServerInfo": "Sunucu bilgisi yükleniyor...", + "serverInfoNotLoaded": "Sunucu bilgisi yüklenemedi.", + "dnsAddresses": "DNS adresleri", + "seeDnsAddresses": "DNS adreslerine bakın", + "dnsPort": "DNS baÄŸlantı noktası", + "httpPort": "HTTP baÄŸlantı noktası", + "protectionEnabled": "Koruma etkin", + "dhcpAvailable": "DHCP mevcut", + "serverRunning": "Sunucu çalışıyor", + "serverVersion": "Sunucu sürümü", + "serverLanguage": "Sunucu dili", + "yes": "Evet", + "no": "Hayır", + "allowedClients": "İzin verilen istemciler", + "disallowedClients": "İzin verilmeyen istemciler", + "disallowedDomains": "İzin verilmeyen alan adları", + "accessSettings": "EriÅŸim ayarları", + "accessSettingsDescription": "Sunucu için eriÅŸim kurallarını yapılandır", + "loadingClients": "İstemciler yükleniyor...", + "clientsNotLoaded": "İstemciler yüklenemedi.", + "noAllowedClients": "İzin verilen istemci yok", + "allowedClientsDescription": "EÄŸer bu liste giriÅŸlere sahipse, AdGuard Home sadece bu istemcilerden gelen istekleri kabul edecek.", + "blockedClientsDescription": "EÄŸer bu liste giriÅŸlere sahipse, AdGuard Home bu istemcilerden gelen istekleri reddedecektir. Bu alan, İzin Verilen İstemciler bölümünde giriÅŸler varsa dikkate alınmaz.", + "disallowedDomainsDescription": "AdGuard Home, bu alanlara uyan DNS sorgularını reddeder ve bu sorgular sorgu günlüğünde bile görünmez.", + "addClientFieldDescription": "CIDR'ler, IP adresi veya ClientID", + "clientIdentifier": "İstemci tanımlayıcısı", + "allowClient": "İstemciye izin ver", + "disallowClient": "İstemciye izin verme", + "noDisallowedDomains": "İzin verilmeyen alan adı yok", + "domainNotAdded": "Alan adı eklenemedi", + "statusSelected": "Durum seçildi.", + "updateLists": "Listeleri güncelle", + "checkHostFiltered": "Ana bilgisayarı kontrol et", + "updatingLists": "Listeler güncelleniyor...", + "listsUpdated": "Listeler güncellendi", + "listsNotUpdated": "Listeler güncellenemedi", + "listsNotLoaded": "Listeler yüklenemedi", + "domainNotValid": "Alan adı geçersiz", + "check": "Kontrol et", + "checkingHost": "Ana bilgisayar kontrol ediliyor", + "errorCheckingHost": "Ana bilgisayar kontrol edilemedi", + "block": "Engelle", + "unblock": "Engeli kaldır", + "custom": "Özel", + "addImportant": "Ekle $important", + "howCreateRules": "Özel kurallar nasıl oluÅŸturulur?", + "examples": "Örnekler", + "example1": "example.org ve tüm alt alanlarına eriÅŸimi engeller.", + "example2": "example.org ve tüm alt alanlarına eriÅŸimi engellemeyi kaldırır.", + "example3": "Yorum ekler.", + "example4": "Belirtilen düzenli ifadeye uyan alan adlarına eriÅŸimi engeller.", + "moreInformation": "Daha fazla bilgi", + "addingRule": "Kural ekleniyor...", + "deletingRule": "Kural siliniyor...", + "enablingList": "Liste etkinleÅŸtiriliyor...", + "disablingList": "Liste devre dışı bırakılıyor...", + "savingList": "Liste kaydediliyor...", + "disableFiltering": "Filtrelemeyi devre dışı bırak", + "enablingFiltering": "Filtreleme etkinleÅŸtiriliyor...", + "disablingFiltering": "Filtreleme devre dışı bırakılıyor...", + "filteringStatusUpdated": "Filtreleme durumu baÅŸarıyla güncellendi", + "filteringStatusNotUpdated": "Filtreleme durumu güncellenemedi", + "updateFrequency": "Güncelleme sıklığı", + "never": "Asla", + "hour1": "1 saat", + "hours12": "12 saat", + "hours24": "24 saat", + "days3": "3 gün", + "days7": "7 gün", + "changingUpdateFrequency": "DeÄŸiÅŸtiriliyor...", + "updateFrequencyChanged": "Güncelleme sıklığı baÅŸarıyla deÄŸiÅŸtirildi", + "updateFrequencyNotChanged": "Güncelleme sıklığı deÄŸiÅŸtirilemedi", + "updating": "DeÄŸerler güncelleniyor...", + "blockedServicesUpdated": "Engellenen hizmetler baÅŸarıyla güncellendi", + "blockedServicesNotUpdated": "Engellenen hizmetler güncellenemedi", + "insertDomain": "Durumunu kontrol etmek için bir alan adı ekleyin.", + "dhcpSettings": "DHCP ayarları", + "dhcpSettingsDescription": "DHCP sunucusunu yapılandır", + "dhcpSettingsNotLoaded": "DHCP ayarları yüklenemedi", + "loadingDhcp": "DHCP ayarları yükleniyor...", + "enableDhcpServer": "DHCP sunucusunu etkinleÅŸtir", + "selectInterface": "Arayüz seçin", + "hardwareAddress": "Donanım adresi", + "gatewayIp": "AÄŸ Geçidi IP'si", + "ipv4addresses": "IPv4 adresleri", + "ipv6addresses": "IPv6 adresleri", + "neededSelectInterface": "DHCP sunucusunu yapılandırmak için bir arayüz seçmeniz gerekir.", + "ipv4settings": "IPv4 ayarları", + "startOfRange": "Menzilin baÅŸlangıcı", + "endOfRange": "Menzilin sonu", + "ipv6settings": "IPv6 ayarları", + "subnetMask": "Alt aÄŸ maskesi", + "subnetMaskNotValid": "Alt aÄŸ maskesi geçerli deÄŸil", + "gateway": "AÄŸ Geçidi", + "gatewayNotValid": "AÄŸ geçidi geçerli deÄŸil", + "leaseTime": "Kira süresi", + "seconds": "{time} saniye", + "leaseTimeNotValid": "Kira süresi geçerli deÄŸil", + "restoreConfiguration": "Yapılandırmayı sıfırla", + "restoreConfigurationMessage": "Devam etmek istediÄŸinizden emin misiniz? Bu, tüm yapılandırmayı sıfırlayacak. Bu iÅŸlem geri alınamaz.", + "changeInterface": "Arayüzü deÄŸiÅŸtir", + "savingSettings": "Ayarlar kaydediliyor...", + "settingsSaved": "Ayarlar baÅŸarıyla kaydedildi", + "settingsNotSaved": "Ayarlar kaydedilemedi", + "restoringConfig": "Yapılandırma geri yükleniyor...", + "configRestored": "Yapılandırma baÅŸarıyla sıfırlandı", + "configNotRestored": "Yapılandırma sıfırlanamadı", + "dhcpStatic": "DHCP statik kiralamaları", + "noDhcpStaticLeases": "DHCP statik kiralamaları bulunamadı", + "deleting": "Siliniyor...", + "staticLeaseDeleted": "DHCP statik kiralama baÅŸarıyla silindi", + "staticLeaseNotDeleted": "DHCP statik kiralaması silinemedi", + "deleteStaticLease": "Statik kiralamayı sil", + "deleteStaticLeaseDescription": "DHCP statik kirası silinecek. Bu iÅŸlem geri alınamaz.", + "addStaticLease": "Statik kiralama ekleyin", + "macAddress": "MAC adresi", + "macAddressNotValid": "MAC adresi geçersiz", + "hostName": "Ana bilgisayar adı", + "hostNameError": "Ana bilgisayar adı boÅŸ olamaz", + "creating": "OluÅŸturuluyor...", + "staticLeaseCreated": "DHCP statik kiralaması baÅŸarıyla oluÅŸturuldu", + "staticLeaseNotCreated": "DHCP statik kiralaması oluÅŸturulamadı", + "staticLeaseExists": "DHCP statik kiralaması zaten mevcut", + "serverNotConfigured": "Sunucu yapılandırılmamış", + "restoreLeases": "Kiralamaları sıfırla", + "restoreLeasesMessage": "Devam etmek istediÄŸinizden emin misiniz? Bu, mevcut tüm kiralamaları sıfırlayacaktır. Bu iÅŸlem geri alınamaz.", + "restoringLeases": "Kiralamalar sıfırlanıyor...", + "leasesRestored": "Kiralamalar baÅŸarıyla sıfırlandı", + "leasesNotRestored": "Kiralar sıfırlanamadı", + "dhcpLeases": "DHCP kiralamaları", + "noLeases": "Kullanılabilir DHCP kiralaması yok", + "dnsRewrites": "DNS yeniden yazımları", + "dnsRewritesDescription": "Özel DNS kurallarını yapılandır", + "loadingRewriteRules": "Yeniden yazma kuralları yükleniyor...", + "rewriteRulesNotLoaded": "DNS yeniden yazma kuralları yüklenemedi.", + "noRewriteRules": "DNS yeniden yazma kuralları yok", + "answer": "Cevap", + "deleteDnsRewrite": "DNS yeniden yazmayı sil", + "deleteDnsRewriteMessage": "Bu DNS yeniden yazmasını silmek istediÄŸinizden emin misiniz? Bu iÅŸlem geri alınamaz.", + "dnsRewriteRuleDeleted": "DNS yeniden yazma kuralı baÅŸarıyla silindi", + "dnsRewriteRuleNotDeleted": "DNS yeniden yazma kuralı silinemedi", + "addDnsRewrite": "DNS yeniden yazmayı ekle", + "addingRewrite": "Yeniden yazma ekleniyor...", + "dnsRewriteRuleAdded": "DNS yeniden yazma kuralı baÅŸarıyla eklendi", + "dnsRewriteRuleNotAdded": "DNS yeniden yazma kuralı eklenemedi", + "logsSettings": "Günlük ayarları", + "enableLog": "Günlüğü etkinleÅŸtir", + "clearLogs": "Günlükleri temizle", + "anonymizeClientIp": "İstemci IP'sini anonimleÅŸtirin", + "hours6": "6 saat", + "days30": "30 gün", + "days90": "90 gün", + "retentionTime": "Saklama süresi", + "selectOneItem": "Bir öğe seçin", + "logSettingsNotLoaded": "Günlük ayarları yüklenemedi.", + "updatingSettings": "Ayarlar güncelleniyor...", + "logsConfigUpdated": "Günlük ayarları baÅŸarıyla güncellendi", + "logsConfigNotUpdated": "Günlük ayarları baÅŸarıyla güncellendi", + "deletingLogs": "Günlükler temizleniyor...", + "logsCleared": "Günlükler baÅŸarıyla temizlendi", + "logsNotCleared": "Günlükler temizlenemedi", + "runningHomeAssistant": "Ev Asistanı üzerinde çalışıyor", + "serverError": "Sunucu hatası", + "noItems": "Burada gösterilecek öğe yok", + "dnsSettings": "DNS ayarları", + "dnsSettingsDescription": "DNS sunucuları ile baÄŸlantıyı yapılandır", + "upstreamDns": "Üst akış DNS sunucuları", + "bootstrapDns": "Önyükleme DNS sunucuları", + "noUpstreamDns": "Üst akış DNS sunucuları eklenmedi.", + "dnsMode": "DNS modu", + "noDnsMode": "DNS modu seçili deÄŸil", + "loadBalancing": "Yük dengeleme", + "parallelRequests": "Paralel istekler", + "fastestIpAddress": "En hızlı IP adresi", + "loadBalancingDescription": "Her seferinde bir üst akış sunucusuna sorgu yap. AdGuard Home, en hızlı sunucunun daha sık kullanılması için ağırlıklı rasgele bir algoritma kullanır.", + "parallelRequestsDescription": "Çözümlemeyi hızlandırmak için tüm üst akış sunucularına aynı anda sorgu yaparak paralel sorguları kullanın.", + "fastestIpAddressDescription": "Tüm DNS sunucularına sorgu yapın ve tüm yanıtlar arasında en hızlı IP adresini döndürün. Bu, AdGuard Home'un tüm DNS sunucularından yanıtları beklemesi gerektiÄŸi için DNS sorgularını yavaÅŸlatır, ancak genel baÄŸlantıyı iyileÅŸtirir.", + "noBootstrapDns": "Önyükleme DNS sunucuları eklenmedi.", + "bootstrapDnsServersInfo": "Önyükleme ​​DNS sunucuları, yukarı akışlarda belirttiÄŸiniz DoH/DoT çözümleyicilerinin IP adreslerini çözmek için kullanılır.", + "privateReverseDnsServers": "Özel ters DNS sunucuları", + "privateReverseDnsServersDescription": "AdGuard Home'un yerel PTR sorguları için kullandığı DNS sunucuları. Bu sunucular, özel IP aralıklarındaki adresler için ters DNS kullanarak PTR isteklerini çözmek için kullanılır, örneÄŸin '192.168.12.34' olarak ayarlanmamışsa AdGuard Home, AdGuard Home'un kendi adresleri dışında, iÅŸletim sisteminizin varsayılan DNS çözümleyicilerinin adreslerini kullanır.", + "reverseDnsDefault": "Varsayılan olarak, AdGuard Home aÅŸağıdaki ters DNS çözümleyicilerini kullanır", + "addItem": "Öğe ekle", + "noServerAddressesAdded": "Sunucu adresleri eklenmedi.", + "usePrivateReverseDnsResolvers": "Özel ters DNS çözümleyicilerini kullanma", + "usePrivateReverseDnsResolversDescription": "Bu üst akış sunucularını kullanarak yerel olarak sunulan adresler için ters DNS sorguları gerçekleÅŸtirin. Devre dışı bırakılırsa, AdGuard Home, DHCP, /etc/hosts vb. kaynaklardan bilinen istemciler dışında tüm PTR isteklerine NXDOMAIN yanıtı verir.", + "enableReverseResolving": "İstemcilerin IP adreslerinin ters çözümlemesini etkinleÅŸtirin", + "enableReverseResolvingDescription": "İstemcilerin IP adreslerini karşılık gelen çözücülere PTR sorguları göndererek IP adreslerini tersine çözümleyerek (yerel istemciler için özel DNS sunucuları, genel IP adresine sahip istemciler için yukarı akış sunucuları) istemcilerin ana bilgisayar adlarını tersine çöz.", + "dnsServerSettings": "AdGuard Home DNS sunucusu ayarları", + "limitRequestsSecond": "Saniye başına hız limiti", + "valueNotNumber": "DeÄŸer bir rakam deÄŸildir", + "enableEdns": "EDNS istemci alt ağını etkinleÅŸtir", + "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı SeçeneÄŸi (ECS) ekleyin ve istemciler tarafından gönderilen deÄŸerleri sorgu günlüğünde kaydet.", + "enableDnssec": "DNSSEC'i EtkinleÅŸtir", + "enableDnssecDescription": "Giden DNS sorgularında DNSSEC bayrağını ayarla ve sonucu kontrol et (DNSSEC etkinleÅŸtirilmiÅŸ bir çözümleyici gereklidir).", + "disableResolvingIpv6": "IPv6 adreslerinin çözümlenmesini devre dışı bırak", + "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını devre dışı bırakın (AAAA yazın).", + "blockingMode": "Engelleme modu", + "defaultMode": "Varsayılan", + "defaultDescription": "Reklam engelleme tarzı bir kural tarafından engellendiÄŸinde sıfır IP adresi ile yanıt verin (A için 0.0.0.0; :: AAAA için) /etc/hosts tarzı bir kural tarafından engellendiÄŸinde kuralda belirtilen IP adresi ile yanıt verin.", + "refusedDescription": "REFUSED kodu ile yanıt verin", + "nxdomainDescription": "NXDOMAIN kodu ile yanıt verin", + "nullIp": "BoÅŸ IP", + "nullIpDescription": "Sıfır IP adresi ile yanıt verin (A için 0.0.0.0; :: AAAA için)", + "customIp": "Özel IP", + "customIpDescription": "Manuel olarak ayarlanmış bir IP adresi ile yanıt verin", + "dnsCacheConfig": "DNS önbellek yapılandırması", + "cacheSize": "Önbellek boyutu", + "inBytes": "Bayt olarak", + "overrideMinimumTtl": "Minimum kullanım süresini geçersiz kıl", + "overrideMinimumTtlDescription": "DNS yanıtlarını önbelleÄŸe alırken üst sunucudan alınan kullanım süresi deÄŸerini uzatın (saniye olarak).", + "overrideMaximumTtl": "Maksimum kullanım süresini geçersiz kıl", + "overrideMaximumTtlDescription": "DNS önbelleÄŸindeki giriÅŸler için maksimum kullanım süresi deÄŸerini ayarlayın (saniye olarak).", + "optimisticCaching": "İyimser önbelleÄŸe alma", + "optimisticCachingDescription": "GiriÅŸlerin süresi dolmuÅŸ olsa bile Adguard Home'un önbellekten yanıt vermesini saÄŸlayın ve aynı zamanda bunları yenilemeye çalışın.", + "loadingDnsConfig": "DNS yapılandırması yükleniyor...", + "dnsConfigNotLoaded": "DNS yapılandırması yüklenemedi.", + "blockingIpv4": "IPv4 engelleniyor", + "blockingIpv4Description": "Engellenen bir A isteÄŸi için döndürülecek IP adresi", + "blockingIpv6": "IPv6 engelleniyor", + "blockingIpv6Description": "Engellenen bir AAAA isteÄŸi için döndürülecek IP adresi", + "invalidIp": "Geçersiz IP adresi", + "dnsConfigSaved": "DNS sunucusu yapılandırması baÅŸarıyla kaydedildi", + "dnsConfigNotSaved": "DNS sunucusu yapılandırması kaydedilemedi", + "savingConfig": "Yapılandırma kaydediliyor...", + "someValueNotValid": "Bazı deÄŸerler geçerli deÄŸil", + "upstreamDnsDescription": "Üst akış sunucularını ve DNS modunu yapılandır", + "bootstrapDnsDescription": "Önyükleme DNS sunucularını yapılandır", + "privateReverseDnsDescription": "Özel DNS çözümleyicileri yapılandır ve özel ters DNS çözümlemeyi etkinleÅŸtir", + "dnsServerSettingsDescription": "Hız limiti, engelleme modu ve daha fazlasını yapılandır", + "dnsCacheConfigDescription": "Sunucunun DNS önbelleÄŸini nasıl yöneteceÄŸini yapılandır", + "comment": "Yorum", + "address": "Adres", + "commentsDescription": "Yorumlar her zaman # iÅŸareti ile baÅŸlar. Onu eklemenize gerek yok, otomatik olarak eklenir.", + "encryptionSettings": "Åžifreleme ayarları", + "encryptionSettingsDescription": "Åžifreleme (HTTPS/QUIC/TLS) desteÄŸi", + "loadingEncryptionSettings": "Åžifreleme ayarları yükleniyor...", + "encryptionSettingsNotLoaded": "Åžifreleme ayarları yüklenemedi.", + "enableEncryption": "Åžifrelemeyi etkinleÅŸtir", + "enableEncryptionTypes": "HTTPS, DNS-over-HTTPS ve DNS-over-TLS", + "enableEncryptionDescription": "EÄŸer ÅŸifreleme etkinleÅŸtirilmiÅŸse, AdGuard Home yönetici arayüzü HTTPS üzerinden çalışacaktır ve DNS sunucusu DNS üzerinden HTTPS ve TLS ile gelen isteklere cevap verecektir.", + "serverConfiguration": "Sunucu yapılandırması", + "domainName": "Alan adı", + "domainNameDescription": "EÄŸer ayarlanırsa, AdGuard Home İstemci Kimliklerini tespit eder, DDR sorgularına yanıt verir ve ek baÄŸlantı doÄŸrulamalarını gerçekleÅŸtirir. Ayarlanmazsa, bu özellikler devre dışı bırakılır. Sertifikadaki DNS adlarından biriyle eÅŸleÅŸmelidir.", + "redirectHttps": "Otomatik olarak HTTPS'e yönlendir", + "httpsPort": "HTTPS baÄŸlantı noktası", + "tlsPort": "DNS-over-TLS baÄŸlantı noktası", + "dnsOverQuicPort": "DNS-over-QUIC baÄŸlantı noktası", + "certificates": "Sertifikalar", + "certificatesDescription": "Åžifreleme kullanmak için, alanınız için geçerli bir SSL sertifikası zinciri saÄŸlamanız gereklidir. letsencrypt.org'dan ücretsiz bir sertifika alabilir veya güvenilir sertifika yetkililerinden satın alabilirsiniz.", + "certificateFilePath": "Bir sertifika dosyası yolu ayarlayın", + "pasteCertificateContent": "Sertifika içeriÄŸini yapıştır", + "certificatePath": "Sertifika dosya yolu", + "certificateContent": "Sertifika içeriÄŸi", + "privateKey": "Private key", + "privateKeyFile": "Özel bir anahtar dosyası belirle", + "pastePrivateKey": "Özel anahtar içeriÄŸini yapıştır", + "usePreviousKey": "Önceden kaydedilmiÅŸ anahtarı kullan", + "privateKeyPath": "Özel anahtar yolu", + "invalidCertificate": "Geçersiz sertifika", + "invalidPrivateKey": "Geçersiz özel anahtar", + "validatingData": "Veri doÄŸrulama", + "dataValid": "Veri geçerli", + "dataNotValid": "Veri geçersiz", + "encryptionConfigSaved": "Åžifreleme yapılandırması baÅŸarıyla kaydedildi", + "encryptionConfigNotSaved": "Åžifreleme yapılandırması kaydedilemedi", + "configError": "Yapılandırma hatası", + "enterOnlyCertificate": "Yalnızca sertifikayı girin. ---BEGIN--- ve ---END--- satırlarını girmeyin.", + "enterOnlyPrivateKey": "Yalnızca anahtarı girin. ---BEGIN--- ve ---END--- satırlarını girmeyin.", + "noItemsSearch": "Bu arama için hiçbir öğe yok.", + "clearSearch": "Aramayı temizle", + "exitSearch": "Aramadan çık", + "searchClients": "İstemcileri ara", + "noClientsSearch": "Bu arama ile ilgili hiçbir istemci bulunamadı.", + "customization": "ÖzelleÅŸtirme", + "customizationDescription": "Bu uygulamayı özelleÅŸtir", + "color": "Renk", + "useDynamicTheme": "Dinamik renk teması kullan", + "red": "Kırmızı", + "green": "YeÅŸil", + "blue": "Mavi", + "yellow": "Sarı", + "orange": "Turuncu", + "brown": "Kahverengi", + "cyan": "CamgöbeÄŸi", + "purple": "Mor", + "pink": "Pembe", + "deepOrange": "Koyu turuncu", + "indigo": "Çivit mavisi", + "useThemeColorStatus": "Durum için tema rengini kullanın", + "useThemeColorStatusDescription": "YeÅŸil ve kırmızı durum renklerini tema rengi ve gri ile deÄŸiÅŸtirir", + "invalidCertificateChain": "Geçersiz sertifika zinciri", + "validCertificateChain": "Geçerli sertifika zinciri", + "subject": "Konu", + "issuer": "İhraççı", + "expires": "Süresi dolacak", + "validPrivateKey": "Geçerli özel anahtar", + "expirationDate": "Son kullanma tarihi", + "keysNotMatch": "Geçersiz bir sertifika veya anahtar: tls: özel anahtar genel anahtarla eÅŸleÅŸmiyor.", + "timeLogs": "Günlüklerdeki zaman", + "timeLogsDescription": "Günlükler listesinde iÅŸlem süresini göster", + "hostNames": "Ana bilgisayar adları", + "keyType": "Anahtar türü", + "updateAvailable": "Güncelleme mevcut", + "installedVersion": "Yüklü sürüm", + "newVersion": "Yeni sürüm", + "source": "Kaynak", + "downloadUpdate": "Güncellemeyi indir", + "download": "İndir", + "doNotRememberAgainUpdate": "Bu sürüm için tekrar hatırlama.", + "downloadingUpdate": "İndiriliyor", + "completed": "Tamamlandı", + "permissionNotGranted": "İzin verilmedi", + "inputSearchTerm": "Bir arama terimi girin.", + "answers": "Cevaplar", + "copyClipboard": "Panoya kopyala", + "domainCopiedClipboard": "Alan adı panoya kopyalandı", + "clearDnsCache": "DNS önbelleÄŸini temizle", + "clearDnsCacheMessage": "DNS önbelleÄŸini temizlemek istediÄŸinizden emin misiniz?", + "dnsCacheCleared": "DNS önbelleÄŸi baÅŸarıyla temizlendi", + "clearingDnsCache": "Önbellek temizleniyor...", + "dnsCacheNotCleared": "DNS önbelleÄŸi temizlenemedi", + "clientsSelected": "Seçilen istemciler", + "invalidDomain": "Geçersiz alan adı", + "loadingBlockedServicesList": "Engellenen hizmetler listesi yükleniyor...", + "blockedServicesListNotLoaded": "Engellenen hizmetler listesi yüklenemedi", + "error": "Hata", + "updates": "Güncellemeler", + "updatesDescription": "AdGuard Home sunucusunu güncelle", + "updateNow": "Åžimdi güncelle", + "currentVersion": "Mevcut sürüm", + "requestStartUpdateFailed": "Güncellemeyi baÅŸlatma isteÄŸi baÅŸarısız oldu", + "requestStartUpdateSuccessful": "Güncellemeyi baÅŸlatma isteÄŸi baÅŸarılı", + "serverUpdated": "Sunucu güncellendi", + "unknownStatus": "Bilinmeyen durum", + "checkingUpdates": "Güncellemeler kontrol ediliyor...", + "checkUpdates": "Güncellemeleri kontrol et", + "requestingUpdate": "Güncelleme talep ediliyor...", + "autoupdateUnavailable": "Otomatik güncelleme kullanılamıyor", + "autoupdateUnavailableDescription": "Otomatik güncelleme servisi bu sunucu için kullanılamıyor. Bunun nedeni sunucunun bir Docker konteynerinde çalışıyor olması olabilir. Sunucunuzu manuel olarak güncellemeniz gerekecektir.", + "minute": "{time} dakika", + "minutes": "{time} dakikalar", + "hour": "{time} saat", + "hours": "{time} saatler", + "remainingTime": "Kalan süre", + "safeSearchSettings": "Güvenli arama ayarları", + "loadingSafeSearchSettings": "Güvenli arama ayarları yükleniyor...", + "safeSearchSettingsNotLoaded": "Güvenli arama ayarları yüklenirken hata oluÅŸtu.", + "loadingLogsSettings": "Günlük ayarları yükleniyor...", + "selectOptionLeftColumn": "Sol sütundan bir seçenek seçin", + "selectClientLeftColumn": "Sol sütundan bir istemci seçin", + "disableList": "Listeyi devre dışı bırak", + "enableList": "Listeyi etkinleÅŸtir", + "screens": "Ekranlar", + "copiedClipboard": "Panoya kopyalandı", + "seeDetails": "Detayları gör", + "listNotAvailable": "Liste mevcut deÄŸil", + "copyListUrl": "Liste URL'sini kopyala", + "listUrlCopied": "Panoya kopyalanan URL'yi listeleyin", + "unsupportedVersion": "Desteklenmeyen sürüm", + "unsupprtedVersionMessage": "Sunucu sürümünüz {version} için destek garantisi verilmiyor. Bu uygulamanın bu sunucu sürümüyle çalışmasında bazı sorunlar olabilir. AdGuard Home Yöneticisi, AdGuard Home sunucunun kararlı sürümleriyle çalışacak ÅŸekilde tasarlanmıştır. Alfa ve beta sürümleriyle çalışabilir, ancak uyumluluk garanti edilmez ve uygulama bu sürümlerle çalışırken bazı sorunlar yaÅŸayabilir.", + "iUnderstand": "Anladım", + "appUpdates": "Uygulama güncellemeleri", + "usingLatestVersion": "En son sürümü kullanıyorsunuz", + "ipLogs": "IP günlüklerde", + "ipLogsDescription": "Günlüklerde istemci adı yerine her zaman IP adresini göster", + "application": "Uygulama", + "combinedChart": "BirleÅŸtirilmiÅŸ grafik", + "combinedChartDescription": "Tüm grafikleri bir araya getirin", + "statistics": "İstatistikler", + "errorLoadFilters": "Filtreler yüklenirken hata oluÅŸtu.", + "clientRemovedSuccessfully": "İstemci baÅŸarıyla kaldırıldı.", + "editRewriteRule": "Yeniden yazma kuralını düzenle", + "dnsRewriteRuleUpdated": "DNS yeniden yazma kuralı baÅŸarıyla güncellendi", + "dnsRewriteRuleNotUpdated": "DNS yeniden yazma kuralı güncellenemedi", + "updatingRule": "Kural güncelleniyor...", + "serverUpdateNeeded": "Sunucu güncellemesi gerekli", + "updateYourServer": "Bu özelliÄŸi kullanmak için AdGuard Home sunucunuzu {version} veya üzeri bir sürüme güncelleyin.", + "january": "Ocak", + "february": "Åžubat", + "march": "Mart", + "april": "Nisan", + "may": "Mayıs", + "june": "Haziran", + "july": "Temmuz", + "august": "AÄŸustos", + "september": "Eylül", + "october": "Ekim", + "november": "Kasım", + "december": "Aralık", + "malwarePhising": "Zararlı yazılım/oltalama", + "queries": "Sorgular", + "adultSites": "YetiÅŸkin siteleri", + "quickFilters": "Hızlı filtreler", + "searchDomainInternet": "İnternette alan adı ara", + "hideServerAddress": "Sunucu adresini gizle", + "hideServerAddressDescription": "Ana ekranda sunucu adresini gizler", + "topItemsOrder": "En iyi ürün sipariÅŸi", + "topItemsOrderDescription": "Ana ekran üst öğe listelerini sırala", + "topItemsReorderInfo": "Yeniden sıralamak için bir öğeyi basılı tutun ve kaydırın.", + "discardChanges": "DeÄŸiÅŸiklikleri iptal edin", + "discardChangesDescription": "DeÄŸiÅŸiklikleri iptal etmek istediÄŸinizden emin misiniz?" +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index a894dc6..98bb878 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -229,7 +229,8 @@ class _MainState extends State
{ Locale('es', ''), Locale('zh', ''), Locale('zh', 'CN'), - Locale('pl', '') + Locale('pl', ''), + Locale('tr', '') ], scaffoldMessengerKey: scaffoldMessengerKey, builder: (context, child) { From f161842a0857918b08af351cba77bd1dcc01fb9b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 21 Oct 2023 19:02:52 +0200 Subject: [PATCH 329/676] Fixed issue private dns resolvers list --- .../settings/dns/private_reverse_servers.dart | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index cd02684..ea16ea3 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -21,12 +21,7 @@ class PrivateReverseDnsServersScreen extends StatefulWidget { class _PrivateReverseDnsServersScreenState extends State { List defaultReverseResolvers = []; bool editReverseResolvers = false; - List> reverseResolversControllers = [ - { - 'controller': TextEditingController(), - 'error': null - } - ]; + List> reverseResolversControllers = []; bool usePrivateReverseDnsResolvers = false; bool enableReverseResolve = false; @@ -67,13 +62,19 @@ class _PrivateReverseDnsServersScreenState extends State Padding( - padding: const EdgeInsets.only( + padding: const EdgeInsets.only( left: 16, right: 6, bottom: 20 ), child: Row( From 7cd3744f70def2cb3a6feaae1e4716ebad236dfa Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 21 Oct 2023 19:04:58 +0200 Subject: [PATCH 330/676] Bug fix --- lib/models/dns_info.dart | 2 +- lib/screens/settings/dns/private_reverse_servers.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 67103f7..4e85400 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -14,7 +14,7 @@ class DnsInfo { int? cacheTtlMax; bool? cacheOptimistic; bool? resolveClients; - bool usePrivatePtrResolvers; + bool? usePrivatePtrResolvers; List localPtrUpstreams; String blockingIpv4; String blockingIpv6; diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index ea16ea3..eb0f16a 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -79,7 +79,7 @@ class _PrivateReverseDnsServersScreenState extends State Date: Sat, 21 Oct 2023 21:06:38 +0200 Subject: [PATCH 331/676] Added ring chart home top items --- lib/l10n/app_en.arb | 11 +- lib/l10n/app_es.arb | 11 +- lib/screens/home/home.dart | 229 ++++++++------- lib/screens/home/top_items.dart | 451 ++++++++++++++++++++++-------- lib/widgets/custom_pie_chart.dart | 32 +++ pubspec.lock | 8 + pubspec.yaml | 1 + 7 files changed, 512 insertions(+), 231 deletions(-) create mode 100644 lib/widgets/custom_pie_chart.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f54e491..b9c7b1e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -57,10 +57,10 @@ "serverStatusNotRefreshed": "Server status could not be refreshed", "loadingStatus": "Loading status...", "errorLoadServerStatus": "Server status could not be loaded", - "topQueriedDomains": "Top queried domains", + "topQueriedDomains": "Queried domains", "viewMore": "View more", - "topClients": "Top clients", - "topBlockedDomains": "Top blocked domains", + "topClients": "Cients", + "topBlockedDomains": "Blocked domains", "appSettings": "App settings", "theme": "Theme", "light": "Light", @@ -662,5 +662,8 @@ "topItemsOrderDescription": "Order the home screen top items lists", "topItemsReorderInfo": "Hold and swipe an item to reorder it.", "discardChanges": "Discard changes", - "discardChangesDescription": "Are you sure you want to discard the changes?" + "discardChangesDescription": "Are you sure you want to discard the changes?", + "others": "Others", + "showChart": "Show chart", + "hideChart": "Hide chart" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index d0c7a15..fe13bcd 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -57,10 +57,10 @@ "serverStatusNotRefreshed": "No se ha podido actualizar el estado del servidor", "loadingStatus": "Cargando estado...", "errorLoadServerStatus": "Error al cargar el estado", - "topQueriedDomains": "Top dominios solicitados", + "topQueriedDomains": "Dominios solicitados", "viewMore": "Ver más", - "topClients": "Top clientes recurrentes", - "topBlockedDomains": "Top dominios bloqueados", + "topClients": "Clientes recurrentes", + "topBlockedDomains": "Dominios bloqueados", "appSettings": "Ajustes de la app", "theme": "Tema", "light": "Claro", @@ -662,5 +662,8 @@ "topItemsOrderDescription": "Ordena las listas de top de elementos en la pantalla de inicio", "topItemsReorderInfo": "Mantén presionado y desliza un elemento para reordenarlo.", "discardChanges": "Descartar cambios", - "discardChangesDescription": "¿Estás seguro de que deseas descartar los cambios realizados?" + "discardChangesDescription": "¿Estás seguro de que deseas descartar los cambios realizados?", + "others": "Otros", + "showChart": "Mostrar gráfico", + "hideChart": "Ocultar gráfico" } \ No newline at end of file diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 01d251d..59fb0bf 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -175,110 +175,66 @@ class _HomeState extends State { child: CombinedHomeChart(), ), - if (width <= 700) ...appConfigProvider.homeTopItemsOrder.asMap().entries.map((item) { - Widget list() { - switch (item.value) { - case HomeTopItems.queriedDomains: - return TopItems( - label: AppLocalizations.of(context)!.topQueriedDomains, - data: statusProvider.serverStatus!.stats.topQueriedDomains, - type: 'topQueriedDomains', - ); - - case HomeTopItems.blockedDomains: - return TopItems( - label: AppLocalizations.of(context)!.topBlockedDomains, - data: statusProvider.serverStatus!.stats.topBlockedDomains, - type: 'topBlockedDomains', - ); - - case HomeTopItems.recurrentClients: - return TopItems( - label: AppLocalizations.of(context)!.topClients, - data: statusProvider.serverStatus!.stats.topClients, - type: 'topClients', - clients: true, - ); - - default: - return const SizedBox(); - } - } - - return Column( - children: [ - list(), - if (item.key < appConfigProvider.homeTopItemsOrder.length - 1) ...[ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), - ), - ), - const SizedBox(height: 16), - ] - ], - ); - }), - if (width > 700) Column( - children: [ - Wrap( - alignment: WrapAlignment.center, - children: appConfigProvider.homeTopItemsOrder.map((item) { - switch (item) { - case HomeTopItems.queriedDomains: - return Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: TopItems( - label: AppLocalizations.of(context)!.topQueriedDomains, - data: statusProvider.serverStatus!.stats.topQueriedDomains, - type: 'topQueriedDomains', - ), - ), - ); + TopItemsLists(order: appConfigProvider.homeTopItemsOrder), - case HomeTopItems.blockedDomains: - return Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: TopItems( - label: AppLocalizations.of(context)!.topBlockedDomains, - data: statusProvider.serverStatus!.stats.topBlockedDomains, - type: 'topBlockedDomains', - ), - ), - ); + // if (width > 700) Column( + // children: [ + // Wrap( + // alignment: WrapAlignment.center, + // children: appConfigProvider.homeTopItemsOrder.map((item) { + // switch (item) { + // case HomeTopItems.queriedDomains: + // return Padding( + // padding: const EdgeInsets.only(bottom: 16), + // child: ConstrainedBox( + // constraints: const BoxConstraints( + // maxWidth: 500 + // ), + // child: TopItems( + // label: AppLocalizations.of(context)!.topQueriedDomains, + // data: statusProvider.serverStatus!.stats.topQueriedDomains, + // type: 'topQueriedDomains', + // ), + // ), + // ); - case HomeTopItems.recurrentClients: - return Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: TopItems( - label: AppLocalizations.of(context)!.topClients, - data: statusProvider.serverStatus!.stats.topClients, - type: 'topClients', - ), - ), - ); + // case HomeTopItems.blockedDomains: + // return Padding( + // padding: const EdgeInsets.only(bottom: 16), + // child: ConstrainedBox( + // constraints: const BoxConstraints( + // maxWidth: 500 + // ), + // child: TopItems( + // label: AppLocalizations.of(context)!.topBlockedDomains, + // data: statusProvider.serverStatus!.stats.topBlockedDomains, + // type: 'topBlockedDomains', + // ), + // ), + // ); + + // case HomeTopItems.recurrentClients: + // return Padding( + // padding: const EdgeInsets.only(bottom: 16), + // child: ConstrainedBox( + // constraints: const BoxConstraints( + // maxWidth: 500 + // ), + // child: TopItems( + // label: AppLocalizations.of(context)!.topClients, + // data: statusProvider.serverStatus!.stats.topClients, + // type: 'topClients', + // ), + // ), + // ); - default: - return const SizedBox(); - } - }).toList(), - ), - ], - ) + // default: + // return const SizedBox(); + // } + // }).toList(), + // ), + // ], + // ) ]; } @@ -348,4 +304,75 @@ class _HomeState extends State { ), ); } +} + +class TopItemsLists extends StatelessWidget { + final List order; + + const TopItemsLists({ + Key? key, + required this.order, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + + List bottom = [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + ), + const SizedBox(height: 16), + ]; + + return Column( + children: order.asMap().entries.map((item) { + switch (item.value) { + case HomeTopItems.queriedDomains: + return Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.topQueriedDomains, + data: statusProvider.serverStatus!.stats.topQueriedDomains, + type: 'topQueriedDomains', + ), + if (item.key < order.length - 1) ...bottom + ], + ); + + case HomeTopItems.blockedDomains: + return Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.topBlockedDomains, + data: statusProvider.serverStatus!.stats.topBlockedDomains, + type: 'topBlockedDomains', + ), + if (item.key < order.length - 1) ...bottom + ], + ); + + case HomeTopItems.recurrentClients: + return Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.topClients, + data: statusProvider.serverStatus!.stats.topClients, + type: 'topClients', + clients: true, + ), + if (item.key < order.length - 1) ...bottom + ], + ); + + default: + return const SizedBox(); + } + }).toList(), + ); + } } \ No newline at end of file diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index c43ba3a..9cacd68 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; import 'package:adguard_home_manager/widgets/domain_options.dart'; import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; @@ -15,7 +16,7 @@ import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class TopItems extends StatelessWidget { +class TopItems extends StatefulWidget { final String type; final String label; final List> data; @@ -29,104 +30,30 @@ class TopItems extends StatelessWidget { this.clients }) : super(key: key); + @override + State createState() => _TopItemsState(); +} + +class _TopItemsState extends State { + bool _showChart = true; + + final colors = [ + Colors.red, + Colors.green, + Colors.blue, + Colors.orange, + Colors.teal, + Colors.grey + ]; + @override Widget build(BuildContext context) { final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; - Widget rowItem(Map item) { - String? name; - if (clients != null && clients == true) { - try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(item.keys.toList()[0])).name; - } catch (e) { - // ---- // - } - } - - return Material( - color: Colors.transparent, - child: DomainOptions( - item: item.keys.toList()[0], - isClient: type == 'topClients', - isBlocked: type == 'topBlockedDomains', - onTap: () { - if (type == 'topQueriedDomains' || type == 'topBlockedDomains') { - logsProvider.setSearchText(item.keys.toList()[0]); - logsProvider.setSelectedClients(null); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: item.keys.toList()[0], - clients: null - ) - ); - appConfigProvider.setSelectedScreen(2); - } - else if (type == 'topClients') { - logsProvider.setSearchText(null); - logsProvider.setSelectedClients([item.keys.toList()[0]]); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: null, - clients: [item.keys.toList()[0]] - ) - ); - } - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - item.keys.toList()[0], - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - if (name != null) ...[ - const SizedBox(height: 5), - Text( - name, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ] - ], - ), - ), - Text( - item.values.toList()[0].toString(), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - ), - ), - ); - } - List> generateData() { - switch (type) { + switch (widget.type) { case 'topQueriedDomains': return statusProvider.serverStatus!.stats.topQueriedDomains; @@ -141,37 +68,123 @@ class TopItems extends StatelessWidget { } } + Map chartData() { + Map values = {}; + widget.data.sublist(0, widget.data.length > 5 ? 5 : widget.data.length).forEach((element) { + values = { + ...values, + element.keys.first: element.values.first.toDouble() + }; + }); + if (widget.data.length > 5) { + final int rest = List.from( + widget.data.sublist(5, widget.data.length).map((e) => e.values.first.toInt()) + ).reduce((a, b) => a + b); + values = { + ...values, + AppLocalizations.of(context)!.others: rest.toDouble() + }; + } + return values; + } + + final List itemsList = widget.data.sublist( + 0, + widget.data.length > 5 ? 5 : widget.data.length + ).asMap().entries.map((e) => RowItem( + clients: widget.clients ?? false, + domain: e.value.keys.toList()[0], + number: e.value.values.toList()[0].toString(), + type: widget.type, + chartColor: _showChart ? colors[e.key] : null, + )).toList(); + + final Widget noItems = Padding( + padding: const EdgeInsets.only( + bottom: 20, + top: 10 + ), + child: Text( + AppLocalizations.of(context)!.noItems, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ); + + final Widget chart = CustomPieChart( + data: chartData(), + colors: colors + ); + return SizedBox( child: Column( children: [ - Text( - label, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: width <= 700 + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.center, + children: [ + Text( + widget.label, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + if (width <= 700) TextButton( + onPressed: () => setState(() => _showChart = !_showChart), + child: Text( + _showChart + ? AppLocalizations.of(context)!.hideChart + : AppLocalizations.of(context)!.showChart + ) + ) + ], ), ), - const SizedBox(height: 20), - if (data.isEmpty) Padding( - padding: const EdgeInsets.only( - bottom: 20, - top: 10 - ), - child: Text( - AppLocalizations.of(context)!.noItems, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), + + const SizedBox(height: 24), + + if (widget.data.isEmpty) noItems, + if (widget.data.isNotEmpty && width > 700) SizedBox( + height: 240, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: Padding( + padding: const EdgeInsets.all(16), + child: chart, + ) + ), + Expanded( + flex: 2, + child: Column( + children: [ + ...itemsList, + OthersRowItem(items: widget.data) + ] + ), + ) + ], ), ), - if (data.isNotEmpty) rowItem(data[0]), - if (data.length >= 2) rowItem(data[1]), - if (data.length >= 3) rowItem(data[2]), - if (data.length >= 4) rowItem(data[3]), - if (data.length >= 5) rowItem(data[4]), - if (data.length > 5) ...[ + if (widget.data.isNotEmpty && width <= 700) ...[ + if (_showChart) ...[ + chart, + const SizedBox(height: 16), + ], + ...itemsList, + if (_showChart) OthersRowItem(items: widget.data) + ], + + if (widget.data.length > 5) ...[ const SizedBox(height: 20), Padding( padding: const EdgeInsets.only(right: 20), @@ -185,9 +198,9 @@ class TopItems extends StatelessWidget { context: context, barrierDismissible: false, builder: (context) => TopItemsModal( - type: type, - title: label, - isClient: clients, + type: widget.type, + title: widget.label, + isClient: widget.clients, data: generateData(), ) ) @@ -196,9 +209,9 @@ class TopItems extends StatelessWidget { Navigator.of(context).push( MaterialPageRoute( builder: (context) => TopItemsScreen( - type: type, - title: label, - isClient: clients, + type: widget.type, + title: widget.label, + isClient: widget.clients, data: generateData(), ) ) @@ -226,4 +239,198 @@ class TopItems extends StatelessWidget { ), ); } +} + +class RowItem extends StatelessWidget { + final String type; + final Color? chartColor; + final String domain; + final String number; + final bool clients; + + const RowItem({ + Key? key, + required this.type, + this.chartColor, + required this.domain, + required this.number, + required this.clients + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + final logsProvider = Provider.of(context); + + String? name; + if (clients == true) { + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(domain)).name; + } catch (e) { + // ---- // + } + } + + return Material( + color: Colors.transparent, + child: DomainOptions( + item: domain, + isClient: type == 'topClients', + isBlocked: type == 'topBlockedDomains', + onTap: () { + if (type == 'topQueriedDomains' || type == 'topBlockedDomains') { + logsProvider.setSearchText(domain); + logsProvider.setSelectedClients(null); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: domain, + clients: null + ) + ); + appConfigProvider.setSelectedScreen(2); + } + else if (type == 'topClients') { + logsProvider.setSearchText(null); + logsProvider.setSelectedClients([domain]); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: null, + clients: [domain] + ) + ); + } + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + children: [ + if (chartColor != null) Container( + margin: const EdgeInsets.only(right: 16), + width: 12, + height: 12, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: chartColor + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + domain, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + if (name != null) ...[ + const SizedBox(height: 5), + Text( + name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ] + ], + ), + ), + ], + ), + ), + const SizedBox(width: 16), + Text( + number, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + ), + ), + ); + } +} + +class OthersRowItem extends StatelessWidget { + final List> items; + + const OthersRowItem({ + Key? key, + required this.items + }) : super(key: key); + + @override + Widget build(BuildContext context) { + + if (items.length <= 5) { + return const SizedBox(); + } + + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 16), + width: 12, + height: 12, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Colors.grey + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.others, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ), + ], + ), + ), + const SizedBox(width: 16), + Text( + List.from( + items.sublist(5, items.length).map((e) => e.values.first.toInt()) + ).reduce((a, b) => a + b).toString(), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + ); + } } \ No newline at end of file diff --git a/lib/widgets/custom_pie_chart.dart b/lib/widgets/custom_pie_chart.dart new file mode 100644 index 0000000..2968568 --- /dev/null +++ b/lib/widgets/custom_pie_chart.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:pie_chart/pie_chart.dart'; + +class CustomPieChart extends StatelessWidget { + final Map data; + final List colors; + + const CustomPieChart({ + Key? key, + required this.data, + required this.colors, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return PieChart( + dataMap: data, + animationDuration: const Duration(milliseconds: 800), + chartRadius: MediaQuery.of(context).size.width / 3, + colorList: colors, + initialAngleInDegree: 270, + chartType: ChartType.ring, + ringStrokeWidth: 12, + legendOptions: const LegendOptions( + showLegends: false + ), + chartValuesOptions: const ChartValuesOptions( + showChartValues: false, + ), + ); + } +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index d0842e2..c647bf5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -478,6 +478,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.4.0" + pie_chart: + dependency: "direct main" + description: + name: pie_chart + sha256: "5dba6d0eb4718e8ed00a9079361cd8947c3f84ac5a5d76f05a27f4ec5e27589e" + url: "https://pub.dev" + source: hosted + version: "5.3.2" plugin_platform_interface: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d18eb72..2445ec4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -73,6 +73,7 @@ dependencies: sentry_flutter: ^7.9.0 flutter_dotenv: ^5.0.2 flutter_reorderable_list: ^1.3.1 + pie_chart: ^5.3.2 dev_dependencies: flutter_test: From 8c0a5bc98b6c654c6fc5cbdf30ccafa56e9f8c6d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 21 Oct 2023 21:17:28 +0200 Subject: [PATCH 332/676] Added settings config --- lib/l10n/app_en.arb | 4 ++- lib/l10n/app_es.arb | 4 ++- lib/providers/app_config_provider.dart | 23 +++++++++++++ lib/screens/home/top_items.dart | 6 ++++ .../general_settings/general_settings.dart | 22 +++++++++++++ lib/services/db/database.dart | 33 ++++++++++++++++--- 6 files changed, 86 insertions(+), 6 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index b9c7b1e..451e4e1 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -665,5 +665,7 @@ "discardChangesDescription": "Are you sure you want to discard the changes?", "others": "Others", "showChart": "Show chart", - "hideChart": "Hide chart" + "hideChart": "Hide chart", + "showTopItemsChart": "Show top items chart", + "showTopItemsChartDescription": "Shows by default the ring chart on the top items sections. Only affects to the mobile view." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index fe13bcd..4276b7b 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -665,5 +665,7 @@ "discardChangesDescription": "¿Estás seguro de que deseas descartar los cambios realizados?", "others": "Otros", "showChart": "Mostrar gráfico", - "hideChart": "Ocultar gráfico" + "hideChart": "Ocultar gráfico", + "showTopItemsChart": "Mostrar gráfico en top de items", + "showTopItemsChartDescription": "Muestra por defecto el gráfico de anillo en las secciones de top de items. Sólo afecta a la vista móvil." } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 3522edc..16e855f 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -52,6 +52,8 @@ class AppConfigProvider with ChangeNotifier { int _combinedChartHome = 0; + int _showTopItemsChart = 0; + String? _doNotRememberVersion; GitHubRelease? _appUpdatesAvailable; @@ -168,6 +170,10 @@ class AppConfigProvider with ChangeNotifier { return _hideServerAddress == 1 ? true : false; } + bool get showTopItemsChart { + return _showTopItemsChart == 1 ? true : false; + } + void setDbInstance(Database db) { _dbInstance = db; } @@ -402,6 +408,22 @@ class AppConfigProvider with ChangeNotifier { } } + Future setShowTopItemsChart(bool value) async { + final updated = await updateConfigQuery( + db: _dbInstance!, + column: 'showTopItemsChart', + value: value == true ? 1 : 0 + ); + if (updated == true) { + _showTopItemsChart = value == true ? 1 : 0; + notifyListeners(); + return true; + } + else { + return false; + } + } + Future setDoNotRememberVersion(String value) async { final updated = await updateConfigQuery( @@ -424,6 +446,7 @@ class AppConfigProvider with ChangeNotifier { _showIpLogs = dbData['showIpLogs'] ?? 0; _combinedChartHome = dbData['combinedChart'] ?? 0; _hideServerAddress = dbData['hideServerAddress']; + _showTopItemsChart = dbData['showTopItemsChart']; if (dbData['homeTopItemsOrder'] != null) { try { _homeTopItemsOrder = List.from( diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 9cacd68..24dd6db 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -46,6 +46,12 @@ class _TopItemsState extends State { Colors.grey ]; + @override + void initState() { + _showChart = Provider.of(context, listen: false).showTopItemsChart; + super.initState(); + } + @override Widget build(BuildContext context) { final statusProvider = Provider.of(context); diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index c5ba7cb..9ead014 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -191,6 +191,28 @@ class _GeneralSettingsState extends State { builder: (context) => const ReorderableTopItemsHome() )), ), + CustomListTile( + icon: Icons.donut_large_rounded, + title: AppLocalizations.of(context)!.showTopItemsChart, + subtitle: AppLocalizations.of(context)!.showTopItemsChartDescription, + trailing: Switch( + value: appConfigProvider.showTopItemsChart, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setShowTopItemsChart + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.showTopItemsChart, + function: appConfigProvider.setShowTopItemsChart + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) + ), SectionLabel(label: AppLocalizations.of(context)!.logs), CustomListTile( icon: Icons.timer_rounded, diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index 5fed50f..7d8cf13 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -116,9 +116,20 @@ Future> loadDb(bool acceptsDynamicTheme) async { }); } + Future upgradeDbToV10(Database db) async { + await db.execute("ALTER TABLE appConfig ADD COLUMN showTopItemsChart NUMERIC"); + await db.execute("UPDATE appConfig SET showTopItemsChart = 1"); + + await db.transaction((txn) async{ + await txn.rawQuery( + 'SELECT * FROM appConfig', + ); + }); + } + Database db = await openDatabase( 'adguard_home_manager.db', - version: 9, + version: 10, onCreate: (Database db, int version) async { await db.execute( """ @@ -154,7 +165,8 @@ Future> loadDb(bool acceptsDynamicTheme) async { combinedChart NUMERIC, doNotRememberVersion TEXT, hideServerAddress NUMERIC, - homeTopItemsOrder TEXT + homeTopItemsOrder TEXT, + showTopItemsChart NUMERIC ) """ ); @@ -173,7 +185,8 @@ Future> loadDb(bool acceptsDynamicTheme) async { showIpLogs, combinedChart, hideServerAddress, - homeTopItemsOrder + homeTopItemsOrder, + showTopItemsChart ) VALUES ( 0, @@ -186,7 +199,8 @@ Future> loadDb(bool acceptsDynamicTheme) async { 0, 0, 0, - '$homeTopItemsDefaultOrderString' + '$homeTopItemsDefaultOrderString', + 1 ) """ ); @@ -201,6 +215,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV7(db); await upgradeDbToV8(db); await upgradeDbToV9(db); + await upgradeDbToV10(db); } if (oldVersion == 2) { await upgradeDbToV3(db); @@ -210,6 +225,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV7(db); await upgradeDbToV8(db); await upgradeDbToV9(db); + await upgradeDbToV10(db); } if (oldVersion == 3) { await upgradeDbToV4(db); @@ -218,6 +234,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV7(db); await upgradeDbToV8(db); await upgradeDbToV9(db); + await upgradeDbToV10(db); } if (oldVersion == 4) { await upgradeDbToV5(db); @@ -225,24 +242,32 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV7(db); await upgradeDbToV8(db); await upgradeDbToV9(db); + await upgradeDbToV10(db); } if (oldVersion == 5) { await upgradeDbToV6(db); await upgradeDbToV7(db); await upgradeDbToV8(db); await upgradeDbToV9(db); + await upgradeDbToV10(db); } if (oldVersion == 6) { await upgradeDbToV7(db); await upgradeDbToV8(db); await upgradeDbToV9(db); + await upgradeDbToV10(db); } if (oldVersion == 7) { await upgradeDbToV8(db); await upgradeDbToV9(db); + await upgradeDbToV10(db); } if (oldVersion == 8) { await upgradeDbToV9(db); + await upgradeDbToV10(db); + } + if (oldVersion == 9) { + await upgradeDbToV10(db); } }, onOpen: (Database db) async { From 14b7232e8aa199dcf0c9c99fd9a1b53c2d174520 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 21 Oct 2023 21:19:40 +0200 Subject: [PATCH 333/676] Updated readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d8e05f3..864b3de 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,8 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [async](https://pub.dev/packages/async) - [sentry flutter](https://pub.dev/packages/sentry_flutter) - [flutter dotenv](https://pub.dev/packages/flutter_dotenv) +- [flutter reorderable list](https://pub.dev/packages/flutter_reorderable_list) +- [pie chart](https://pub.dev/packages/pie_chart)
From 3e71abc8dc8fca56e2a9577ac031e84e09469b9e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 23 Oct 2023 10:32:49 +0200 Subject: [PATCH 334/676] Updated turkish translation --- lib/l10n/app_tr.arb | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index b7b3c93..c89a8b6 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -37,7 +37,7 @@ "connectionRemoved": "Bağlantı başarıyla kaldırıldı", "connectionCannotBeRemoved": "Bağlantı kaldırılamaz.", "remove": "Kaldır", - "removeWarning": "Bu AdGuard Home sunucusuyla bağlantıyı kaldırmak istediğinizden emin misiniz?", + "removeWarning": "Bu AdGuard Home sunucusuyla olan bağlantıyı kaldırmak istediğinizden emin misiniz?", "cancel": "İptal", "defaultConnection": "Varsayılan bağlantı", "setDefault": "Varsayılan ayarla", @@ -45,7 +45,7 @@ "delete": "Sil", "save": "Kaydet", "serverStatus": "Sunucu durumu", - "connectionNotUpdated": "Bağlantı güncellenmedi", + "connectionNotUpdated": "Bağlantı Güncellenmedi", "ruleFilteringWidget": "Kural filtreleme bileşeni", "safeBrowsingWidget": "Güvenli gezinti bileşeni", "parentalFilteringWidget": "Ebeveyn filtreleme bileşeni", @@ -78,7 +78,7 @@ "helperPath": "Ters proxy kullanıyorsanız", "aboutApp": "Uygulama hakkında", "appVersion": "Uygulama sürümü", - "createdBy": "Tarafından oluşturuldu", + "createdBy": "Yapımcı", "clients": "İstemciler", "allowed": "İzin verildi", "blocked": "Engellendi", @@ -159,7 +159,7 @@ "notSelected": "Seçili değil", "resetFilters": "Filtreleri sıfırla", "noLogsDisplay": "Gösterilecek günlük yok", - "noLogsThatOld": "Seçilen zamanda kaydedilmiş herhangi bir kayıt olmayabilir. Daha yakın bir zamanı seçmeyi deneyin.", + "noLogsThatOld": "Seçilen zaman için kaydedilmiş herhangi bir günlük bulunmuyor olabilir. Daha yakın bir zaman seçmeyi deneyin.", "apply": "Uygula", "selectAll": "Hepsini seç", "unselectAll": "Seçimleri kaldır", @@ -264,7 +264,7 @@ "loadingServerInfo": "Sunucu bilgisi yükleniyor...", "serverInfoNotLoaded": "Sunucu bilgisi yüklenemedi.", "dnsAddresses": "DNS adresleri", - "seeDnsAddresses": "DNS adreslerine bakın", + "seeDnsAddresses": "DNS adreslerine bak", "dnsPort": "DNS bağlantı noktası", "httpPort": "HTTP bağlantı noktası", "protectionEnabled": "Koruma etkin", @@ -308,8 +308,8 @@ "addImportant": "Ekle $important", "howCreateRules": "Özel kurallar nasıl oluşturulur?", "examples": "Örnekler", - "example1": "example.org ve tüm alt alanlarına erişimi engeller.", - "example2": "example.org ve tüm alt alanlarına erişimi engellemeyi kaldırır.", + "example1": "ornek.org ve tüm alt alanlarına erişimi engeller.", + "example2": "ornek.org ve tüm alt alanlarına erişimi engellemeyi kaldırır.", "example3": "Yorum ekler.", "example4": "Belirtilen düzenli ifadeye uyan alan adlarına erişimi engeller.", "moreInformation": "Daha fazla bilgi", @@ -409,7 +409,7 @@ "logsSettings": "Günlük ayarları", "enableLog": "Günlüğü etkinleştir", "clearLogs": "Günlükleri temizle", - "anonymizeClientIp": "İstemci IP'sini anonimleştirin", + "anonymizeClientIp": "İstemci IP'sini anonimleştir", "hours6": "6 saat", "days30": "30 gün", "days90": "90 gün", @@ -435,11 +435,11 @@ "loadBalancing": "Yük dengeleme", "parallelRequests": "Paralel istekler", "fastestIpAddress": "En hızlı IP adresi", - "loadBalancingDescription": "Her seferinde bir üst akış sunucusuna sorgu yap. AdGuard Home, en hızlı sunucunun daha sık kullanılması için ağırlıklı rasgele bir algoritma kullanır.", - "parallelRequestsDescription": "Çözümlemeyi hızlandırmak için tüm üst akış sunucularına aynı anda sorgu yaparak paralel sorguları kullanın.", + "loadBalancingDescription": "Her seferinde bir üst akış sunucusuna sorgu yap. AdGuard Home, sunucuyu seçmek için ağırlıklı rastgele algoritmasını kullanır, böylece en hızlı sunucu daha sık kullanılır.", + "parallelRequestsDescription": "Tüm üst akış sunucularını aynı anda sorgulayarak çözümlemeyi hızlandırmak için paralel sorgular kullanın.", "fastestIpAddressDescription": "Tüm DNS sunucularına sorgu yapın ve tüm yanıtlar arasında en hızlı IP adresini döndürün. Bu, AdGuard Home'un tüm DNS sunucularından yanıtları beklemesi gerektiği için DNS sorgularını yavaşlatır, ancak genel bağlantıyı iyileştirir.", "noBootstrapDns": "Önyükleme DNS sunucuları eklenmedi.", - "bootstrapDnsServersInfo": "Önyükleme ​​DNS sunucuları, yukarı akışlarda belirttiğiniz DoH/DoT çözümleyicilerinin IP adreslerini çözmek için kullanılır.", + "bootstrapDnsServersInfo": "Önyükleme ​​DNS sunucuları, üst akışlarda belirttiğiniz DoH/DoT çözümleyicilerinin IP adreslerini çözmek için kullanılır.", "privateReverseDnsServers": "Özel ters DNS sunucuları", "privateReverseDnsServersDescription": "AdGuard Home'un yerel PTR sorguları için kullandığı DNS sunucuları. Bu sunucular, özel IP aralıklarındaki adresler için ters DNS kullanarak PTR isteklerini çözmek için kullanılır, örneğin '192.168.12.34' olarak ayarlanmamışsa AdGuard Home, AdGuard Home'un kendi adresleri dışında, işletim sisteminizin varsayılan DNS çözümleyicilerinin adreslerini kullanır.", "reverseDnsDefault": "Varsayılan olarak, AdGuard Home aşağıdaki ters DNS çözümleyicilerini kullanır", @@ -451,7 +451,7 @@ "enableReverseResolvingDescription": "İstemcilerin IP adreslerini karşılık gelen çözücülere PTR sorguları göndererek IP adreslerini tersine çözümleyerek (yerel istemciler için özel DNS sunucuları, genel IP adresine sahip istemciler için yukarı akış sunucuları) istemcilerin ana bilgisayar adlarını tersine çöz.", "dnsServerSettings": "AdGuard Home DNS sunucusu ayarları", "limitRequestsSecond": "Saniye başına hız limiti", - "valueNotNumber": "Değer bir rakam değildir", + "valueNotNumber": "Değer bir sayı değil", "enableEdns": "EDNS istemci alt ağını etkinleştir", "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı Seçeneği (ECS) ekleyin ve istemciler tarafından gönderilen değerleri sorgu günlüğünde kaydet.", "enableDnssec": "DNSSEC'i Etkinleştir", @@ -555,7 +555,7 @@ "invalidCertificateChain": "Geçersiz sertifika zinciri", "validCertificateChain": "Geçerli sertifika zinciri", "subject": "Konu", - "issuer": "İhraççı", + "issuer": "Veren", "expires": "Süresi dolacak", "validPrivateKey": "Geçerli özel anahtar", "expirationDate": "Son kullanma tarihi", From 2c8b5b9c6d18e81033d21eb87a6ad3bdfea4e408 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 23 Oct 2023 18:08:02 +0200 Subject: [PATCH 335/676] Updated turkish translation --- lib/l10n/app_tr.arb | 99 ++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 47 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index c89a8b6..08a7842 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -46,10 +46,10 @@ "save": "Kaydet", "serverStatus": "Sunucu durumu", "connectionNotUpdated": "Bağlantı Güncellenmedi", - "ruleFilteringWidget": "Kural filtreleme bileşeni", - "safeBrowsingWidget": "Güvenli gezinti bileşeni", - "parentalFilteringWidget": "Ebeveyn filtreleme bileşeni", - "safeSearchWidget": "Güvenli arama bileşeni", + "ruleFilteringWidget": "Kural filtreleme", + "safeBrowsingWidget": "Güvenli gezinti", + "parentalFilteringWidget": "Ebeveyn filtreleme", + "safeSearchWidget": "Güvenli arama", "ruleFiltering": "Kural filtreleme", "safeBrowsing": "Güvenli gezinti", "parentalFiltering": "Ebeveyn filtreleme", @@ -57,15 +57,15 @@ "serverStatusNotRefreshed": "Sunucu durumu yenilenemedi", "loadingStatus": "Durum yükleniyor...", "errorLoadServerStatus": "Sunucu durumu yüklenemedi", - "topQueriedDomains": "En çok sorgulanan alan adları", + "topQueriedDomains": "En çok sorgulananlar", "viewMore": "Daha fazla göster", "topClients": "Öne çıkan istemciler", - "topBlockedDomains": "En çok engellenen alan adları", + "topBlockedDomains": "En çok engellenenler", "appSettings": "Uygulama ayarları", "theme": "Tema", "light": "Aydınlık", "dark": "Karanlık", - "systemDefined": "Tanımlanmış sistem", + "systemDefined": "Sistem temasına uy", "close": "Kapat", "connectedTo": "Bağlandı:", "selectedServer": "Seçili sunucu:", @@ -102,7 +102,7 @@ "copyLogsClipboard": "Günlükleri panoya kopyala", "logsCopiedClipboard": "Günlükler panoya kopyalandı", "advancedSettings": "Gelişmiş ayarlar", - "dontCheckCertificate": "SSL sertifikasını kontrol etme", + "dontCheckCertificate": "SSL sertifikası kontrol edilmesin", "dontCheckCertificateDescription": "Sunucunun SSL sertifikası doğrulamasını geçersiz kılar", "advancedSetupDescription": "Gelişmiş seçenekler", "settingsUpdatedSuccessfully": "Ayarlar başarıyla güncellendi.", @@ -143,7 +143,7 @@ "responseCode": "Yanıt kodu", "client": "İstemci", "deviceIp": "IP adresi", - "deviceName": "Ad", + "deviceName": "İstemci adı", "logDetails": "Günlük detayları", "blockingRule": "Engelleme kuralı", "blockDomain": "Alan adını engelle", @@ -170,9 +170,9 @@ "search": "Ara", "dnsQueries": "DNS sorguları", "average": "Ortalama", - "blockedFilters": "Filtreler tarafından engellenen", - "malwarePhisingBlocked": "Engellenen zararlı yazılım/oltalama ", - "blockedAdultWebsites": "Engellenen yetişkin siteleri", + "blockedFilters": "Engellenen (Alan adları)", + "malwarePhisingBlocked": "Engellenen (Zararlı içerik)", + "blockedAdultWebsites": "Engellenen (Yetişkin içerik)", "generalSettings": "Genel ayarlar", "generalSettingsDescription": "Çeşitli farklı ayarlar", "hideZeroValues": "Sıfır değerlerini gizle", @@ -190,9 +190,9 @@ "noIdentifiers": "Tanımlayıcı eklenmedi", "useGlobalSettings": "Küresel ayarları kullan", "enableFiltering": "Filtrelemeyi etkinleştir", - "enableSafeBrowsing": "Güvenli gezintiyi etkinleştirin", - "enableParentalControl": "Ebeveyn kontrolünü etkinleştirinl", - "enableSafeSearch": "Güvenli aramayı etkinleştirin", + "enableSafeBrowsing": "Güvenli gezintiyi etkinleştir", + "enableParentalControl": "Ebeveyn kontrolünü etkinleştir", + "enableSafeSearch": "Güvenli aramayı etkinleştir", "blockedServices": "Engellenen hizmetler", "selectBlockedServices": "Engellenen hizmetleri seç", "noBlockedServicesSelected": "Engellenen hizmetler seçilmedi", @@ -214,8 +214,8 @@ "whitelists": "Beyaz listeler", "blacklists": "Kara listeler", "rules": "Kurallar", - "customRules": "Özel kural", - "enabledRules": "Etkin kural", + "customRules": "Özel kurallar", + "enabledRules": "Etkin kurallar", "enabled": "Etkin", "disabled": "Devre dışı", "rule": "Kural", @@ -233,12 +233,12 @@ "noWhiteLists": "Beyaz listeler yok", "addWhitelist": "Beyaz liste ekle", "addBlacklist": "Kara liste ekle", - "urlNotValid": "URL geçerli değil", - "urlAbsolutePath": "URL veya kesin dosya yolu", + "urlNotValid": "URL Adresi geçerli değil", + "urlAbsolutePath": "URL adresi veya kesin dosya yolu", "addingList": "Liste ekleniyor...", "listAdded": "Liste başarıyla eklendi. Eklenen öğeler:", "listAlreadyAdded": "Liste zaten eklenmiş", - "listUrlInvalid": "Liste URL'si geçersiz", + "listUrlInvalid": "Liste URL adresi geçersiz", "listNotAdded": "Liste eklenemedi", "listDetails": "Liste detayları", "listType": "Liste türü", @@ -284,7 +284,7 @@ "noAllowedClients": "İzin verilen istemci yok", "allowedClientsDescription": "Eğer bu liste girişlere sahipse, AdGuard Home sadece bu istemcilerden gelen istekleri kabul edecek.", "blockedClientsDescription": "Eğer bu liste girişlere sahipse, AdGuard Home bu istemcilerden gelen istekleri reddedecektir. Bu alan, İzin Verilen İstemciler bölümünde girişler varsa dikkate alınmaz.", - "disallowedDomainsDescription": "AdGuard Home, bu alanlara uyan DNS sorgularını reddeder ve bu sorgular sorgu günlüğünde bile görünmez.", + "disallowedDomainsDescription": "AdGuard Home, bu alan adlarına uyan DNS sorgularını reddeder ve bu sorgular sorgu günlüğünde bile görünmez.", "addClientFieldDescription": "CIDR'ler, IP adresi veya ClientID", "clientIdentifier": "İstemci tanımlayıcısı", "allowClient": "İstemciye izin ver", @@ -305,11 +305,11 @@ "block": "Engelle", "unblock": "Engeli kaldır", "custom": "Özel", - "addImportant": "Ekle $important", + "addImportant": "Ekle ($important)", "howCreateRules": "Özel kurallar nasıl oluşturulur?", "examples": "Örnekler", - "example1": "ornek.org ve tüm alt alanlarına erişimi engeller.", - "example2": "ornek.org ve tüm alt alanlarına erişimi engellemeyi kaldırır.", + "example1": "example.org ve tüm alt alan adlarına erişimi engeller.", + "example2": "example.org ve tüm alt alan adlarına erişimi engellemeyi kaldırır.", "example3": "Yorum ekler.", "example4": "Belirtilen düzenli ifadeye uyan alan adlarına erişimi engeller.", "moreInformation": "Daha fazla bilgi", @@ -336,7 +336,7 @@ "updating": "Değerler güncelleniyor...", "blockedServicesUpdated": "Engellenen hizmetler başarıyla güncellendi", "blockedServicesNotUpdated": "Engellenen hizmetler güncellenemedi", - "insertDomain": "Durumunu kontrol etmek için bir alan adı ekleyin.", + "insertDomain": "Durumu kontrol etmek için bir alan adı ekleyin.", "dhcpSettings": "DHCP ayarları", "dhcpSettingsDescription": "DHCP sunucusunu yapılandır", "dhcpSettingsNotLoaded": "DHCP ayarları yüklenemedi", @@ -422,7 +422,7 @@ "deletingLogs": "Günlükler temizleniyor...", "logsCleared": "Günlükler başarıyla temizlendi", "logsNotCleared": "Günlükler temizlenemedi", - "runningHomeAssistant": "Ev Asistanı üzerinde çalışıyor", + "runningHomeAssistant": "Ev Asistanı üzerinde çalıştır", "serverError": "Sunucu hatası", "noItems": "Burada gösterilecek öğe yok", "dnsSettings": "DNS ayarları", @@ -445,19 +445,19 @@ "reverseDnsDefault": "Varsayılan olarak, AdGuard Home aşağıdaki ters DNS çözümleyicilerini kullanır", "addItem": "Öğe ekle", "noServerAddressesAdded": "Sunucu adresleri eklenmedi.", - "usePrivateReverseDnsResolvers": "Özel ters DNS çözümleyicilerini kullanma", + "usePrivateReverseDnsResolvers": "Özel ters DNS çözümleyicilerini kullan", "usePrivateReverseDnsResolversDescription": "Bu üst akış sunucularını kullanarak yerel olarak sunulan adresler için ters DNS sorguları gerçekleştirin. Devre dışı bırakılırsa, AdGuard Home, DHCP, /etc/hosts vb. kaynaklardan bilinen istemciler dışında tüm PTR isteklerine NXDOMAIN yanıtı verir.", - "enableReverseResolving": "İstemcilerin IP adreslerinin ters çözümlemesini etkinleştirin", + "enableReverseResolving": "İstemcilerin IP adreslerinin ters çözümlemesini etkinleştir", "enableReverseResolvingDescription": "İstemcilerin IP adreslerini karşılık gelen çözücülere PTR sorguları göndererek IP adreslerini tersine çözümleyerek (yerel istemciler için özel DNS sunucuları, genel IP adresine sahip istemciler için yukarı akış sunucuları) istemcilerin ana bilgisayar adlarını tersine çöz.", "dnsServerSettings": "AdGuard Home DNS sunucusu ayarları", "limitRequestsSecond": "Saniye başına hız limiti", "valueNotNumber": "Değer bir sayı değil", "enableEdns": "EDNS istemci alt ağını etkinleştir", - "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı Seçeneği (ECS) ekleyin ve istemciler tarafından gönderilen değerleri sorgu günlüğünde kaydet.", + "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı Seçeneği (ECS) ekleyin ve istemciler tarafından gönderilen değerleri sorgu günlüğüne kaydedin.", "enableDnssec": "DNSSEC'i Etkinleştir", - "enableDnssecDescription": "Giden DNS sorgularında DNSSEC bayrağını ayarla ve sonucu kontrol et (DNSSEC etkinleştirilmiş bir çözümleyici gereklidir).", + "enableDnssecDescription": "Giden DNS sorguları için DNSSEC özelliğini etkinleştir ve sonucu kontrol et (DNSSEC etkinleştirilmiş bir çözümleyici gerekli).", "disableResolvingIpv6": "IPv6 adreslerinin çözümlenmesini devre dışı bırak", - "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını devre dışı bırakın (AAAA yazın).", + "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını bırakın (AAAA yazın) ve HTTPS yanıtlarından IPv6 ipuçlarını kaldırın.", "blockingMode": "Engelleme modu", "defaultMode": "Varsayılan", "defaultDescription": "Reklam engelleme tarzı bir kural tarafından engellendiğinde sıfır IP adresi ile yanıt verin (A için 0.0.0.0; :: AAAA için) /etc/hosts tarzı bir kural tarafından engellendiğinde kuralda belirtilen IP adresi ile yanıt verin.", @@ -471,7 +471,7 @@ "cacheSize": "Önbellek boyutu", "inBytes": "Bayt olarak", "overrideMinimumTtl": "Minimum kullanım süresini geçersiz kıl", - "overrideMinimumTtlDescription": "DNS yanıtlarını önbelleğe alırken üst sunucudan alınan kullanım süresi değerini uzatın (saniye olarak).", + "overrideMinimumTtlDescription": "DNS yanıtlarını önbelleğe alırken üst sunucudan alınan minimum kullanım süresi değerini ayarlayın (saniye olarak).", "overrideMaximumTtl": "Maksimum kullanım süresini geçersiz kıl", "overrideMaximumTtlDescription": "DNS önbelleğindeki girişler için maksimum kullanım süresi değerini ayarlayın (saniye olarak).", "optimisticCaching": "İyimser önbelleğe alma", @@ -504,18 +504,18 @@ "enableEncryptionDescription": "Eğer şifreleme etkinleştirilmişse, AdGuard Home yönetici arayüzü HTTPS üzerinden çalışacaktır ve DNS sunucusu DNS üzerinden HTTPS ve TLS ile gelen isteklere cevap verecektir.", "serverConfiguration": "Sunucu yapılandırması", "domainName": "Alan adı", - "domainNameDescription": "Eğer ayarlanırsa, AdGuard Home İstemci Kimliklerini tespit eder, DDR sorgularına yanıt verir ve ek bağlantı doğrulamalarını gerçekleştirir. Ayarlanmazsa, bu özellikler devre dışı bırakılır. Sertifikadaki DNS adlarından biriyle eşleşmelidir.", + "domainNameDescription": "Eğer ayarlanırsa, AdGuard Home istemci kimliklerini tespit eder, DDR sorgularına yanıt verir ve ek bağlantı doğrulamalarını gerçekleştirir. Ayarlanmazsa, bu özellikler devre dışı bırakılır. Sertifikadaki DNS adlarından biriyle eşleşmelidir.", "redirectHttps": "Otomatik olarak HTTPS'e yönlendir", "httpsPort": "HTTPS bağlantı noktası", "tlsPort": "DNS-over-TLS bağlantı noktası", "dnsOverQuicPort": "DNS-over-QUIC bağlantı noktası", "certificates": "Sertifikalar", - "certificatesDescription": "Şifreleme kullanmak için, alanınız için geçerli bir SSL sertifikası zinciri sağlamanız gereklidir. letsencrypt.org'dan ücretsiz bir sertifika alabilir veya güvenilir sertifika yetkililerinden satın alabilirsiniz.", - "certificateFilePath": "Bir sertifika dosyası yolu ayarlayın", + "certificatesDescription": "Şifreleme kullanmak için, alan adınız için geçerli bir SSL sertifikası zinciri sağlamanız gereklidir. letsencrypt.org'dan ücretsiz bir sertifika alabilir veya güvenilir sertifika yetkililerinden satın alabilirsiniz.", + "certificateFilePath": "Sertifika dosyası yolu ayarla", "pasteCertificateContent": "Sertifika içeriğini yapıştır", "certificatePath": "Sertifika dosya yolu", "certificateContent": "Sertifika içeriği", - "privateKey": "Private key", + "privateKey": "Özel anahtar", "privateKeyFile": "Özel bir anahtar dosyası belirle", "pastePrivateKey": "Özel anahtar içeriğini yapıştır", "usePreviousKey": "Önceden kaydedilmiş anahtarı kullan", @@ -550,7 +550,7 @@ "pink": "Pembe", "deepOrange": "Koyu turuncu", "indigo": "Çivit mavisi", - "useThemeColorStatus": "Durum için tema rengini kullanın", + "useThemeColorStatus": "Durum için tema rengini kullan", "useThemeColorStatusDescription": "Yeşil ve kırmızı durum renklerini tema rengi ve gri ile değiştirir", "invalidCertificateChain": "Geçersiz sertifika zinciri", "validCertificateChain": "Geçerli sertifika zinciri", @@ -602,9 +602,9 @@ "autoupdateUnavailable": "Otomatik güncelleme kullanılamıyor", "autoupdateUnavailableDescription": "Otomatik güncelleme servisi bu sunucu için kullanılamıyor. Bunun nedeni sunucunun bir Docker konteynerinde çalışıyor olması olabilir. Sunucunuzu manuel olarak güncellemeniz gerekecektir.", "minute": "{time} dakika", - "minutes": "{time} dakikalar", + "minutes": "{time} dakika", "hour": "{time} saat", - "hours": "{time} saatler", + "hours": "{time} saat", "remainingTime": "Kalan süre", "safeSearchSettings": "Güvenli arama ayarları", "loadingSafeSearchSettings": "Güvenli arama ayarları yükleniyor...", @@ -618,14 +618,14 @@ "copiedClipboard": "Panoya kopyalandı", "seeDetails": "Detayları gör", "listNotAvailable": "Liste mevcut değil", - "copyListUrl": "Liste URL'sini kopyala", - "listUrlCopied": "Panoya kopyalanan URL'yi listeleyin", + "copyListUrl": "Liste URL adresini kopyala", + "listUrlCopied": "Panoya kopyalanan URL adresini listeleyin", "unsupportedVersion": "Desteklenmeyen sürüm", "unsupprtedVersionMessage": "Sunucu sürümünüz {version} için destek garantisi verilmiyor. Bu uygulamanın bu sunucu sürümüyle çalışmasında bazı sorunlar olabilir. AdGuard Home Yöneticisi, AdGuard Home sunucunun kararlı sürümleriyle çalışacak şekilde tasarlanmıştır. Alfa ve beta sürümleriyle çalışabilir, ancak uyumluluk garanti edilmez ve uygulama bu sürümlerle çalışırken bazı sorunlar yaşayabilir.", "iUnderstand": "Anladım", "appUpdates": "Uygulama güncellemeleri", "usingLatestVersion": "En son sürümü kullanıyorsunuz", - "ipLogs": "IP günlüklerde", + "ipLogs": "Günlüklerdeki IP", "ipLogsDescription": "Günlüklerde istemci adı yerine her zaman IP adresini göster", "application": "Uygulama", "combinedChart": "Birleştirilmiş grafik", @@ -653,14 +653,19 @@ "december": "Aralık", "malwarePhising": "Zararlı yazılım/oltalama", "queries": "Sorgular", - "adultSites": "Yetişkin siteleri", + "adultSites": "Yetişkin içerikler", "quickFilters": "Hızlı filtreler", "searchDomainInternet": "İnternette alan adı ara", "hideServerAddress": "Sunucu adresini gizle", "hideServerAddressDescription": "Ana ekranda sunucu adresini gizler", - "topItemsOrder": "En iyi ürün siparişi", - "topItemsOrderDescription": "Ana ekran üst öğe listelerini sırala", + "topItemsOrder": "Öne çıkan öğe sıralaması", + "topItemsOrderDescription": "Ana ekrandaki öne çıkan öğe listelerini sırala", "topItemsReorderInfo": "Yeniden sıralamak için bir öğeyi basılı tutun ve kaydırın.", - "discardChanges": "Değişiklikleri iptal edin", - "discardChangesDescription": "Değişiklikleri iptal etmek istediğinizden emin misiniz?" + "discardChanges": "Değişiklikleri iptal et", + "discardChangesDescription": "Değişiklikleri iptal etmek istediğinizden emin misiniz?", + "others": "Diğerleri", + "showChart": "Göster", + "hideChart": "Gizle", + "showTopItemsChart": "Öne çıkan öğeler grafiği", + "showTopItemsChartDescription": "Varsayılan olarak öne çıkan öğeler bölümünde halka grafiğini gösterir. Sadece mobil görünümü etkiler." } \ No newline at end of file From 5a13d5259805cefe6ba2db144d1da4d553c1c1f7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 23 Oct 2023 18:12:21 +0200 Subject: [PATCH 336/676] Small fix --- lib/screens/clients/client/settings_tile.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/screens/clients/client/settings_tile.dart b/lib/screens/clients/client/settings_tile.dart index 81f0c5c..c2d6ede 100644 --- a/lib/screens/clients/client/settings_tile.dart +++ b/lib/screens/clients/client/settings_tile.dart @@ -30,11 +30,14 @@ class SettingsTile extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - label, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface, + Expanded( + child: Text( + label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface, + ), ), ), useGlobalSettingsFiltering == false From 639f583046e3edf4028cc4d73dc6e0b7daf130e1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 24 Oct 2023 20:59:54 +0200 Subject: [PATCH 337/676] Desktop UI improvements --- lib/screens/home/home.dart | 59 --------------------------------- lib/screens/home/top_items.dart | 49 +++++++++++++++------------ 2 files changed, 27 insertions(+), 81 deletions(-) diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 59fb0bf..fcac0cc 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -176,65 +176,6 @@ class _HomeState extends State { ), TopItemsLists(order: appConfigProvider.homeTopItemsOrder), - - // if (width > 700) Column( - // children: [ - // Wrap( - // alignment: WrapAlignment.center, - // children: appConfigProvider.homeTopItemsOrder.map((item) { - // switch (item) { - // case HomeTopItems.queriedDomains: - // return Padding( - // padding: const EdgeInsets.only(bottom: 16), - // child: ConstrainedBox( - // constraints: const BoxConstraints( - // maxWidth: 500 - // ), - // child: TopItems( - // label: AppLocalizations.of(context)!.topQueriedDomains, - // data: statusProvider.serverStatus!.stats.topQueriedDomains, - // type: 'topQueriedDomains', - // ), - // ), - // ); - - // case HomeTopItems.blockedDomains: - // return Padding( - // padding: const EdgeInsets.only(bottom: 16), - // child: ConstrainedBox( - // constraints: const BoxConstraints( - // maxWidth: 500 - // ), - // child: TopItems( - // label: AppLocalizations.of(context)!.topBlockedDomains, - // data: statusProvider.serverStatus!.stats.topBlockedDomains, - // type: 'topBlockedDomains', - // ), - // ), - // ); - - // case HomeTopItems.recurrentClients: - // return Padding( - // padding: const EdgeInsets.only(bottom: 16), - // child: ConstrainedBox( - // constraints: const BoxConstraints( - // maxWidth: 500 - // ), - // child: TopItems( - // label: AppLocalizations.of(context)!.topClients, - // data: statusProvider.serverStatus!.stats.topClients, - // type: 'topClients', - // ), - // ), - // ); - - // default: - // return const SizedBox(); - // } - // }).toList(), - // ), - // ], - // ) ]; } diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 24dd6db..06ef00e 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -157,41 +157,46 @@ class _TopItemsState extends State { const SizedBox(height: 24), if (widget.data.isEmpty) noItems, - if (widget.data.isNotEmpty && width > 700) SizedBox( - height: 240, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - flex: 1, + if (widget.data.isNotEmpty && width > 700) Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: ConstrainedBox( + constraints: const BoxConstraints( + maxHeight: 250 + ), child: Padding( padding: const EdgeInsets.all(16), child: chart, - ) - ), - Expanded( - flex: 2, - child: Column( - children: [ - ...itemsList, - OthersRowItem(items: widget.data) - ] ), ) - ], - ), + ), + Expanded( + flex: 2, + child: Column( + children: [ + ...itemsList, + OthersRowItem(items: widget.data) + ] + ), + ) + ], ), if (widget.data.isNotEmpty && width <= 700) ...[ if (_showChart) ...[ - chart, + SizedBox( + height: 300, + child: chart + ), const SizedBox(height: 16), ], ...itemsList, - if (_showChart) OthersRowItem(items: widget.data) + if (_showChart) OthersRowItem(items: widget.data), + const SizedBox(height: 16), ], - if (widget.data.length > 5) ...[ - const SizedBox(height: 20), + if (widget.data.length > 5) ...[ Padding( padding: const EdgeInsets.only(right: 20), child: Row( From 6f3ba647f42b2d8782c38beb9a01cd7e10e01472 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 24 Oct 2023 21:19:03 +0200 Subject: [PATCH 338/676] Added scrollbar desktop management modal --- lib/screens/home/management_modal.dart | 88 +++++++++++++++----------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index d23ddd4..9b94b58 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -31,6 +31,8 @@ class _ManagementModalState extends State with SingleTickerProv late Animation animation; final ExpandableController expandableController = ExpandableController(); + final _chipsScrollController = ScrollController(); + @override void initState() { expandableController.addListener(() async { @@ -155,46 +157,58 @@ class _ManagementModalState extends State with SingleTickerProv Widget bottomRow() { return Container( - height: 40, + height: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 50 : 40, margin: const EdgeInsets.only(top: 8), - child: ListView( - scrollDirection: Axis.horizontal, - children: [ - ActionChip( - label: Text(AppLocalizations.of(context)!.seconds(30)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(29000) - : null, + child: Scrollbar( + controller: _chipsScrollController, + thumbVisibility: Platform.isMacOS || Platform.isLinux || Platform.isWindows, + interactive: Platform.isMacOS || Platform.isLinux || Platform.isWindows, + thickness: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 8 : 0, + child: Padding( + padding: EdgeInsets.only( + bottom: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 16 : 0 ), - const SizedBox(width: 8), - ActionChip( - label: Text(AppLocalizations.of(context)!.minute(1)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(59000) - : null, + child: ListView( + controller: _chipsScrollController, + scrollDirection: Axis.horizontal, + children: [ + ActionChip( + label: Text(AppLocalizations.of(context)!.seconds(30)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => disableWithCountdown(29000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.minute(1)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => disableWithCountdown(59000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.minutes(10)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => disableWithCountdown(599000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.hour(1)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => disableWithCountdown(3599000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.hours(24)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => disableWithCountdown(86399000) + : null, + ), + ], ), - const SizedBox(width: 8), - ActionChip( - label: Text(AppLocalizations.of(context)!.minutes(10)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(599000) - : null, - ), - const SizedBox(width: 8), - ActionChip( - label: Text(AppLocalizations.of(context)!.hour(1)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(3599000) - : null, - ), - const SizedBox(width: 8), - ActionChip( - label: Text(AppLocalizations.of(context)!.hours(24)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(86399000) - : null, - ), - ], + ), ), ); } From 229d329936e6861fa66ea890dc4b766db3b97bd5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 24 Oct 2023 21:28:57 +0200 Subject: [PATCH 339/676] Fixed settings sliver list --- lib/screens/settings/settings.dart | 311 +++++++++++++++-------------- 1 file changed, 162 insertions(+), 149 deletions(-) diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 709a245..2f9a24d 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -129,158 +129,171 @@ class SettingsWidget extends StatelessWidget { ) ) ], - body: ListView( - children: [ - if ( - serversProvider.selectedServer != null && - statusProvider.serverStatus != null && - serversProvider.apiClient != null - ) ...[ - SectionLabel(label: AppLocalizations.of(context)!.serverSettings), - if (serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true) settingsTile( - icon: Icons.search_rounded, - title: AppLocalizations.of(context)!.safeSearch, - subtitle: AppLocalizations.of(context)!.safeSearchSettings, - thisItem: 0, - screenToNavigate: const SafeSearchSettingsScreen(), - ), - settingsTile( - icon: Icons.lock_rounded, - title: AppLocalizations.of(context)!.accessSettings, - subtitle: AppLocalizations.of(context)!.accessSettingsDescription, - thisItem: 1, - screenToNavigate: const AccessSettings(), - ), - settingsTile( - icon: Icons.install_desktop_rounded, - title: AppLocalizations.of(context)!.dhcpSettings, - subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, - thisItem: 2, - screenToNavigate: const DhcpScreen(), - ), - settingsTile( - icon: Icons.dns_rounded, - title: AppLocalizations.of(context)!.dnsSettings, - subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, - thisItem: 3, - screenToNavigate: const DnsSettings(), - ), - settingsTile( - icon: Icons.security_rounded, - title: AppLocalizations.of(context)!.encryptionSettings, - subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, - thisItem: 4, - screenToNavigate: const EncryptionSettings(), - ), - settingsTile( - icon: Icons.route_rounded, - title: AppLocalizations.of(context)!.dnsRewrites, - subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, - thisItem: 5, - screenToNavigate: const DnsRewritesScreen(), - ), - if (serversProvider.updateAvailable.data != null) settingsTile( - icon: Icons.system_update_rounded, - title: AppLocalizations.of(context)!.updates, - subtitle: AppLocalizations.of(context)!.updatesDescription, - trailing: serversProvider.updateAvailable.data != null && - serversProvider.updateAvailable.data!.canAutoupdate == true - ? Container( - width: 10, - height: 10, - margin: const EdgeInsets.only(right: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.red - ), - ) - : null, - thisItem: 6, - screenToNavigate: const UpdateScreen(), - ), - settingsTile( - icon: Icons.info_rounded, - title: AppLocalizations.of(context)!.serverInformation, - subtitle: AppLocalizations.of(context)!.serverInformationDescription, - thisItem: 7, - screenToNavigate: const ServerInformation(), - ), - ], - SectionLabel(label: AppLocalizations.of(context)!.appSettings), - settingsTile( - icon: Icons.palette_rounded, - title: AppLocalizations.of(context)!.customization, - subtitle: AppLocalizations.of(context)!.customizationDescription, - thisItem: 8, - screenToNavigate: const Customization(), - ), - settingsTile( - icon: Icons.storage_rounded, - title: AppLocalizations.of(context)!.servers, - subtitle: serversProvider.selectedServer != null - ? statusProvider.serverStatus != null - ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" - : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" - : AppLocalizations.of(context)!.noServerSelected, - thisItem: 9, - screenToNavigate: const Servers(), - ), - settingsTile( - icon: Icons.settings, - title: AppLocalizations.of(context)!.generalSettings, - subtitle: AppLocalizations.of(context)!.generalSettingsDescription, - thisItem: 10, - screenToNavigate: const GeneralSettings(), - ), - settingsTile( - icon: Icons.build_outlined, - title: AppLocalizations.of(context)!.advancedSettings, - subtitle: AppLocalizations.of(context)!.advancedSetupDescription, - thisItem: 11, - screenToNavigate: const AdvancedSettings(), - ), - SectionLabel(label: AppLocalizations.of(context)!.aboutApp), - CustomListTile( - title: AppLocalizations.of(context)!.appVersion, - subtitle: appConfigProvider.getAppInfo!.version, - ), - CustomListTile( - title: AppLocalizations.of(context)!.createdBy, - subtitle: Strings.createdBy, - ), - Padding( - padding: const EdgeInsets.all(15), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - if (Platform.isAndroid) IconButton( - onPressed: () => openUrl(Urls.playStore), - icon: SvgPicture.asset( - 'assets/resources/google-play.svg', - color: Theme.of(context).colorScheme.onSurfaceVariant, - width: 30, - height: 30, + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + if ( + serversProvider.selectedServer != null && + statusProvider.serverStatus != null && + serversProvider.apiClient != null + ) ...[ + SectionLabel(label: AppLocalizations.of(context)!.serverSettings), + if (serverVersionIsAhead( + currentVersion: statusProvider.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true) settingsTile( + icon: Icons.search_rounded, + title: AppLocalizations.of(context)!.safeSearch, + subtitle: AppLocalizations.of(context)!.safeSearchSettings, + thisItem: 0, + screenToNavigate: const SafeSearchSettingsScreen(), + ), + settingsTile( + icon: Icons.lock_rounded, + title: AppLocalizations.of(context)!.accessSettings, + subtitle: AppLocalizations.of(context)!.accessSettingsDescription, + thisItem: 1, + screenToNavigate: const AccessSettings(), + ), + settingsTile( + icon: Icons.install_desktop_rounded, + title: AppLocalizations.of(context)!.dhcpSettings, + subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, + thisItem: 2, + screenToNavigate: const DhcpScreen(), + ), + settingsTile( + icon: Icons.dns_rounded, + title: AppLocalizations.of(context)!.dnsSettings, + subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, + thisItem: 3, + screenToNavigate: const DnsSettings(), + ), + settingsTile( + icon: Icons.security_rounded, + title: AppLocalizations.of(context)!.encryptionSettings, + subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, + thisItem: 4, + screenToNavigate: const EncryptionSettings(), + ), + settingsTile( + icon: Icons.route_rounded, + title: AppLocalizations.of(context)!.dnsRewrites, + subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, + thisItem: 5, + screenToNavigate: const DnsRewritesScreen(), + ), + if (serversProvider.updateAvailable.data != null) settingsTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.updates, + subtitle: AppLocalizations.of(context)!.updatesDescription, + trailing: serversProvider.updateAvailable.data != null && + serversProvider.updateAvailable.data!.canAutoupdate == true + ? Container( + width: 10, + height: 10, + margin: const EdgeInsets.only(right: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.red + ), + ) + : null, + thisItem: 6, + screenToNavigate: const UpdateScreen(), + ), + settingsTile( + icon: Icons.info_rounded, + title: AppLocalizations.of(context)!.serverInformation, + subtitle: AppLocalizations.of(context)!.serverInformationDescription, + thisItem: 7, + screenToNavigate: const ServerInformation(), + ), + ], + SectionLabel(label: AppLocalizations.of(context)!.appSettings), + settingsTile( + icon: Icons.palette_rounded, + title: AppLocalizations.of(context)!.customization, + subtitle: AppLocalizations.of(context)!.customizationDescription, + thisItem: 8, + screenToNavigate: const Customization(), ), - tooltip: AppLocalizations.of(context)!.visitGooglePlay, - ), - IconButton( - onPressed: () => openUrl(Urls.gitHub), - icon: SvgPicture.asset( - 'assets/resources/github.svg', - color: Theme.of(context).colorScheme.onSurfaceVariant, - width: 30, - height: 30, + settingsTile( + icon: Icons.storage_rounded, + title: AppLocalizations.of(context)!.servers, + subtitle: serversProvider.selectedServer != null + ? statusProvider.serverStatus != null + ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" + : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" + : AppLocalizations.of(context)!.noServerSelected, + thisItem: 9, + screenToNavigate: const Servers(), ), - tooltip: AppLocalizations.of(context)!.gitHub, - ), - ], - ), + settingsTile( + icon: Icons.settings, + title: AppLocalizations.of(context)!.generalSettings, + subtitle: AppLocalizations.of(context)!.generalSettingsDescription, + thisItem: 10, + screenToNavigate: const GeneralSettings(), + ), + settingsTile( + icon: Icons.build_outlined, + title: AppLocalizations.of(context)!.advancedSettings, + subtitle: AppLocalizations.of(context)!.advancedSetupDescription, + thisItem: 11, + screenToNavigate: const AdvancedSettings(), + ), + SectionLabel(label: AppLocalizations.of(context)!.aboutApp), + CustomListTile( + title: AppLocalizations.of(context)!.appVersion, + subtitle: appConfigProvider.getAppInfo!.version, + ), + CustomListTile( + title: AppLocalizations.of(context)!.createdBy, + subtitle: Strings.createdBy, + ), + Padding( + padding: const EdgeInsets.all(15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if (Platform.isAndroid) IconButton( + onPressed: () => openUrl(Urls.playStore), + icon: SvgPicture.asset( + 'assets/resources/google-play.svg', + color: Theme.of(context).colorScheme.onSurfaceVariant, + width: 30, + height: 30, + ), + tooltip: AppLocalizations.of(context)!.visitGooglePlay, + ), + IconButton( + onPressed: () => openUrl(Urls.gitHub), + icon: SvgPicture.asset( + 'assets/resources/github.svg', + color: Theme.of(context).colorScheme.onSurfaceVariant, + width: 30, + height: 30, + ), + tooltip: AppLocalizations.of(context)!.gitHub, + ), + ], + ), + ) + ], + ) + ], ) - ], + ), ), ) ); From 211a0b02980823f030c26d3918200c1fcae178fa Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 24 Oct 2023 21:43:24 +0200 Subject: [PATCH 340/676] Fixed typo --- lib/l10n/app_en.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 451e4e1..ee0533d 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -59,7 +59,7 @@ "errorLoadServerStatus": "Server status could not be loaded", "topQueriedDomains": "Queried domains", "viewMore": "View more", - "topClients": "Cients", + "topClients": "Clients", "topBlockedDomains": "Blocked domains", "appSettings": "App settings", "theme": "Theme", From 80b3c004d62199f8c9825f4735bc249105cc4b1b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 27 Oct 2023 14:39:07 +0200 Subject: [PATCH 341/676] Fixed GitHub update notifier --- lib/constants/urls.dart | 1 + lib/functions/check_app_updates.dart | 24 +++++---- lib/functions/compare_versions.dart | 12 ++--- lib/services/http_requests.dart | 73 +++++++++++++++++++++++++++- 4 files changed, 92 insertions(+), 18 deletions(-) diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart index 440c8d7..b7eb069 100644 --- a/lib/constants/urls.dart +++ b/lib/constants/urls.dart @@ -3,6 +3,7 @@ class Urls { static const String gitHub = "https://github.com/JGeek00/adguard-home-manager"; static const String customRuleDocs = "https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters"; static const String getReleasesGitHub = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases"; + static const String getLatestReleaseGitHub = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases/latest"; static const String adGuardHomeReleasesTags = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/tags"; static const String googleSearchUrl = "https://www.google.com/search"; static const String connectionInstructions = "https://github.com/JGeek00/adguard-home-manager/wiki/Create-a-connection"; diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart index eb44177..306b2ea 100644 --- a/lib/functions/check_app_updates.dart +++ b/lib/functions/check_app_updates.dart @@ -12,21 +12,27 @@ Future checkAppUpdates({ required Source installationSource, required bool isBeta }) async { - final result = await checkAppUpdatesGitHub(); + var result = isBeta + ? await getReleasesGitHub() + : await getLatestReleaseGitHub(); if (result['result'] == 'success') { + late GitHubRelease gitHubRelease; + if (isBeta) { + gitHubRelease = (result['body'] as List).firstWhere((r) => r.prerelease == true); + } + else { + gitHubRelease = result['body'] as GitHubRelease; + } + final update = gitHubUpdateExists( currentBuildNumber: currentBuildNumber, - gitHubReleases: result['body'], + gitHubRelease: gitHubRelease, isBeta: isBeta ); if (update == true) { - final release = isBeta == true - ? result['body'].firstWhere((release) => release.prerelease == true) - : result['body'].firstWhere((release) => release.prerelease == false); - - setUpdateAvailable(release); + setUpdateAvailable(gitHubRelease); if (Platform.isAndroid) { if ( @@ -34,7 +40,7 @@ Future checkAppUpdates({ installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || installationSource == Source.UNKNOWN ) { - return release; + return gitHubRelease; } else { return null; @@ -44,7 +50,7 @@ Future checkAppUpdates({ return null; } else { - return release; + return gitHubRelease; } } else { diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index 33ae8fe..b2f37e1 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -151,15 +151,11 @@ bool serverVersionIsAhead({ bool gitHubUpdateExists({ required String currentBuildNumber, - required List gitHubReleases, + required GitHubRelease gitHubRelease, required bool isBeta }) { - final release = isBeta == true - ? gitHubReleases.firstWhere((release) => release.prerelease == true) - : gitHubReleases.firstWhere((release) => release.prerelease == false); - final versionNumberRegex = RegExp(r'\(\d+\)'); - final releaseNumberExtractedMatches = versionNumberRegex.allMatches(release.tagName); + final releaseNumberExtractedMatches = versionNumberRegex.allMatches(gitHubRelease.tagName); if (releaseNumberExtractedMatches.isNotEmpty) { final releaseNumberExtracted = releaseNumberExtractedMatches.first.group(0); @@ -181,12 +177,12 @@ bool gitHubUpdateExists({ } } else { - Sentry.captureMessage("Invalid release number. Tagname: ${release.tagName}"); + Sentry.captureMessage("Invalid release number. Tagname: ${gitHubRelease.tagName}"); return false; } } else { - Sentry.captureMessage("No matches. ${release.tagName}"); + Sentry.captureMessage("No matches. ${gitHubRelease.tagName}"); return false; } } \ No newline at end of file diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index e1f4552..7fe18e0 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -2322,7 +2322,7 @@ class ApiClient { } } -Future checkAppUpdatesGitHub() async { +Future getReleasesGitHub() async { try { HttpClient httpClient = HttpClient(); HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getReleasesGitHub)); @@ -2391,4 +2391,75 @@ Future checkAppUpdatesGitHub() async { ) }; } +} + +Future getLatestReleaseGitHub() async { + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getLatestReleaseGitHub)); + HttpClientResponse response = await request.close(); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + if (response.statusCode == 200) { + return { + 'result': 'success', + 'hasResponse': true, + 'error': false, + 'statusCode': response.statusCode, + 'body': GitHubRelease.fromJson(jsonDecode(reply)) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: response.statusCode.toString(), + resBody: reply, + ) + }; + } + } on SocketException { + return { + 'result': 'no_connection', + 'message': 'SocketException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'SocketException' + ) + }; + } on TimeoutException { + return { + 'result': 'no_connection', + 'message': 'TimeoutException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'TimeoutException' + ) + }; + } on HandshakeException { + return { + 'result': 'ssl_error', + 'message': 'HandshakeException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'HandshakeException' + ) + }; + } catch (e) { + return { + 'result': 'error', + 'message': e.toString(), + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: e.toString() + ) + }; + } } \ No newline at end of file From 2ad739ed4fe38103b9eec0ec28630f0e2f27d7b3 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 27 Oct 2023 14:39:53 +0200 Subject: [PATCH 342/676] Updated turkish translation --- lib/l10n/app_tr.arb | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 08a7842..ef6edd7 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -139,7 +139,7 @@ "clas": "Sınıf", "response": "Yanıt", "dnsServer": "DNS sunucusu", - "elapsedTime": "Zaman aşımı", + "elapsedTime": "İşlem süresi", "responseCode": "Yanıt kodu", "client": "İstemci", "deviceIp": "IP adresi", @@ -171,7 +171,7 @@ "dnsQueries": "DNS sorguları", "average": "Ortalama", "blockedFilters": "Engellenen (Alan adları)", - "malwarePhisingBlocked": "Engellenen (Zararlı içerik)", + "malwarePhishingBlocked": "Engellenen (Zararlı içerik)", "blockedAdultWebsites": "Engellenen (Yetişkin içerik)", "generalSettings": "Genel ayarlar", "generalSettingsDescription": "Çeşitli farklı ayarlar", @@ -267,9 +267,9 @@ "seeDnsAddresses": "DNS adreslerine bak", "dnsPort": "DNS bağlantı noktası", "httpPort": "HTTP bağlantı noktası", - "protectionEnabled": "Koruma etkin", - "dhcpAvailable": "DHCP mevcut", - "serverRunning": "Sunucu çalışıyor", + "protectionEnabled": "Koruma etkin mi?", + "dhcpAvailable": "DHCP mevcut mu?", + "serverRunning": "Sunucu çalışıyor mu?", "serverVersion": "Sunucu sürümü", "serverLanguage": "Sunucu dili", "yes": "Evet", @@ -281,9 +281,9 @@ "accessSettingsDescription": "Sunucu için erişim kurallarını yapılandır", "loadingClients": "İstemciler yükleniyor...", "clientsNotLoaded": "İstemciler yüklenemedi.", - "noAllowedClients": "İzin verilen istemci yok", - "allowedClientsDescription": "Eğer bu liste girişlere sahipse, AdGuard Home sadece bu istemcilerden gelen istekleri kabul edecek.", - "blockedClientsDescription": "Eğer bu liste girişlere sahipse, AdGuard Home bu istemcilerden gelen istekleri reddedecektir. Bu alan, İzin Verilen İstemciler bölümünde girişler varsa dikkate alınmaz.", + "noAllowedClients": "İzin verilmiş istemci yok", + "allowedClientsDescription": "Eğer bu liste girdiler içeriyorsa, AdGuard Home yalnızca bu istemcilerden gelen talepleri kabul edecektir.", + "blockedClientsDescription": "Bu liste girdiler içeriyorsa, AdGuard Home bu istemcilerden gelen talepleri reddedecektir. Bu alan, İzin Verilen İstemciler'de girdi varsa görmezden gelinir.", "disallowedDomainsDescription": "AdGuard Home, bu alan adlarına uyan DNS sorgularını reddeder ve bu sorgular sorgu günlüğünde bile görünmez.", "addClientFieldDescription": "CIDR'ler, IP adresi veya ClientID", "clientIdentifier": "İstemci tanımlayıcısı", @@ -396,7 +396,7 @@ "dnsRewritesDescription": "Özel DNS kurallarını yapılandır", "loadingRewriteRules": "Yeniden yazma kuralları yükleniyor...", "rewriteRulesNotLoaded": "DNS yeniden yazma kuralları yüklenemedi.", - "noRewriteRules": "DNS yeniden yazma kuralları yok", + "noRewriteRules": "DNS yeniden yazım kuralları yok", "answer": "Cevap", "deleteDnsRewrite": "DNS yeniden yazmayı sil", "deleteDnsRewriteMessage": "Bu DNS yeniden yazmasını silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.", @@ -511,15 +511,15 @@ "dnsOverQuicPort": "DNS-over-QUIC bağlantı noktası", "certificates": "Sertifikalar", "certificatesDescription": "Şifreleme kullanmak için, alan adınız için geçerli bir SSL sertifikası zinciri sağlamanız gereklidir. letsencrypt.org'dan ücretsiz bir sertifika alabilir veya güvenilir sertifika yetkililerinden satın alabilirsiniz.", - "certificateFilePath": "Sertifika dosyası yolu ayarla", + "certificateFilePath": "Sertifika dosyası yolunu ayarla", "pasteCertificateContent": "Sertifika içeriğini yapıştır", "certificatePath": "Sertifika dosya yolu", "certificateContent": "Sertifika içeriği", "privateKey": "Özel anahtar", - "privateKeyFile": "Özel bir anahtar dosyası belirle", + "privateKeyFile": "Özel anahtar dosyası belirle", "pastePrivateKey": "Özel anahtar içeriğini yapıştır", "usePreviousKey": "Önceden kaydedilmiş anahtarı kullan", - "privateKeyPath": "Özel anahtar yolu", + "privateKeyPath": "Özel anahtar dosya yolu", "invalidCertificate": "Geçersiz sertifika", "invalidPrivateKey": "Geçersiz özel anahtar", "validatingData": "Veri doğrulama", @@ -561,7 +561,7 @@ "expirationDate": "Son kullanma tarihi", "keysNotMatch": "Geçersiz bir sertifika veya anahtar: tls: özel anahtar genel anahtarla eşleşmiyor.", "timeLogs": "Günlüklerdeki zaman", - "timeLogsDescription": "Günlükler listesinde işlem süresini göster", + "timeLogsDescription": "Günlükler listesinde zaman yerine işlem süresini göster", "hostNames": "Ana bilgisayar adları", "keyType": "Anahtar türü", "updateAvailable": "Güncelleme mevcut", @@ -651,14 +651,14 @@ "october": "Ekim", "november": "Kasım", "december": "Aralık", - "malwarePhising": "Zararlı yazılım/oltalama", + "malwarePhishing": "Zararlı yazılım/oltalama", "queries": "Sorgular", "adultSites": "Yetişkin içerikler", "quickFilters": "Hızlı filtreler", "searchDomainInternet": "İnternette alan adı ara", "hideServerAddress": "Sunucu adresini gizle", "hideServerAddressDescription": "Ana ekranda sunucu adresini gizler", - "topItemsOrder": "Öne çıkan öğe sıralaması", + "topItemsOrder": "Öne çıkan öğeler sıralaması", "topItemsOrderDescription": "Ana ekrandaki öne çıkan öğe listelerini sırala", "topItemsReorderInfo": "Yeniden sıralamak için bir öğeyi basılı tutun ve kaydırın.", "discardChanges": "Değişiklikleri iptal et", @@ -668,4 +668,4 @@ "hideChart": "Gizle", "showTopItemsChart": "Öne çıkan öğeler grafiği", "showTopItemsChartDescription": "Varsayılan olarak öne çıkan öğeler bölümünde halka grafiğini gösterir. Sadece mobil görünümü etkiler." -} \ No newline at end of file +} From 621171c5b1940bc8e05b58370d59799f078eb1c9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 28 Oct 2023 22:38:49 +0200 Subject: [PATCH 343/676] Implemented go router --- lib/base.dart | 2 +- lib/config/app_screens.dart | 7 - lib/config/sizes.dart | 1 + lib/constants/routes_names.dart | 19 ++ lib/functions/desktop_mode.dart | 5 + lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/main.dart | 7 +- lib/models/app_screen.dart | 2 - lib/routes/router.dart | 20 ++ lib/routes/router_globals.dart | 10 + lib/routes/routes.dart | 113 ++++++++ lib/screens/clients/added_list.dart | 3 - .../clients/client/client_placeholder.dart | 12 + .../clients/client/logs_list_client.dart | 44 ++- lib/screens/clients/clients.dart | 263 ++++++++---------- lib/screens/clients/clients_desktop_view.dart | 19 +- lib/screens/clients/clients_list.dart | 3 - lib/screens/home/appbar.dart | 4 + lib/widgets/bottom_nav_bar.dart | 30 +- lib/widgets/layout.dart | 250 +++++++++++++++++ pubspec.lock | 24 ++ pubspec.yaml | 2 + 23 files changed, 614 insertions(+), 234 deletions(-) create mode 100644 lib/config/sizes.dart create mode 100644 lib/constants/routes_names.dart create mode 100644 lib/functions/desktop_mode.dart create mode 100644 lib/routes/router.dart create mode 100644 lib/routes/router_globals.dart create mode 100644 lib/routes/routes.dart create mode 100644 lib/screens/clients/client/client_placeholder.dart create mode 100644 lib/widgets/layout.dart diff --git a/lib/base.dart b/lib/base.dart index b2b593b..d57dd72 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -101,7 +101,7 @@ class _BaseState extends State with WidgetsBindingObserver { child: child, ) ), - child: screens[appConfigProvider.selectedScreen].body, + child: SizedBox() ), ), ], diff --git a/lib/config/app_screens.dart b/lib/config/app_screens.dart index 1835dc4..91d33f0 100644 --- a/lib/config/app_screens.dart +++ b/lib/config/app_screens.dart @@ -13,12 +13,10 @@ List screensSelectServer = [ const AppScreen( name: "connect", icon: Icons.link_rounded, - body: Connect(), ), const AppScreen( name: "settings", icon: Icons.settings_rounded, - body: Settings() ) ]; @@ -26,26 +24,21 @@ List screensServerConnected = [ const AppScreen( name: "home", icon: Icons.home_rounded, - body: Home(), ), const AppScreen( name: "clients", icon: Icons.devices, - body: Clients() ), const AppScreen( name: "logs", icon: Icons.list_alt_rounded, - body: Logs(), ), const AppScreen( name: "filters", icon: Icons.shield_rounded, - body: Filters(), ), const AppScreen( name: "settings", icon: Icons.settings_rounded, - body: Settings() ) ]; \ No newline at end of file diff --git a/lib/config/sizes.dart b/lib/config/sizes.dart new file mode 100644 index 0000000..0fc2640 --- /dev/null +++ b/lib/config/sizes.dart @@ -0,0 +1 @@ +const double desktopBreakpoint = 1000; \ No newline at end of file diff --git a/lib/constants/routes_names.dart b/lib/constants/routes_names.dart new file mode 100644 index 0000000..dae8723 --- /dev/null +++ b/lib/constants/routes_names.dart @@ -0,0 +1,19 @@ +class RoutesNames { + static const String connect = "/connect"; + + static const String home = "/home"; + static const String queriedDomains = "/home/queried-domains"; + static const String blockedDomains = "/home/blocked-domains"; + static const String recurrentClients = "/home/recurrent-clients"; + + static const String clients = "/clients"; + static const String clientsList = "/clients/list"; + static const String clientPlaceholder = "/clients/list/placeholder"; + static const String client = "/clients/list:id"; + + static const String logs = "/logs"; + + static const String filters = "/filters"; + + static const String settings = "/settings"; +} \ No newline at end of file diff --git a/lib/functions/desktop_mode.dart b/lib/functions/desktop_mode.dart new file mode 100644 index 0000000..4586068 --- /dev/null +++ b/lib/functions/desktop_mode.dart @@ -0,0 +1,5 @@ +import 'package:adguard_home_manager/config/sizes.dart'; + +bool isDesktop(double width) { + return width > desktopBreakpoint; +} \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ee0533d..d4962e3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -667,5 +667,7 @@ "showChart": "Show chart", "hideChart": "Hide chart", "showTopItemsChart": "Show top items chart", - "showTopItemsChartDescription": "Shows by default the ring chart on the top items sections. Only affects to the mobile view." + "showTopItemsChartDescription": "Shows by default the ring chart on the top items sections. Only affects to the mobile view.", + "openMenu": "Open menu", + "closeMenu": "Close menu" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 4276b7b..2f202a8 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -667,5 +667,7 @@ "showChart": "Mostrar gráfico", "hideChart": "Ocultar gráfico", "showTopItemsChart": "Mostrar gráfico en top de items", - "showTopItemsChartDescription": "Muestra por defecto el gráfico de anillo en las secciones de top de items. Sólo afecta a la vista móvil." + "showTopItemsChartDescription": "Muestra por defecto el gráfico de anillo en las secciones de top de items. Sólo afecta a la vista móvil.", + "openMenu": "Abrir menú", + "closeMenu": "Cerrar menú" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 98bb878..fafb46e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,8 +15,7 @@ import 'package:window_size/window_size.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/base.dart'; - +import 'package:adguard_home_manager/routes/router.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; @@ -204,7 +203,7 @@ class _MainState extends State
{ final appConfigProvider = Provider.of(context); return DynamicColorBuilder( - builder: (lightDynamic, darkDynamic) => MaterialApp( + builder: (lightDynamic, darkDynamic) => MaterialApp.router( title: 'AdGuard Home Manager', theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 ? appConfigProvider.useDynamicColor == true @@ -243,7 +242,7 @@ class _MainState extends State
{ child: child!, ); }, - home: const Base(), + routerConfig: goRouter, ), ); } diff --git a/lib/models/app_screen.dart b/lib/models/app_screen.dart index bce5cc3..1e377eb 100644 --- a/lib/models/app_screen.dart +++ b/lib/models/app_screen.dart @@ -4,14 +4,12 @@ class AppScreen { final String name; final IconData icon; final PreferredSizeWidget? appBar; - final Widget body; final Widget? fab; const AppScreen({ required this.name, required this.icon, this.appBar, - required this.body, this.fab }); } \ No newline at end of file diff --git a/lib/routes/router.dart b/lib/routes/router.dart new file mode 100644 index 0000000..9b1cfba --- /dev/null +++ b/lib/routes/router.dart @@ -0,0 +1,20 @@ +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; + +import 'package:adguard_home_manager/routes/router_globals.dart'; +import 'package:adguard_home_manager/routes/routes.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/routes_names.dart'; + +final goRouter = GoRouter( + navigatorKey: rootNavigatorKey, + redirect: (context, state) { + final serversProvider = Provider.of(context, listen: false); + if (serversProvider.selectedServer == null) { + return RoutesNames.connect; + } + return null; + }, + initialLocation: RoutesNames.home, + routes: routes, +); \ No newline at end of file diff --git a/lib/routes/router_globals.dart b/lib/routes/router_globals.dart new file mode 100644 index 0000000..739c50c --- /dev/null +++ b/lib/routes/router_globals.dart @@ -0,0 +1,10 @@ +import 'package:flutter/widgets.dart'; + +final GlobalKey rootNavigatorKey = GlobalKey(); +final GlobalKey connectNavigatorKey = GlobalKey(); +final GlobalKey homeNavigatorKey = GlobalKey(); +final GlobalKey clientsNavigatorKey = GlobalKey(); +final GlobalKey clientsListNavigatorKey = GlobalKey(); +final GlobalKey logsNavigatorKey = GlobalKey(); +final GlobalKey filtersNavigatorKey = GlobalKey(); +final GlobalKey settingsNavigatorKey = GlobalKey(); \ No newline at end of file diff --git a/lib/routes/routes.dart b/lib/routes/routes.dart new file mode 100644 index 0000000..04bd218 --- /dev/null +++ b/lib/routes/routes.dart @@ -0,0 +1,113 @@ +import 'package:go_router/go_router.dart'; + +import 'package:adguard_home_manager/screens/home/home.dart'; +import 'package:adguard_home_manager/screens/clients/clients.dart'; +import 'package:adguard_home_manager/screens/connect/connect.dart'; +import 'package:adguard_home_manager/screens/filters/filters.dart'; +import 'package:adguard_home_manager/screens/settings/settings.dart'; +import 'package:adguard_home_manager/screens/clients/client/client_placeholder.dart'; +import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dart'; +import 'package:adguard_home_manager/screens/logs/logs.dart'; +import 'package:adguard_home_manager/widgets/layout.dart'; + +import 'package:adguard_home_manager/routes/router_globals.dart'; +import 'package:adguard_home_manager/constants/routes_names.dart'; + +final List routes = [ + GoRoute( + path: "/", + redirect: (context, state) => RoutesNames.home, + ), + StatefulShellRoute.indexedStack( + builder: (context, state, navigationShell) => Layout( + navigationShell: navigationShell + ), + branches: [ + StatefulShellBranch( + navigatorKey: homeNavigatorKey, + routes: [ + GoRoute( + parentNavigatorKey: homeNavigatorKey, + path: RoutesNames.home, + builder: (context, state) => const Home(), + ), + GoRoute( + parentNavigatorKey: homeNavigatorKey, + path: RoutesNames.queriedDomains, + builder: (context, state) => const Home(), + ), + GoRoute( + parentNavigatorKey: homeNavigatorKey, + path: RoutesNames.blockedDomains, + builder: (context, state) => const Home(), + ), + GoRoute( + parentNavigatorKey: homeNavigatorKey, + path: RoutesNames.recurrentClients, + builder: (context, state) => const Home(), + ), + ] + ), + StatefulShellBranch( + navigatorKey: clientsNavigatorKey, + routes: [ + ShellRoute( + parentNavigatorKey: clientsNavigatorKey, + navigatorKey: clientsListNavigatorKey, + builder: (context, state, child) => Clients(child: child), + routes: [ + GoRoute( + path: RoutesNames.clientPlaceholder, + parentNavigatorKey: clientsListNavigatorKey, + builder: (context, state) => const ClientPlaceholder(), + ), + GoRoute( + path: RoutesNames.client, + parentNavigatorKey: clientsListNavigatorKey, + builder: (context, state) => LogsListClient( + id: (state.extra as Map?)?['id'] + ) + ) + ] + ) + ] + ), + StatefulShellBranch( + navigatorKey: logsNavigatorKey, + routes: [ + GoRoute( + path: RoutesNames.logs, + builder: (context, state) => const Logs(), + ) + ] + ), + StatefulShellBranch( + navigatorKey: filtersNavigatorKey, + routes: [ + GoRoute( + path: RoutesNames.filters, + builder: (context, state) => const Filters(), + ) + ] + ), + StatefulShellBranch( + navigatorKey: settingsNavigatorKey, + routes: [ + GoRoute( + path: RoutesNames.settings, + builder: (context, state) => const Settings(), + ) + ] + ), + StatefulShellBranch( + navigatorKey: connectNavigatorKey, + routes: [ + GoRoute( + path: RoutesNames.connect, + builder: (context, state) => const Connect(), + ) + ] + ), + ] + ) +]; \ No newline at end of file diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 24b69ae..eea9dd6 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -1,7 +1,5 @@ // ignore_for_file: use_build_context_synchronously -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:flutter/rendering.dart'; @@ -157,7 +155,6 @@ class _AddedListState extends State { } return CustomTabContentList( - noSliver: !(Platform.isAndroid || Platform.isIOS), listPadding: widget.splitView == true ? const EdgeInsets.only(top: 8) : null, diff --git a/lib/screens/clients/client/client_placeholder.dart b/lib/screens/clients/client/client_placeholder.dart new file mode 100644 index 0000000..cf4f485 --- /dev/null +++ b/lib/screens/clients/client/client_placeholder.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class ClientPlaceholder extends StatelessWidget { + const ClientPlaceholder({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Center( + child: Text("Select a client"), + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index 0ddc99a..f35de0b 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -1,7 +1,9 @@ import 'dart:io'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:flutter/material.dart'; import 'package:async/async.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -12,18 +14,12 @@ import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class LogsListClient extends StatefulWidget { - final String ip; - final String? name; - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; +class LogsListClient extends StatefulHookWidget { + final String id; const LogsListClient({ Key? key, - required this.ip, - this.name, - required this.serversProvider, - required this.appConfigProvider + required this.id, }) : super(key: key); @override @@ -38,11 +34,9 @@ class _LogsListClientState extends State { int logsQuantity = 100; int offset = 0; - int loadStatus = 0; + LoadStatus loadStatus = LoadStatus.loading; LogsData? logsData; - String previousIp = ""; - bool showDivider = true; CancelableOperation? cancelableRequest; @@ -67,7 +61,7 @@ class _LogsListClientState extends State { serversProvider.apiClient!.getLogs( count: logsQuantity, offset: offst, - search: '"${widget.ip}"' + search: '"${widget.id}"' ) ); @@ -90,11 +84,11 @@ class _LogsListClientState extends State { LogsData newLogsData = result['data']; setState(() => logsData = newLogsData); } - setState(() => loadStatus = 1); + setState(() => loadStatus = LoadStatus.loaded); } else { - setState(() => loadStatus = 2); - widget.appConfigProvider.addLog(result['log']); + setState(() => loadStatus = LoadStatus.error); + Provider.of(context, listen: false).addLog(result['log']); } } } @@ -116,8 +110,6 @@ class _LogsListClientState extends State { @override void initState() { scrollController = ScrollController()..addListener(scrollListener); - fetchLogs(inOffset: 0); - setState(() => previousIp = widget.ip); super.initState(); } @@ -125,15 +117,15 @@ class _LogsListClientState extends State { Widget build(BuildContext context) { final width = MediaQuery.of(context).size.width; - if (widget.ip != previousIp) { - setState(() => loadStatus = 0); + useEffect(() { + setState(() => loadStatus = LoadStatus.loading); fetchLogs(inOffset: 0); - setState(() => previousIp = widget.ip); - } + return null; + }, [widget.id]); Widget status() { switch (loadStatus) { - case 0: + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -154,7 +146,7 @@ class _LogsListClientState extends State { ), ); - case 1: + case LoadStatus.loaded: if (logsData!.data.isNotEmpty) { return RefreshIndicator( onRefresh: fetchLogs, @@ -217,7 +209,7 @@ class _LogsListClientState extends State { ); } - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( @@ -249,7 +241,7 @@ class _LogsListClientState extends State { return Scaffold( appBar: AppBar( - title: Text(widget.name != null && widget.name != '' ? widget.name! : widget.ip), + title: Text(widget.id), centerTitle: true, actions: [ if (!(Platform.isAndroid || Platform.isIOS)) ...[ diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 4762e5b..45ccbd4 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -1,24 +1,25 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; +import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/clients_list.dart'; -import 'package:adguard_home_manager/screens/clients/search_clients.dart'; -import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dart'; -import 'package:adguard_home_manager/screens/clients/clients_desktop_view.dart'; import 'package:adguard_home_manager/screens/clients/added_list.dart'; +import 'package:adguard_home_manager/constants/routes_names.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class Clients extends StatefulWidget { - const Clients({Key? key}) : super(key: key); + final Widget child; + + const Clients({ + Key? key, + required this.child, + }) : super(key: key); @override State createState() => _ClientsState(); @@ -53,9 +54,7 @@ class _ClientsState extends State with TickerProviderStateMixin { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final clientsProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -96,163 +95,119 @@ class _ClientsState extends State with TickerProviderStateMixin { scrollController: scrollController, data: clientsProvider.loadStatus == LoadStatus.loaded ? clientsProvider.filteredActiveClients : [], - onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( - builder: (context) => LogsListClient( - ip: client.ip, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider - ) - )), - splitView: false, - sliver: sliver, + onClientSelected: (client) => context.go( + RoutesNames.client, + extra: { + "id": client.name != null && client.name != "" + ? client.name + : client.ip + } + ), + splitView: isDesktop(width), ), AddedList( scrollController: scrollController, data: clientsProvider.loadStatus == LoadStatus.loaded ? clientsProvider.filteredAddedClients : [], - onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( - builder: (context) => LogsListClient( - ip: client.ids[0], - serversProvider: serversProvider, - appConfigProvider: appConfigProvider - ) - )), - splitView: false, + onClientSelected: (client) => context.go( + RoutesNames.client, + extra: { "id": client.name } + ), + splitView: isDesktop(width), ), ] ); } - if (width > 900) { - return SplitView.material( - hideDivider: true, - flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), - placeholder: Center( - child: Padding( - padding: const EdgeInsets.all(24), - child: Text( - AppLocalizations.of(context)!.selectClientLeftColumn, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), + return Row( + children: [ + SizedBox( + width: isDesktop(width) ? 300 : width, + height: double.maxFinite, + child: Material( + child: DefaultTabController( + length: 2, + child: NestedScrollView( + controller: scrollController, + headerSliverBuilder: ((context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + title: searchMode == true + ? Row( + children: [ + IconButton( + onPressed: () { + setState(() { + searchMode = false; + searchController.text = ""; + clientsProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.arrow_back_rounded), + tooltip: AppLocalizations.of(context)!.exitSearch, + ), + const SizedBox(width: 16), + Expanded( + child: TextField( + controller: searchController, + onChanged: (value) => clientsProvider.setSearchTermClients(value), + decoration: InputDecoration( + suffixIcon: IconButton( + onPressed: () { + setState(() { + searchController.text = ""; + clientsProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.clear_rounded) + ), + hintText: AppLocalizations.of(context)!.search, + hintStyle: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + border: InputBorder.none, + ), + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + autofocus: true, + ), + ) + ], + ) + : Text(AppLocalizations.of(context)!.clients), + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + actions: [ + if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + IconButton( + onPressed: () => setState(() => searchMode = true), + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.searchClients, + ), + const SizedBox(width: 10), + ] + ], + bottom: tabBar() + ), + ) + ]; + }), + body: tabBarView(true) + ) ), ), ), - child: ClientsDesktopView( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, + if (isDesktop(width) == true) Expanded( + child: widget.child, ) - ); - } - else { - if (!(Platform.isAndroid || Platform.isIOS)) { - return DefaultTabController( - length: 2, - child: Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.clients), - centerTitle: false, - actions: [ - if (clientsProvider.loadStatus == LoadStatus.loaded) ...[ - IconButton( - onPressed: () => { - Navigator.push(context, MaterialPageRoute( - builder: (context) => const SearchClients() - )) - }, - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.searchClients, - ), - const SizedBox(width: 10), - ] - ], - bottom: tabBar() - ), - body: tabBarView(false), - ), - ); - } - else { - return DefaultTabController( - length: 2, - child: NestedScrollView( - controller: scrollController, - headerSliverBuilder: ((context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - title: searchMode == true - ? Row( - children: [ - IconButton( - onPressed: () { - setState(() { - searchMode = false; - searchController.text = ""; - clientsProvider.setSearchTermClients(null); - }); - }, - icon: const Icon(Icons.arrow_back_rounded), - tooltip: AppLocalizations.of(context)!.exitSearch, - ), - const SizedBox(width: 16), - Expanded( - child: TextField( - controller: searchController, - onChanged: (value) => clientsProvider.setSearchTermClients(value), - decoration: InputDecoration( - suffixIcon: IconButton( - onPressed: () { - setState(() { - searchController.text = ""; - clientsProvider.setSearchTermClients(null); - }); - }, - icon: const Icon(Icons.clear_rounded) - ), - hintText: AppLocalizations.of(context)!.search, - hintStyle: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - border: InputBorder.none, - ), - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - autofocus: true, - ), - ) - ], - ) - : Text(AppLocalizations.of(context)!.clients), - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - actions: [ - if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ - IconButton( - onPressed: () => setState(() => searchMode = true), - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.searchClients, - ), - const SizedBox(width: 10), - ] - ], - bottom: tabBar() - ), - ) - ]; - }), - body: tabBarView(true) - ) - ); - } - } + ], + ); } } \ No newline at end of file diff --git a/lib/screens/clients/clients_desktop_view.dart b/lib/screens/clients/clients_desktop_view.dart index 9e261ff..7356e15 100644 --- a/lib/screens/clients/clients_desktop_view.dart +++ b/lib/screens/clients/clients_desktop_view.dart @@ -97,18 +97,10 @@ class _ClientsDesktopViewState extends State with TickerPro onClientSelected: (client) => setState(() { selectedAddedClient = null; selectedActiveClient = client; - SplitView.of(context).setSecondary( - LogsListClient( - ip: client.ip, - name: client.name, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ) - ); + }), selectedClient: selectedActiveClient, splitView: true, - sliver: sliver, ), AddedList( scrollController: scrollController, @@ -117,14 +109,7 @@ class _ClientsDesktopViewState extends State with TickerPro onClientSelected: (client) => setState(() { selectedActiveClient = null; selectedAddedClient = client; - SplitView.of(context).setSecondary( - LogsListClient( - ip: client.ids[0], - name: client.name, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ) - ); + }), selectedClient: selectedAddedClient, splitView: true, diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index f3ee547..d0ecd33 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -15,7 +15,6 @@ class ClientsList extends StatelessWidget { final void Function(AutoClient) onClientSelected; final AutoClient? selectedClient; final bool splitView; - final bool sliver; const ClientsList({ Key? key, @@ -24,7 +23,6 @@ class ClientsList extends StatelessWidget { required this.onClientSelected, this.selectedClient, required this.splitView, - required this.sliver }) : super(key: key); @override @@ -35,7 +33,6 @@ class ClientsList extends StatelessWidget { listPadding: splitView == true ? const EdgeInsets.only(top: 8) : null, - noSliver: !sliver, loadingGenerator: () => SizedBox( width: double.maxFinite, height: MediaQuery.of(context).size.height-171, diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 8660f54..34893b6 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -25,6 +26,8 @@ class HomeAppBar extends StatelessWidget { final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + final Server? server = serversProvider.selectedServer; void navigateServers() { @@ -40,6 +43,7 @@ class HomeAppBar extends StatelessWidget { floating: true, centerTitle: false, forceElevated: innerBoxScrolled, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, leading: Stack( children: [ Center( diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index 366fe2c..0f16dcd 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -84,21 +84,21 @@ class BottomNavBar extends StatelessWidget { ), label: translatedName(screen.name) )).toList(), - onDestinationSelected: (value) { - // Reset clients tab to 0 when changing screen - if (value != 1) { - appConfigProvider.setSelectedClientsTab(0); - } - // Reset logs filters when changing screen - if (value != 2) { - logsProvider.resetFilters(); - } - // Reset settings selected screen - if (value != screens.length-1) { - appConfigProvider.setSelectedSettingsScreen(screen: null); - } - appConfigProvider.setSelectedScreen(value); - }, + // onDestinationSelected: (value) { + // // Reset clients tab to 0 when changing screen + // if (value != 1) { + // appConfigProvider.setSelectedClientsTab(0); + // } + // // Reset logs filters when changing screen + // if (value != 2) { + // logsProvider.resetFilters(); + // } + // // Reset settings selected screen + // if (value != screens.length-1) { + // appConfigProvider.setSelectedSettingsScreen(screen: null); + // } + // appConfigProvider.setSelectedScreen(value); + // }, ); } } \ No newline at end of file diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart new file mode 100644 index 0000000..3513bb9 --- /dev/null +++ b/lib/widgets/layout.dart @@ -0,0 +1,250 @@ +import 'package:adguard_home_manager/widgets/bottom_nav_bar.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:go_router/go_router.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/config/app_screens.dart'; +import 'package:adguard_home_manager/config/sizes.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class Layout extends StatefulWidget { + final StatefulNavigationShell navigationShell; + + const Layout({ + Key? key, + required this.navigationShell, + }) : super(key: key); + + @override + State createState() => _LayoutState(); +} + +class _LayoutState extends State { + bool _drawerExpanded = true; + + void _goBranch(int index) { + widget.navigationShell.goBranch( + index, + initialLocation: index == widget.navigationShell.currentIndex, + ); + } + + @override + Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + + final serversProvider = Provider.of(context); + + String translatedName(String key) { + switch (key) { + case 'home': + return AppLocalizations.of(context)!.home; + + case 'settings': + return AppLocalizations.of(context)!.settings; + + case 'connect': + return AppLocalizations.of(context)!.connect; + + case 'clients': + return AppLocalizations.of(context)!.clients; + + case 'logs': + return AppLocalizations.of(context)!.logs; + + case 'filters': + return AppLocalizations.of(context)!.filters; + + default: + return ''; + } + } + + if (width > desktopBreakpoint) { + return Material( + child: Row( + children: [ + AnimatedContainer( + duration: const Duration(milliseconds: 250), + curve: Curves.ease, + width: _drawerExpanded ? 250 : 90, + child: ListView( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 16 + ), + child: IconButton( + onPressed: () => setState(() => _drawerExpanded = !_drawerExpanded), + icon: const Icon(Icons.menu_open_rounded), + tooltip: _drawerExpanded == true + ? AppLocalizations.of(context)!.closeMenu + : AppLocalizations.of(context)!.openMenu, + ), + ), + ], + ), + if (serversProvider.selectedServer != null) + ...screensServerConnected.asMap().entries.map( + (s) => DrawerTile( + icon: s.value.icon, + title: translatedName(s.value.name), + isSelected: + widget.navigationShell.currentIndex == s.key, + onSelect: () => _goBranch(s.key), + withoutTitle: !_drawerExpanded, + ), + ), + if (serversProvider.selectedServer == null) + ...screensSelectServer.asMap().entries.map( + (s) => DrawerTile( + icon: s.value.icon, + title: translatedName(s.value.name), + isSelected: + widget.navigationShell.currentIndex == s.key, + onSelect: () => _goBranch(s.key), + withoutTitle: !_drawerExpanded, + ), + ), + ], + ), + ), + Expanded( + child: widget.navigationShell + ), + ], + ), + ); + } + else { + final screens = serversProvider.selectedServer != null && serversProvider.apiClient != null + ? screensServerConnected + : screensSelectServer; + + return Scaffold( + body: widget.navigationShell, + bottomNavigationBar: NavigationBar( + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && widget.navigationShell.currentIndex > 1 + ? 0 + : widget.navigationShell.currentIndex, + onDestinationSelected: (s) => _goBranch(s), + destinations: screens.asMap().entries.map((screen) => NavigationDestination( + icon: Stack( + children: [ + Icon( + screen.value.icon, + color: widget.navigationShell.currentIndex == screen.key + ? Theme.of(context).colorScheme.onSecondaryContainer + : Theme.of(context).colorScheme.onSurfaceVariant, + ), + if ( + screen.value.name == 'settings' && + serversProvider.updateAvailable.data != null && + serversProvider.updateAvailable.data!.canAutoupdate == true + ) Positioned( + bottom: 0, + right: -12, + child: Container( + width: 10, + height: 10, + margin: const EdgeInsets.only(right: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.red + ), + ), + ) + ], + ), + label: translatedName(screen.value.name) + )).toList(), + ) + ); + } + } +} + +class DrawerTile extends StatelessWidget { + final IconData icon; + final String title; + final bool isSelected; + final void Function() onSelect; + final bool? withoutTitle; + + const DrawerTile({ + super.key, + required this.icon, + required this.title, + required this.isSelected, + required this.onSelect, + this.withoutTitle, + }); + + @override + Widget build(BuildContext context) { + Widget iconWidget = withoutTitle == true + ? Tooltip( + message: title, + child: Icon( + icon, + color: isSelected + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + : Icon( + icon, + color: isSelected + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant, + ); + + return Padding( + padding: const EdgeInsets.only(right: 16), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: const BorderRadius.only( + topRight: Radius.circular(30), + bottomRight: Radius.circular(30), + ), + onTap: onSelect, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + color: isSelected + ? Theme.of(context).colorScheme.secondaryContainer + : null, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(30), + bottomRight: Radius.circular(30), + ), + ), + child: Row(children: [ + iconWidget, + const SizedBox(width: 16), + Flexible( + child: Text( + title, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 14, + color: isSelected + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ) + ]), + ), + ), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index c647bf5..a194327 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -222,6 +222,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.0" + flutter_hooks: + dependency: "direct main" + description: + name: flutter_hooks + sha256: "7c8db779c2d1010aa7f9ea3fbefe8f86524fcb87b69e8b0af31e1a4b55422dec" + url: "https://pub.dev" + source: hosted + version: "0.20.3" flutter_html: dependency: "direct main" description: @@ -310,6 +318,14 @@ packages: description: flutter source: sdk version: "0.0.0" + go_router: + dependency: "direct main" + description: + name: go_router + sha256: e156bc1b2088eb5ece9351bccd48c3e1719a4858eacbd44e59162e98a68205d1 + url: "https://pub.dev" + source: hosted + version: "12.0.1" html: dependency: "direct main" description: @@ -382,6 +398,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" markdown: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2445ec4..06ae67d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -74,6 +74,8 @@ dependencies: flutter_dotenv: ^5.0.2 flutter_reorderable_list: ^1.3.1 pie_chart: ^5.3.2 + go_router: ^12.0.1 + flutter_hooks: ^0.20.3 dev_dependencies: flutter_test: From 96fe7eb730603ed0bc45b247cd158434cc0f3e5c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 02:19:00 +0100 Subject: [PATCH 344/676] Implemented new router --- lib/config/app_screens.dart | 7 - lib/constants/routes_names.dart | 12 + lib/routes/router_globals.dart | 4 +- lib/routes/routes.dart | 44 +- .../clients/client/logs_list_client.dart | 49 +- lib/screens/clients/clients.dart | 222 +------ lib/screens/clients/clients_desktop_view.dart | 229 ------- lib/screens/clients/clients_list.dart | 2 - lib/screens/clients/clients_lists.dart | 222 +++++++ lib/screens/filters/filters.dart | 34 +- lib/screens/filters/filters_tabs_view.dart | 4 + .../filters/filters_triple_column.dart | 4 + lib/screens/logs/log_details_screen.dart | 4 + lib/screens/logs/log_tile.dart | 6 +- lib/screens/logs/logs.dart | 601 ++---------------- lib/screens/logs/logs_list.dart | 566 +++++++++++++++++ lib/screens/settings/settings.dart | 65 +- 17 files changed, 985 insertions(+), 1090 deletions(-) delete mode 100644 lib/screens/clients/clients_desktop_view.dart create mode 100644 lib/screens/clients/clients_lists.dart create mode 100644 lib/screens/logs/logs_list.dart diff --git a/lib/config/app_screens.dart b/lib/config/app_screens.dart index 91d33f0..4f9a97d 100644 --- a/lib/config/app_screens.dart +++ b/lib/config/app_screens.dart @@ -1,12 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:adguard_home_manager/screens/filters/filters.dart'; -import 'package:adguard_home_manager/screens/logs/logs.dart'; -import 'package:adguard_home_manager/screens/connect/connect.dart'; -import 'package:adguard_home_manager/screens/home/home.dart'; -import 'package:adguard_home_manager/screens/clients/clients.dart'; -import 'package:adguard_home_manager/screens/settings/settings.dart'; - import 'package:adguard_home_manager/models/app_screen.dart'; List screensSelectServer = [ diff --git a/lib/constants/routes_names.dart b/lib/constants/routes_names.dart index dae8723..fa0b07c 100644 --- a/lib/constants/routes_names.dart +++ b/lib/constants/routes_names.dart @@ -16,4 +16,16 @@ class RoutesNames { static const String filters = "/filters"; static const String settings = "/settings"; + static const String safeSearch = "/settings/safe-search"; + static const String accessSettings = "/settings/access-settigs"; + static const String dhcpSettings = "/settings/dhcp-settings"; + static const String dnsSettings = "/settings/dns-settings"; + static const String encryptionSettings = "/settings/encryption-settings"; + static const String dnsRewrites = "/settings/dns-rewrites"; + static const String serverUpdates = "/settings/server-updates"; + static const String serverInfo = "/settings/server-info"; + static const String customization = "/settings/customization"; + static const String servers = "/settings/servers"; + static const String generalSettings = "/settings/general-settings"; + static const String advancedSettings = "/settings/advanced-settings"; } \ No newline at end of file diff --git a/lib/routes/router_globals.dart b/lib/routes/router_globals.dart index 739c50c..f78c1a7 100644 --- a/lib/routes/router_globals.dart +++ b/lib/routes/router_globals.dart @@ -4,7 +4,7 @@ final GlobalKey rootNavigatorKey = GlobalKey(); final GlobalKey connectNavigatorKey = GlobalKey(); final GlobalKey homeNavigatorKey = GlobalKey(); final GlobalKey clientsNavigatorKey = GlobalKey(); -final GlobalKey clientsListNavigatorKey = GlobalKey(); final GlobalKey logsNavigatorKey = GlobalKey(); final GlobalKey filtersNavigatorKey = GlobalKey(); -final GlobalKey settingsNavigatorKey = GlobalKey(); \ No newline at end of file +final GlobalKey settingsNavigatorKey = GlobalKey(); +final GlobalKey settingsListNavigatorKey = GlobalKey(); \ No newline at end of file diff --git a/lib/routes/routes.dart b/lib/routes/routes.dart index 04bd218..a216446 100644 --- a/lib/routes/routes.dart +++ b/lib/routes/routes.dart @@ -4,10 +4,8 @@ import 'package:adguard_home_manager/screens/home/home.dart'; import 'package:adguard_home_manager/screens/clients/clients.dart'; import 'package:adguard_home_manager/screens/connect/connect.dart'; import 'package:adguard_home_manager/screens/filters/filters.dart'; -import 'package:adguard_home_manager/screens/settings/settings.dart'; -import 'package:adguard_home_manager/screens/clients/client/client_placeholder.dart'; -import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dart'; import 'package:adguard_home_manager/screens/logs/logs.dart'; +import 'package:adguard_home_manager/screens/settings/settings.dart'; import 'package:adguard_home_manager/widgets/layout.dart'; import 'package:adguard_home_manager/routes/router_globals.dart'; @@ -31,44 +29,15 @@ final List routes = [ path: RoutesNames.home, builder: (context, state) => const Home(), ), - GoRoute( - parentNavigatorKey: homeNavigatorKey, - path: RoutesNames.queriedDomains, - builder: (context, state) => const Home(), - ), - GoRoute( - parentNavigatorKey: homeNavigatorKey, - path: RoutesNames.blockedDomains, - builder: (context, state) => const Home(), - ), - GoRoute( - parentNavigatorKey: homeNavigatorKey, - path: RoutesNames.recurrentClients, - builder: (context, state) => const Home(), - ), ] ), StatefulShellBranch( navigatorKey: clientsNavigatorKey, routes: [ - ShellRoute( + GoRoute( parentNavigatorKey: clientsNavigatorKey, - navigatorKey: clientsListNavigatorKey, - builder: (context, state, child) => Clients(child: child), - routes: [ - GoRoute( - path: RoutesNames.clientPlaceholder, - parentNavigatorKey: clientsListNavigatorKey, - builder: (context, state) => const ClientPlaceholder(), - ), - GoRoute( - path: RoutesNames.client, - parentNavigatorKey: clientsListNavigatorKey, - builder: (context, state) => LogsListClient( - id: (state.extra as Map?)?['id'] - ) - ) - ] + path: RoutesNames.clients, + builder: (context, state) => const Clients(), ) ] ), @@ -76,6 +45,7 @@ final List routes = [ navigatorKey: logsNavigatorKey, routes: [ GoRoute( + parentNavigatorKey: logsNavigatorKey, path: RoutesNames.logs, builder: (context, state) => const Logs(), ) @@ -85,6 +55,7 @@ final List routes = [ navigatorKey: filtersNavigatorKey, routes: [ GoRoute( + parentNavigatorKey: filtersNavigatorKey, path: RoutesNames.filters, builder: (context, state) => const Filters(), ) @@ -94,7 +65,8 @@ final List routes = [ navigatorKey: settingsNavigatorKey, routes: [ GoRoute( - path: RoutesNames.settings, + parentNavigatorKey: settingsNavigatorKey, + path: RoutesNames.settings, builder: (context, state) => const Settings(), ) ] diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index f35de0b..eb724fd 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -1,9 +1,7 @@ import 'dart:io'; -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:flutter/material.dart'; import 'package:async/async.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -14,12 +12,20 @@ import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class LogsListClient extends StatefulHookWidget { - final String id; +class LogsListClient extends StatefulWidget { + final String ip; + final String? name; + final ServersProvider serversProvider; + final AppConfigProvider appConfigProvider; + final bool splitView; const LogsListClient({ Key? key, - required this.id, + required this.ip, + this.name, + required this.serversProvider, + required this.appConfigProvider, + required this.splitView, }) : super(key: key); @override @@ -34,9 +40,11 @@ class _LogsListClientState extends State { int logsQuantity = 100; int offset = 0; - LoadStatus loadStatus = LoadStatus.loading; + int loadStatus = 0; LogsData? logsData; + String previousIp = ""; + bool showDivider = true; CancelableOperation? cancelableRequest; @@ -61,7 +69,7 @@ class _LogsListClientState extends State { serversProvider.apiClient!.getLogs( count: logsQuantity, offset: offst, - search: '"${widget.id}"' + search: '"${widget.ip}"' ) ); @@ -84,11 +92,11 @@ class _LogsListClientState extends State { LogsData newLogsData = result['data']; setState(() => logsData = newLogsData); } - setState(() => loadStatus = LoadStatus.loaded); + setState(() => loadStatus = 1); } else { - setState(() => loadStatus = LoadStatus.error); - Provider.of(context, listen: false).addLog(result['log']); + setState(() => loadStatus = 2); + widget.appConfigProvider.addLog(result['log']); } } } @@ -110,6 +118,8 @@ class _LogsListClientState extends State { @override void initState() { scrollController = ScrollController()..addListener(scrollListener); + fetchLogs(inOffset: 0); + setState(() => previousIp = widget.ip); super.initState(); } @@ -117,15 +127,15 @@ class _LogsListClientState extends State { Widget build(BuildContext context) { final width = MediaQuery.of(context).size.width; - useEffect(() { - setState(() => loadStatus = LoadStatus.loading); + if (widget.ip != previousIp) { + setState(() => loadStatus = 0); fetchLogs(inOffset: 0); - return null; - }, [widget.id]); + setState(() => previousIp = widget.ip); + } Widget status() { switch (loadStatus) { - case LoadStatus.loading: + case 0: return SizedBox( width: double.maxFinite, child: Column( @@ -146,7 +156,7 @@ class _LogsListClientState extends State { ), ); - case LoadStatus.loaded: + case 1: if (logsData!.data.isNotEmpty) { return RefreshIndicator( onRefresh: fetchLogs, @@ -189,7 +199,8 @@ class _LogsListClientState extends State { ) )) } - } + }, + twoColumns: widget.splitView, ); } } @@ -209,7 +220,7 @@ class _LogsListClientState extends State { ); } - case LoadStatus.error: + case 2: return SizedBox( width: double.maxFinite, child: Column( @@ -241,7 +252,7 @@ class _LogsListClientState extends State { return Scaffold( appBar: AppBar( - title: Text(widget.id), + title: Text(widget.name != null && widget.name != '' ? widget.name! : widget.ip), centerTitle: true, actions: [ if (!(Platform.isAndroid || Platform.isIOS)) ...[ diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 45ccbd4..80393a8 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -1,213 +1,55 @@ import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/clients/clients_list.dart'; -import 'package:adguard_home_manager/screens/clients/added_list.dart'; +import 'package:adguard_home_manager/screens/clients/clients_lists.dart'; -import 'package:adguard_home_manager/constants/routes_names.dart'; -import 'package:adguard_home_manager/functions/desktop_mode.dart'; -import 'package:adguard_home_manager/providers/clients_provider.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients.dart'; class Clients extends StatefulWidget { - final Widget child; - - const Clients({ - Key? key, - required this.child, - }) : super(key: key); + const Clients({Key? key}) : super(key: key); @override State createState() => _ClientsState(); } class _ClientsState extends State with TickerProviderStateMixin { - late TabController tabController; - final ScrollController scrollController = ScrollController(); - - bool searchMode = false; - final TextEditingController searchController = TextEditingController(); - - @override - void initState() { - final clientsProvider = Provider.of(context, listen: false); - clientsProvider.fetchClients(updateLoading: true); - - super.initState(); - tabController = TabController( - initialIndex: 0, - length: 2, - vsync: this, - ); - tabController.addListener( - () => Provider.of(context, listen: false).setSelectedClientsTab(tabController.index) - ); - } - List generateClientsList(List clients, List ips) { return clients.where((client) => ips.contains(client.ip)).toList(); } @override Widget build(BuildContext context) { - final clientsProvider = Provider.of(context); - - final width = MediaQuery.of(context).size.width; - - PreferredSizeWidget tabBar() { - return TabBar( - controller: tabController, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.devices), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.activeClients) - ], + return LayoutBuilder( + builder: (context, constraints) { + if (constraints.maxWidth > 1000) { + return SplitView.material( + hideDivider: true, + flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), + placeholder: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + AppLocalizations.of(context)!.selectClientLeftColumn, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), ), - ), - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.add_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.added) - ], - ), - ), - ] - ); - } - - Widget tabBarView(bool sliver) { - return TabBarView( - controller: tabController, - children: [ - ClientsList( - scrollController: scrollController, - data: clientsProvider.loadStatus == LoadStatus.loaded - ? clientsProvider.filteredActiveClients : [], - onClientSelected: (client) => context.go( - RoutesNames.client, - extra: { - "id": client.name != null && client.name != "" - ? client.name - : client.ip - } - ), - splitView: isDesktop(width), - ), - AddedList( - scrollController: scrollController, - data: clientsProvider.loadStatus == LoadStatus.loaded - ? clientsProvider.filteredAddedClients : [], - onClientSelected: (client) => context.go( - RoutesNames.client, - extra: { "id": client.name } - ), - splitView: isDesktop(width), - ), - ] - ); - } - - return Row( - children: [ - SizedBox( - width: isDesktop(width) ? 300 : width, - height: double.maxFinite, - child: Material( - child: DefaultTabController( - length: 2, - child: NestedScrollView( - controller: scrollController, - headerSliverBuilder: ((context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - title: searchMode == true - ? Row( - children: [ - IconButton( - onPressed: () { - setState(() { - searchMode = false; - searchController.text = ""; - clientsProvider.setSearchTermClients(null); - }); - }, - icon: const Icon(Icons.arrow_back_rounded), - tooltip: AppLocalizations.of(context)!.exitSearch, - ), - const SizedBox(width: 16), - Expanded( - child: TextField( - controller: searchController, - onChanged: (value) => clientsProvider.setSearchTermClients(value), - decoration: InputDecoration( - suffixIcon: IconButton( - onPressed: () { - setState(() { - searchController.text = ""; - clientsProvider.setSearchTermClients(null); - }); - }, - icon: const Icon(Icons.clear_rounded) - ), - hintText: AppLocalizations.of(context)!.search, - hintStyle: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - border: InputBorder.none, - ), - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - autofocus: true, - ), - ) - ], - ) - : Text(AppLocalizations.of(context)!.clients), - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - actions: [ - if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ - IconButton( - onPressed: () => setState(() => searchMode = true), - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.searchClients, - ), - const SizedBox(width: 10), - ] - ], - bottom: tabBar() - ), - ) - ]; - }), - body: tabBarView(true) - ) - ), - ), - ), - if (isDesktop(width) == true) Expanded( - child: widget.child, - ) - ], + child: const ClientsLists( + splitView: true, + ) + ); + } + else { + return const ClientsLists( + splitView: false, + ); + } + }, ); } } \ No newline at end of file diff --git a/lib/screens/clients/clients_desktop_view.dart b/lib/screens/clients/clients_desktop_view.dart deleted file mode 100644 index 7356e15..0000000 --- a/lib/screens/clients/clients_desktop_view.dart +++ /dev/null @@ -1,229 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dart'; -import 'package:adguard_home_manager/screens/clients/added_list.dart'; -import 'package:adguard_home_manager/screens/clients/clients_list.dart'; - -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/clients_provider.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; - - -class ClientsDesktopView extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const ClientsDesktopView({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - }) : super(key: key); - - @override - State createState() => _ClientsDesktopViewState(); -} - -class _ClientsDesktopViewState extends State with TickerProviderStateMixin { - late TabController tabController; - final ScrollController scrollController = ScrollController(); - - AutoClient? selectedActiveClient; - Client? selectedAddedClient; - - bool searchMode = false; - final TextEditingController searchController = TextEditingController(); - - @override - void initState() { - super.initState(); - tabController = TabController( - initialIndex: 0, - length: 2, - vsync: this, - ); - tabController.addListener(() => widget.appConfigProvider.setSelectedClientsTab(tabController.index)); - } - - @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final clientsProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - PreferredSizeWidget tabBar() { - return TabBar( - controller: tabController, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.devices), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.activeClients) - ], - ), - ), - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.add_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.added) - ], - ), - ), - ] - ); - } - - Widget tabBarView(bool sliver) { - return TabBarView( - controller: tabController, - children: [ - ClientsList( - scrollController: scrollController, - data: clientsProvider.loadStatus == LoadStatus.loaded - ? clientsProvider.filteredActiveClients : [], - onClientSelected: (client) => setState(() { - selectedAddedClient = null; - selectedActiveClient = client; - - }), - selectedClient: selectedActiveClient, - splitView: true, - ), - AddedList( - scrollController: scrollController, - data: clientsProvider.loadStatus == LoadStatus.loaded - ? clientsProvider.filteredAddedClients : [], - onClientSelected: (client) => setState(() { - selectedActiveClient = null; - selectedAddedClient = client; - - }), - selectedClient: selectedAddedClient, - splitView: true, - ), - ] - ); - } - - Widget title() { - if (searchMode == true) { - return Row( - children: [ - IconButton( - onPressed: () { - setState(() { - searchMode = false; - searchController.text = ""; - clientsProvider.setSearchTermClients(null); - }); - }, - icon: const Icon(Icons.arrow_back_rounded) - ), - const SizedBox(width: 16), - Expanded( - child: TextField( - controller: searchController, - onChanged: (value) => clientsProvider.setSearchTermClients(value), - decoration: InputDecoration( - suffixIcon: IconButton( - onPressed: () { - setState(() { - searchController.text = ""; - clientsProvider.setSearchTermClients(null); - }); - }, - icon: const Icon(Icons.clear_rounded) - ), - hintText: AppLocalizations.of(context)!.search, - hintStyle: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - border: InputBorder.none, - ), - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - ), - ) - ], - ); - } - else { - return Text(AppLocalizations.of(context)!.clients); - } - } - - if (!(Platform.isAndroid || Platform.isIOS)) { - return DefaultTabController( - length: 2, - child: Scaffold( - appBar: AppBar( - title: title(), - centerTitle: false, - actions: [ - if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ - IconButton( - onPressed: () => setState(() => searchMode = true), - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.searchClients, - ), - const SizedBox(width: 10), - ] - ], - bottom: tabBar() - ), - body: tabBarView(false), - ), - ); - } - else { - return DefaultTabController( - length: 2, - child: NestedScrollView( - controller: scrollController, - headerSliverBuilder: ((context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - title: title(), - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - actions: [ - if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ - IconButton( - onPressed: () => setState(() => searchMode = true), - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.searchClients, - ), - const SizedBox(width: 10), - ] - ], - bottom: tabBar() - ), - ) - ]; - }), - body: tabBarView(true) - ) - ); - } - } -} \ No newline at end of file diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index d0ecd33..2e52738 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -10,7 +10,6 @@ import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; class ClientsList extends StatelessWidget { - final ScrollController scrollController; final List data; final void Function(AutoClient) onClientSelected; final AutoClient? selectedClient; @@ -18,7 +17,6 @@ class ClientsList extends StatelessWidget { const ClientsList({ Key? key, - required this.scrollController, required this.data, required this.onClientSelected, this.selectedClient, diff --git a/lib/screens/clients/clients_lists.dart b/lib/screens/clients/clients_lists.dart new file mode 100644 index 0000000..ec451bc --- /dev/null +++ b/lib/screens/clients/clients_lists.dart @@ -0,0 +1,222 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/clients/added_list.dart'; +import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dart'; +import 'package:adguard_home_manager/screens/clients/clients_list.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class ClientsLists extends StatefulWidget { + final bool splitView; + + const ClientsLists({ + Key? key, + required this.splitView, + }) : super(key: key); + + @override + State createState() => _ClientsListsState(); +} + +class _ClientsListsState extends State with TickerProviderStateMixin { + late TabController tabController; + final ScrollController scrollController = ScrollController(); + + bool searchMode = false; + final TextEditingController searchController = TextEditingController(); + + AutoClient? _selectedAutoClient; + Client? _selectedClient; + + @override + void initState() { + final clientsProvider = Provider.of(context, listen: false); + clientsProvider.fetchClients(updateLoading: true); + + super.initState(); + tabController = TabController( + initialIndex: 0, + length: 2, + vsync: this, + ); + tabController.addListener( + () => Provider.of(context, listen: false).setSelectedClientsTab(tabController.index) + ); + } + + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final clientsProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void onAutoClientSelected(AutoClient client) { + setState(() => _selectedAutoClient = client); + final w = LogsListClient( + ip: client.ip, + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + splitView: widget.splitView, + ); + if (widget.splitView) { + SplitView.of(context).push(w); + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => w, + )); + } + } + + void onClientSelected(Client client) { + setState(() => _selectedClient = client); + final w = LogsListClient( + ip: client.ids[0], + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + splitView: widget.splitView, + ); + if (widget.splitView) { + SplitView.of(context).push(w); + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => w, + )); + } + } + + return DefaultTabController( + length: 2, + child: NestedScrollView( + headerSliverBuilder: ((context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + title: searchMode == true + ? Row( + children: [ + IconButton( + onPressed: () { + setState(() { + searchMode = false; + searchController.text = ""; + clientsProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.arrow_back_rounded), + tooltip: AppLocalizations.of(context)!.exitSearch, + ), + const SizedBox(width: 16), + Expanded( + child: TextField( + controller: searchController, + onChanged: (value) => clientsProvider.setSearchTermClients(value), + decoration: InputDecoration( + suffixIcon: IconButton( + onPressed: () { + setState(() { + searchController.text = ""; + clientsProvider.setSearchTermClients(null); + }); + }, + icon: const Icon(Icons.clear_rounded) + ), + hintText: AppLocalizations.of(context)!.search, + hintStyle: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + border: InputBorder.none, + ), + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + autofocus: true, + ), + ) + ], + ) + : Text(AppLocalizations.of(context)!.clients), + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + surfaceTintColor: isDesktop(MediaQuery.of(context).size.width) + ? Colors.transparent + : null, + actions: [ + if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + IconButton( + onPressed: () => setState(() => searchMode = true), + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.searchClients, + ), + const SizedBox(width: 10), + ] + ], + bottom: TabBar( + controller: tabController, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.devices), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.activeClients) + ], + ), + ), + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.add_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.added) + ], + ), + ), + ] + ) + ), + ) + ]; + }), + body: TabBarView( + controller: tabController, + children: [ + ClientsList( + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredActiveClients : [], + onClientSelected: onAutoClientSelected, + selectedClient: _selectedAutoClient, + splitView: widget.splitView, + ), + AddedList( + scrollController: scrollController, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredAddedClients : [], + onClientSelected: onClientSelected, + selectedClient: _selectedClient, + splitView: widget.splitView, + ), + ] + ) + ) + ); + } +} \ No newline at end of file diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index c4e6d9b..4b94b1e 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -324,20 +324,24 @@ class _FiltersState extends State { } } - if (width > 1200) { - return FiltersTripleColumn( - onRemoveCustomRule: openRemoveCustomRuleModal, - onOpenDetailsModal: openListDetails, - actions: actions(), - ); - } - else { - return FiltersTabsView( - appConfigProvider: appConfigProvider, - actions: actions(), - onRemoveCustomRule: openRemoveCustomRuleModal, - onOpenDetailsModal: openListDetails, - ); - } + return LayoutBuilder( + builder: (context, constraints) { + if (constraints.maxWidth > 900) { + return FiltersTripleColumn( + onRemoveCustomRule: openRemoveCustomRuleModal, + onOpenDetailsModal: openListDetails, + actions: actions(), + ); + } + else { + return FiltersTabsView( + appConfigProvider: appConfigProvider, + actions: actions(), + onRemoveCustomRule: openRemoveCustomRuleModal, + onOpenDetailsModal: openListDetails, + ); + } + }, + ); } } \ No newline at end of file diff --git a/lib/screens/filters/filters_tabs_view.dart b/lib/screens/filters/filters_tabs_view.dart index 81cd67a..63e6a4e 100644 --- a/lib/screens/filters/filters_tabs_view.dart +++ b/lib/screens/filters/filters_tabs_view.dart @@ -5,6 +5,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/custom_rules_list.dart'; import 'package:adguard_home_manager/screens/filters/filters_list.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/filtering.dart'; @@ -47,6 +48,8 @@ class _FiltersTabsViewState extends State with TickerProviderSt Widget build(BuildContext context) { final filteringProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + return DefaultTabController( length: 3, child: NestedScrollView( @@ -62,6 +65,7 @@ class _FiltersTabsViewState extends State with TickerProviderSt forceElevated: innerBoxIsScrolled, centerTitle: false, actions: widget.actions, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, bottom: TabBar( controller: tabController, isScrollable: true, diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 2f7979d..3a8bfa2 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -13,6 +13,7 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; @@ -37,6 +38,8 @@ class FiltersTripleColumn extends StatelessWidget { Widget build(BuildContext context) { final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; Widget? generateSubtitle(String rule) { final allowRegex = RegExp(r'^@@.*$'); @@ -325,6 +328,7 @@ class FiltersTripleColumn extends StatelessWidget { return Scaffold( appBar: AppBar( + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, title: Text(AppLocalizations.of(context)!.filters), actions: [ IconButton( diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 859d5e7..161e9fa 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -8,6 +8,7 @@ import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/screens/logs/log_list_tile.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -34,6 +35,8 @@ class LogDetailsScreen extends StatelessWidget { final appConfigProvider = Provider.of(context); final statusProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + Filter? getList(int id) { try { return statusProvider.filteringStatus!.filters.firstWhere((filter) => filter.id == id, orElse: () { @@ -288,6 +291,7 @@ class LogDetailsScreen extends StatelessWidget { floating: true, centerTitle: false, forceElevated: innerBoxIsScrolled, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, title: Text(AppLocalizations.of(context)!.logDetails), actions: [ IconButton( diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index bd2b1a9..40f3b0d 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -17,6 +17,7 @@ class LogTile extends StatelessWidget { final bool? isLogSelected; final void Function(Log) onLogTap; final bool? useAlwaysNormalTile; + final bool twoColumns; const LogTile({ Key? key, @@ -25,7 +26,8 @@ class LogTile extends StatelessWidget { required this.index, this.isLogSelected, required this.onLogTap, - this.useAlwaysNormalTile + this.useAlwaysNormalTile, + required this.twoColumns, }) : super(key: key); @override @@ -83,7 +85,7 @@ class LogTile extends StatelessWidget { } } - if (width > 1100 && !(useAlwaysNormalTile == true)) { + if (twoColumns && !(useAlwaysNormalTile == true)) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: InkWell( diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 6d9cef6..b218ad7 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -1,27 +1,10 @@ // ignore_for_file: use_build_context_synchronously -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/logs/logs_filters_modal.dart'; -import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart'; -import 'package:adguard_home_manager/screens/logs/log_tile.dart'; -import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; - -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; -import 'package:adguard_home_manager/providers/clients_provider.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/providers/logs_provider.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/logs.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/screens/logs/logs_list.dart'; +import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; class Logs extends StatefulWidget { const Logs({Key? key}) : super(key: key); @@ -31,554 +14,48 @@ class Logs extends StatefulWidget { } class _LogsState extends State { - bool showDivider = true; - - Log? selectedLog; - - void fetchFilteringRules() async { - final appConfigProvider = Provider.of(context, listen: false); - final statusProvider = Provider.of(context, listen: false); - - final result = await statusProvider.getFilteringRules(); - if (mounted && result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.couldntGetFilteringStatus, - color: Colors.red - ); - } - } - - Future fetchClients() async { - final clientsProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - final result = await clientsProvider.fetchClients(); - if (mounted && result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.couldntGetFilteringStatus, - color: Colors.red - ); - } - } - - bool scrollListener(ScrollUpdateNotification scrollNotification) { - final logsProvider = Provider.of(context, listen: false); - - if (scrollNotification.metrics.extentAfter < 500 && logsProvider.isLoadingMore == false) { - logsProvider.fetchLogs(loadingMore: true); - } - if (scrollNotification.metrics.pixels > 0) { - setState(() => showDivider = false); - } - else { - setState(() => showDivider = true); - } - - return false; - } - - @override - void initState() { - final logsProvider = Provider.of(context, listen: false); - - logsProvider.fetchLogs(inOffset: 0); - fetchFilteringRules(); - fetchClients(); - super.initState(); - } + Log? _selectedLog; @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); + - final width = MediaQuery.of(context).size.width; - - void updateConfig(Map data) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.updatingSettings); - - final result = serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? await serversProvider.apiClient!.updateQueryLogParameters(data: data) - : await serversProvider.apiClient!.updateQueryLogParametersLegacy(data: data); - - processModal.close(); - - if (result['result'] == 'success') { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsConfigUpdated, - color: Colors.green - ); - } - else { - appConfigProvider.addLog(result['log']); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsConfigNotUpdated, - color: Colors.red - ); - } - } - - void clearQueries() async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.updatingSettings); - - final result = await serversProvider.apiClient!.clearLogs(); - - processModal.close(); - - if (result['result'] == 'success') { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsCleared, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsNotCleared, - color: Colors.red - ); - } - } - - - void openFilersModal() { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => const LogsFiltersModal( - dialog: true, - ), - barrierDismissible: false - ); - } - else { - showModalBottomSheet( - context: context, - builder: (context) => const LogsFiltersModal( - dialog: false, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ); - } - } - - final Map translatedString = { - "all": AppLocalizations.of(context)!.all, - "filtered": AppLocalizations.of(context)!.filtered, - "processed": AppLocalizations.of(context)!.processedRow, - "whitelisted": AppLocalizations.of(context)!.processedWhitelistRow, - "blocked": AppLocalizations.of(context)!.blocked, - "blocked_safebrowsing": AppLocalizations.of(context)!.blockedSafeBrowsingRow, - "blocked_parental": AppLocalizations.of(context)!.blockedParentalRow, - "safe_search": AppLocalizations.of(context)!.safeSearch, - }; - - Widget generateBody() { - switch (logsProvider.loadStatus) { - case LoadStatus.loading: - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverFillRemaining( - child: SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingLogs, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ) + return LayoutBuilder( + builder: (context, constraints) { + if (constraints.maxWidth > 1000) { + return Material( + color: Colors.transparent, + child: Row( + children: [ + Expanded( + flex: 2, + child: LogsListWidget( + twoColumns: true, + selectedLog: _selectedLog, + onLogSelected: (log) => setState(() => _selectedLog = log), ) - ], - ), - ) - ); - - case LoadStatus.loaded: - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => RefreshIndicator( - onRefresh: () async { - await logsProvider.fetchLogs(inOffset: 0); - }, - displacement: 95, - child: NotificationListener( - onNotification: scrollListener, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (logsProvider.logsData!.data.isNotEmpty) SliverList.builder( - itemCount: logsProvider.isLoadingMore - ? logsProvider.logsData!.data.length + 1 - : logsProvider.logsData!.data.length, - itemBuilder: (context, index) { - if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { - return const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - else if (logsProvider.logsData!.data[index].question.name != null) { - return LogTile( - log: logsProvider.logsData!.data[index], - index: index, - length: logsProvider.logsData!.data.length, - isLogSelected: selectedLog != null && selectedLog == logsProvider.logsData!.data[index], - onLogTap: (log) { - if (width <= 1100) { - Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false, - ) - )); - } - setState(() => selectedLog = log); - } - ); - } - else { - return null; - } - } - ), - if (logsProvider.logsData!.data.isEmpty) SliverFillRemaining( - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - AppLocalizations.of(context)!.noLogsDisplay, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - if (logsProvider.logsOlderThan != null) Padding( - padding: const EdgeInsets.only( - top: 30, - left: 20, - right: 20 - ), - child: Text( - AppLocalizations.of(context)!.noLogsThatOld, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - ] - ), - ), - ) - ], - ), ), - ), - ) - ); - - case LoadStatus.error: - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverFillRemaining( - child: SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.logsNotLoaded, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ) - ) - ], - ), - ) - ); - - default: - return const SizedBox(); - } - } - - Widget logsScreen() { - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(AppLocalizations.of(context)!.logs), - expandedHeight: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null - ? 170 : null, - actions: [ - if (!(Platform.isAndroid || Platform.isIOS)) IconButton( - onPressed: () => logsProvider.fetchLogs(inOffset: 0), - icon: const Icon(Icons.refresh_rounded), - tooltip: AppLocalizations.of(context)!.refresh, - ), - logsProvider.loadStatus == LoadStatus.loaded - ? IconButton( - onPressed: openFilersModal, - icon: const Icon(Icons.filter_list_rounded), - tooltip: AppLocalizations.of(context)!.filters, + Expanded( + flex: 3, + child: _selectedLog != null + ? LogDetailsScreen( + log: _selectedLog!, + dialog: false, ) - : const SizedBox(), - if (statusProvider.serverStatus != null) IconButton( - tooltip: AppLocalizations.of(context)!.settings, - onPressed: () => { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => LogsConfigModal( - onConfirm: updateConfig, - onClear: clearQueries, - dialog: true, - serverVersion: statusProvider.serverStatus!.serverVersion, - ), - barrierDismissible: false - ) - } - else { - showModalBottomSheet( - context: context, - builder: (context) => LogsConfigModal( - onConfirm: updateConfig, - onClear: clearQueries, - dialog: false, - serverVersion: statusProvider.serverStatus!.serverVersion, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ) - } - }, - icon: const Icon(Icons.settings) - ), - const SizedBox(width: 5), - ], - bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null - ? PreferredSize( - preferredSize: const Size(double.maxFinite, 70), - child: Container( - height: 50, - width: double.maxFinite, - padding: const EdgeInsets.only(bottom: 10), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: showDivider == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.1) - : Colors.transparent, - ) - ) - ), - child: ListView( - scrollDirection: Axis.horizontal, - children: [ - if (logsProvider.appliedFilters.searchText != null) ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.search_rounded, - ), - label: Row( - children: [ - Text( - logsProvider.appliedFilters.searchText!, - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: null, - clients: logsProvider.appliedFilters.clients - ) - ); - logsProvider.setSearchText(null); - logsProvider.fetchLogs( - inOffset: 0, - searchText: '' - ); - }, - ), - ], - if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.shield_rounded, - ), - label: Row( - children: [ - Text( - translatedString[logsProvider.appliedFilters.selectedResultStatus]!, - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: logsProvider.appliedFilters.searchText, - clients: logsProvider.appliedFilters.clients - ) - ); - logsProvider.setSelectedResultStatus('all'); - logsProvider.fetchLogs( - inOffset: 0, - responseStatus: 'all' - ); - }, - ), - ], - if (logsProvider.appliedFilters.clients != null) ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.smartphone_rounded, - ), - label: Row( - children: [ - Text( - logsProvider.appliedFilters.clients!.length == 1 - ? logsProvider.appliedFilters.clients![0] - : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: logsProvider.appliedFilters.searchText, - clients: null - ) - ); - logsProvider.setSelectedClients(null); - logsProvider.fetchLogs( - inOffset: 0, - responseStatus: logsProvider.appliedFilters.selectedResultStatus - ); - }, - ), - ], - const SizedBox(width: 15), - ], - ), - ) - ) - : null, - ), - ) - ], - body: generateBody() - ), - ); - } - - if (width > 1100) { - return Material( - color: Colors.transparent, - child: Row( - children: [ - Expanded( - flex: 1, - child: logsScreen() + : const SizedBox() + ) + ], ), - Expanded( - flex: 2, - child: selectedLog != null - ? LogDetailsScreen( - log: selectedLog!, - dialog: false, - ) - : const SizedBox() - ) - ], - ), - ); - } - else { - return logsScreen(); - } + ); + } + else { + return LogsListWidget( + twoColumns: false, + selectedLog: _selectedLog, + onLogSelected: (log) => setState(() => _selectedLog = log), + ); + } + }, + ); } } \ No newline at end of file diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart new file mode 100644 index 0000000..9ca811d --- /dev/null +++ b/lib/screens/logs/logs_list.dart @@ -0,0 +1,566 @@ +// ignore_for_file: use_build_context_synchronously + +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/logs/log_details_screen.dart'; +import 'package:adguard_home_manager/screens/logs/log_tile.dart'; +import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart'; +import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/models/logs.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; +import 'package:adguard_home_manager/providers/logs_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; + +class LogsListWidget extends StatefulWidget { + final Log? selectedLog; + final bool twoColumns; + final void Function(Log) onLogSelected; + + const LogsListWidget({ + Key? key, + required this.twoColumns, + required this.selectedLog, + required this.onLogSelected, + }) : super(key: key); + + @override + State createState() => _LogsListWidgetState(); +} + +class _LogsListWidgetState extends State { + bool showDivider = true; + + void fetchFilteringRules() async { + final appConfigProvider = Provider.of(context, listen: false); + final statusProvider = Provider.of(context, listen: false); + + final result = await statusProvider.getFilteringRules(); + if (mounted && result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.couldntGetFilteringStatus, + color: Colors.red + ); + } + } + + Future fetchClients() async { + final clientsProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + + final result = await clientsProvider.fetchClients(); + if (mounted && result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.couldntGetFilteringStatus, + color: Colors.red + ); + } + } + + bool scrollListener(ScrollUpdateNotification scrollNotification) { + final logsProvider = Provider.of(context, listen: false); + + if (scrollNotification.metrics.extentAfter < 500 && logsProvider.isLoadingMore == false) { + logsProvider.fetchLogs(loadingMore: true); + } + if (scrollNotification.metrics.pixels > 0) { + setState(() => showDivider = false); + } + else { + setState(() => showDivider = true); + } + + return false; + } + + @override + void initState() { + final logsProvider = Provider.of(context, listen: false); + + logsProvider.fetchLogs(inOffset: 0); + fetchFilteringRules(); + fetchClients(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + final logsProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; + + void updateConfig(Map data) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.updatingSettings); + + final result = serverVersionIsAhead( + currentVersion: statusProvider.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? await serversProvider.apiClient!.updateQueryLogParameters(data: data) + : await serversProvider.apiClient!.updateQueryLogParametersLegacy(data: data); + + processModal.close(); + + if (result['result'] == 'success') { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsConfigUpdated, + color: Colors.green + ); + } + else { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsConfigNotUpdated, + color: Colors.red + ); + } + } + + void clearQueries() async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.updatingSettings); + + final result = await serversProvider.apiClient!.clearLogs(); + + processModal.close(); + + if (result['result'] == 'success') { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsCleared, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsNotCleared, + color: Colors.red + ); + } + } + + + void openFilersModal() { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => const LogsFiltersModal( + dialog: true, + ), + barrierDismissible: false + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => const LogsFiltersModal( + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ); + } + } + + final Map translatedString = { + "all": AppLocalizations.of(context)!.all, + "filtered": AppLocalizations.of(context)!.filtered, + "processed": AppLocalizations.of(context)!.processedRow, + "whitelisted": AppLocalizations.of(context)!.processedWhitelistRow, + "blocked": AppLocalizations.of(context)!.blocked, + "blocked_safebrowsing": AppLocalizations.of(context)!.blockedSafeBrowsingRow, + "blocked_parental": AppLocalizations.of(context)!.blockedParentalRow, + "safe_search": AppLocalizations.of(context)!.safeSearch, + }; + + return Scaffold( + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, + title: Text(AppLocalizations.of(context)!.logs), + expandedHeight: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + ? 170 : null, + actions: [ + if (!(Platform.isAndroid || Platform.isIOS)) IconButton( + onPressed: () => logsProvider.fetchLogs(inOffset: 0), + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ), + logsProvider.loadStatus == LoadStatus.loaded + ? IconButton( + onPressed: openFilersModal, + icon: const Icon(Icons.filter_list_rounded), + tooltip: AppLocalizations.of(context)!.filters, + ) + : const SizedBox(), + if (statusProvider.serverStatus != null) IconButton( + tooltip: AppLocalizations.of(context)!.settings, + onPressed: () => { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => LogsConfigModal( + onConfirm: updateConfig, + onClear: clearQueries, + dialog: true, + serverVersion: statusProvider.serverStatus!.serverVersion, + ), + barrierDismissible: false + ) + } + else { + showModalBottomSheet( + context: context, + builder: (context) => LogsConfigModal( + onConfirm: updateConfig, + onClear: clearQueries, + dialog: false, + serverVersion: statusProvider.serverStatus!.serverVersion, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ) + } + }, + icon: const Icon(Icons.settings) + ), + const SizedBox(width: 5), + ], + bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + ? PreferredSize( + preferredSize: const Size(double.maxFinite, 70), + child: Container( + height: 50, + width: double.maxFinite, + padding: const EdgeInsets.only(bottom: 10), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: showDivider == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.1) + : Colors.transparent, + ) + ) + ), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + if (logsProvider.appliedFilters.searchText != null) ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.search_rounded, + ), + label: Row( + children: [ + Text( + logsProvider.appliedFilters.searchText!, + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: null, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.setSearchText(null); + logsProvider.fetchLogs( + inOffset: 0, + searchText: '' + ); + }, + ), + ], + if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.shield_rounded, + ), + label: Row( + children: [ + Text( + translatedString[logsProvider.appliedFilters.selectedResultStatus]!, + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: logsProvider.appliedFilters.searchText, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.setSelectedResultStatus('all'); + logsProvider.fetchLogs( + inOffset: 0, + responseStatus: 'all' + ); + }, + ), + ], + if (logsProvider.appliedFilters.clients != null) ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.smartphone_rounded, + ), + label: Row( + children: [ + Text( + logsProvider.appliedFilters.clients!.length == 1 + ? logsProvider.appliedFilters.clients![0] + : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: logsProvider.appliedFilters.searchText, + clients: null + ) + ); + logsProvider.setSelectedClients(null); + logsProvider.fetchLogs( + inOffset: 0, + responseStatus: logsProvider.appliedFilters.selectedResultStatus + ); + }, + ), + ], + const SizedBox(width: 15), + ], + ), + ) + ) + : null, + ), + ) + ], + body: Builder( + builder: (context) { + switch (logsProvider.loadStatus) { + case LoadStatus.loading: + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverFillRemaining( + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingLogs, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) + ) + ], + ), + ) + ); + + case LoadStatus.loaded: + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => RefreshIndicator( + onRefresh: () async { + await logsProvider.fetchLogs(inOffset: 0); + }, + displacement: 95, + child: NotificationListener( + onNotification: scrollListener, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (logsProvider.logsData!.data.isNotEmpty) SliverList.builder( + itemCount: logsProvider.isLoadingMore + ? logsProvider.logsData!.data.length + 1 + : logsProvider.logsData!.data.length, + itemBuilder: (context, index) { + if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else if (logsProvider.logsData!.data[index].question.name != null) { + return LogTile( + log: logsProvider.logsData!.data[index], + index: index, + length: logsProvider.logsData!.data.length, + isLogSelected: widget.selectedLog != null && widget.selectedLog == logsProvider.logsData!.data[index], + onLogTap: (log) { + if (!widget.twoColumns) { + Navigator.push(context, MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + ) + )); + } + widget.onLogSelected(log); + }, + twoColumns: widget.twoColumns, + ); + } + else { + return null; + } + } + ), + if (logsProvider.logsData!.data.isEmpty) SliverFillRemaining( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context)!.noLogsDisplay, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + if (logsProvider.logsOlderThan != null) Padding( + padding: const EdgeInsets.only( + top: 30, + left: 20, + right: 20 + ), + child: Text( + AppLocalizations.of(context)!.noLogsThatOld, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ] + ), + ), + ) + ], + ), + ), + ), + ) + ); + + case LoadStatus.error: + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverFillRemaining( + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.logsNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) + ) + ], + ), + ) + ); + + default: + return const SizedBox(); + } + }, + ) + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 2f9a24d..87d23ef 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -23,6 +23,7 @@ import 'package:adguard_home_manager/widgets/custom_settings_tile.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/desktop_mode.dart'; import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; @@ -36,35 +37,46 @@ class Settings extends StatelessWidget { @override Widget build(BuildContext context) { - final width = MediaQuery.of(context).size.width; - - if (width > 900) { - return SplitView.material( - hideDivider: true, - flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), - placeholder: Center( - child: Padding( - padding: const EdgeInsets.all(24), - child: Text( - AppLocalizations.of(context)!.selectOptionLeftColumn, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant + return LayoutBuilder( + builder: (context, constraints) { + if (constraints.maxWidth > 900) { + return SplitView.material( + hideDivider: true, + flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), + placeholder: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + AppLocalizations.of(context)!.selectOptionLeftColumn, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), ), ), - ), - ), - child: const SettingsWidget(), - ); - } - else { - return const SettingsWidget(); - } + child: const SettingsWidget( + twoColumns: true, + ), + ); + } + else { + return const SettingsWidget( + twoColumns: false, + ); + } + }, + ); } } class SettingsWidget extends StatelessWidget { - const SettingsWidget({Key? key}) : super(key: key); + final bool twoColumns; + + const SettingsWidget({ + Key? key, + required this.twoColumns, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -74,7 +86,7 @@ class SettingsWidget extends StatelessWidget { final width = MediaQuery.of(context).size.width; - if (width <= 900 && appConfigProvider.selectedSettingsScreen != null) { + if (!twoColumns && appConfigProvider.selectedSettingsScreen != null) { appConfigProvider.setSelectedSettingsScreen(screen: null); } @@ -86,7 +98,7 @@ class SettingsWidget extends StatelessWidget { required Widget screenToNavigate, required int thisItem }) { - if (width > 900) { + if (twoColumns) { return CustomSettingsTile( title: title, subtitle: subtitle, @@ -125,6 +137,7 @@ class SettingsWidget extends StatelessWidget { floating: true, centerTitle: false, forceElevated: innerBoxIsScrolled, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, title: Text(AppLocalizations.of(context)!.settings), ) ) From 91d4d2c87a911bc1fa9f72826296ef11fe96cada Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 02:47:14 +0100 Subject: [PATCH 345/676] Removed color appbar desktop mode --- .../clients/client/logs_list_client.dart | 240 ++--- lib/screens/filters/add_button.dart | 2 + lib/screens/filters/filters.dart | 2 + lib/screens/filters/list_details_screen.dart | 1 + lib/screens/home/fab.dart | 1 + lib/screens/logs/logs_filters_modal.dart | 2 + lib/screens/logs/logs_list.dart | 4 +- .../access_settings/access_settings.dart | 4 + .../access_settings/clients_list.dart | 1 + lib/screens/settings/advanced_setings.dart | 4 + .../settings/customization/customization.dart | 6 +- lib/screens/settings/dhcp/dhcp.dart | 980 +++++++++--------- lib/screens/settings/dhcp/dhcp_leases.dart | 3 + lib/screens/settings/dns/bootstrap_dns.dart | 4 + lib/screens/settings/dns/cache_config.dart | 4 + lib/screens/settings/dns/dns.dart | 202 ++-- .../settings/dns/dns_server_settings.dart | 3 + .../settings/dns/private_reverse_servers.dart | 4 + lib/screens/settings/dns/upstream_dns.dart | 4 + .../settings/dns_rewrites/dns_rewrites.dart | 364 +++---- .../settings/encryption/encryption.dart | 744 ++++++------- .../general_settings/general_settings.dart | 4 + .../reorderable_top_items_home.dart | 4 + .../settings/safe_search_settings.dart | 322 +++--- .../settings/server_info/server_info.dart | 221 ++-- lib/screens/settings/settings.dart | 4 +- 26 files changed, 1607 insertions(+), 1527 deletions(-) diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index eb724fd..5d8f6ed 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -8,6 +8,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -133,127 +134,13 @@ class _LogsListClientState extends State { setState(() => previousIp = widget.ip); } - Widget status() { - switch (loadStatus) { - case 0: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingLogs, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case 1: - if (logsData!.data.isNotEmpty) { - return RefreshIndicator( - onRefresh: fetchLogs, - child: ListView.builder( - controller: scrollController, - padding: const EdgeInsets.only(top: 0), - itemCount: isLoadingMore == true - ? logsData!.data.length+1 - : logsData!.data.length, - itemBuilder: (context, index) { - if (isLoadingMore == true && index == logsData!.data.length) { - return const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - else { - return LogTile( - log: logsData!.data[index], - index: index, - length: logsData!.data.length, - useAlwaysNormalTile: true, - onLogTap: (log) => { - if (width > 700) { - showDialog( - context: context, - builder: (context) => LogDetailsScreen( - log: log, - dialog: true - ) - ) - } - else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false - ) - )) - } - }, - twoColumns: widget.splitView, - ); - } - } - ), - ); - } - else { - return Center( - child: Text( - AppLocalizations.of(context)!.noLogsDisplay, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ); - } - - case 2: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.logsNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - } - return Scaffold( appBar: AppBar( title: Text(widget.name != null && widget.name != '' ? widget.name! : widget.ip), centerTitle: true, + surfaceTintColor: isDesktop(MediaQuery.of(context).size.width) + ? Colors.transparent + : null, actions: [ if (!(Platform.isAndroid || Platform.isIOS)) ...[ IconButton( @@ -265,7 +152,124 @@ class _LogsListClientState extends State { ] ], ), - body: status(), + body: Builder( + builder: (context) { + switch (loadStatus) { + case 0: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingLogs, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case 1: + if (logsData!.data.isNotEmpty) { + return RefreshIndicator( + onRefresh: fetchLogs, + child: ListView.builder( + controller: scrollController, + padding: const EdgeInsets.only(top: 0), + itemCount: isLoadingMore == true + ? logsData!.data.length+1 + : logsData!.data.length, + itemBuilder: (context, index) { + if (isLoadingMore == true && index == logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else { + return LogTile( + log: logsData!.data[index], + index: index, + length: logsData!.data.length, + useAlwaysNormalTile: true, + onLogTap: (log) => { + if (width > 700) { + showDialog( + context: context, + builder: (context) => LogDetailsScreen( + log: log, + dialog: true + ) + ) + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false + ) + )) + } + }, + twoColumns: widget.splitView, + ); + } + } + ), + ); + } + else { + return Center( + child: Text( + AppLocalizations.of(context)!.noLogsDisplay, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ); + } + + case 2: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.logsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ) ); } } \ No newline at end of file diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 195d7af..7afccf0 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -2,6 +2,7 @@ import 'dart:io'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -134,6 +135,7 @@ class AddFiltersButton extends StatelessWidget { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (ctx) => AddListModal( type: type, onConfirm: confirmAddList, diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 4b94b1e..5975cf6 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -87,6 +87,7 @@ class _FiltersState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => const CheckHostModal( dialog: false, ), @@ -269,6 +270,7 @@ class _FiltersState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => UpdateIntervalListsModal( interval: filteringProvider.filtering!.interval, onChange: setUpdateFrequency, diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index e98c759..236ee75 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -219,6 +219,7 @@ class _ListDetailsScreenState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (ctx) => AddListModal( list: list, type: widget.type, diff --git a/lib/screens/home/fab.dart b/lib/screens/home/fab.dart index 0e7db97..d0701cc 100644 --- a/lib/screens/home/fab.dart +++ b/lib/screens/home/fab.dart @@ -28,6 +28,7 @@ class HomeFab extends StatelessWidget { showModalBottomSheet( context: context, isScrollControlled: true, + useRootNavigator: true, builder: (context) => const ManagementModal( dialog: false, ), diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/logs_filters_modal.dart index 5251d9a..8f1d7f0 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/logs_filters_modal.dart @@ -89,6 +89,7 @@ class _LogsFiltersModalWidgetState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => FilterStatusModal( value: logsProvider.selectedResultStatus, dialog: false, @@ -113,6 +114,7 @@ class _LogsFiltersModalWidgetState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => ClientsModal( value: logsProvider.selectedClients, dialog: false, diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart index 9ca811d..6fd80e6 100644 --- a/lib/screens/logs/logs_list.dart +++ b/lib/screens/logs/logs_list.dart @@ -176,6 +176,7 @@ class _LogsListWidgetState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => const LogsFiltersModal( dialog: false, ), @@ -240,7 +241,8 @@ class _LogsListWidgetState extends State { } else { showModalBottomSheet( - context: context, + context: context, + useRootNavigator: true, builder: (context) => LogsConfigModal( onConfirm: updateConfig, onClear: clearQueries, diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index beb34fd..ca9cf12 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/access_settings/clients_list.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; @@ -35,6 +36,8 @@ class _AccessSettingsState extends State with TickerProviderStat Widget build(BuildContext context) { final clientsProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + Widget body() { return TabBarView( controller: tabController, @@ -119,6 +122,7 @@ class _AccessSettingsState extends State with TickerProviderStat floating: true, centerTitle: false, forceElevated: innerBoxIsScrolled, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, bottom: tabBar() ), ), diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 31c01a7..6f87c7c 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -361,6 +361,7 @@ class _ClientsListState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => AddClientModal( type: widget.type, onConfirm: confirmAddItem, diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 66ff49b..75572c1 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -16,6 +17,8 @@ class AdvancedSettings extends StatelessWidget { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + Future updateSettings({ required bool newStatus, required Future Function(bool) function @@ -40,6 +43,7 @@ class AdvancedSettings extends StatelessWidget { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.advancedSettings), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, ), body: ListView( children: [ diff --git a/lib/screens/settings/customization/customization.dart b/lib/screens/settings/customization/customization.dart index 98a7121..6ddd5e4 100644 --- a/lib/screens/settings/customization/customization.dart +++ b/lib/screens/settings/customization/customization.dart @@ -1,4 +1,3 @@ -import 'package:adguard_home_manager/functions/generate_color_translation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -9,6 +8,8 @@ import 'package:adguard_home_manager/screens/settings/customization/theme_mode_b import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; +import 'package:adguard_home_manager/functions/generate_color_translation.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/colors.dart'; @@ -56,10 +57,13 @@ class _CustomizationWidgetState extends State { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.customization), centerTitle: false, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, ), body: ListView( children: [ diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 724a33a..aa44414 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -12,6 +12,7 @@ import 'package:adguard_home_manager/widgets/confirm_action_modal.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_leases.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/select_interface_modal.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/dhcp_provider.dart'; @@ -337,6 +338,7 @@ class _DhcpScreenState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => SelectInterfaceModal( interfaces: dhcpProvider.dhcp!.networkInterfaces, onSelect: (i) => setState(() { @@ -353,498 +355,11 @@ class _DhcpScreenState extends State { }); } - Widget generateBody() { - switch (dhcpProvider.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingDhcp, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - if (selectedInterface != null) { - return SingleChildScrollView( - child: Wrap( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - left: 16, - right: 16 - ), - child: Material( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: selectedInterface != null - ? () => setState(() => enabled = !enabled) - : null, - borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.enableDhcpServer, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - if (selectedInterface != null) ...[ - Text( - selectedInterface!.name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).listTileTheme.textColor - ), - ) - ] - ], - ), - Switch( - value: enabled, - onChanged: selectedInterface != null - ? (value) => setState(() => enabled = value) - : null, - ), - ], - ), - ), - ), - ), - ), - if (selectedInterface!.ipv4Addresses.isNotEmpty) ...[ - SectionLabel( - label: AppLocalizations.of(context)!.ipv4settings, - padding: const EdgeInsets.only( - top: 24, left: 16, right: 16, bottom: 8 - ) - ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4StartRangeController, - onChanged: (value) => validateIpV4(value, 'ipv4StartRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_previous_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4StartRangeError, - labelText: AppLocalizations.of(context)!.startOfRange, - ), - keyboardType: TextInputType.number, - ), - ), - ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4EndRangeController, - onChanged: (value) => validateIpV4(value, 'ipv4EndRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_next_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4EndRangeError, - labelText: AppLocalizations.of(context)!.endOfRange, - ), - keyboardType: TextInputType.number, - ), - ), - ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4SubnetMaskController, - onChanged: (value) => validateIpV4(value, 'ipv4SubnetMaskError', AppLocalizations.of(context)!.subnetMaskNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.hub_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4SubnetMaskError, - labelText: AppLocalizations.of(context)!.subnetMask, - ), - keyboardType: TextInputType.number, - ), - ), - ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4GatewayController, - onChanged: (value) => validateIpV4(value, 'ipv4GatewayError', AppLocalizations.of(context)!.gatewayNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.router_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4GatewayError, - labelText: AppLocalizations.of(context)!.gateway, - ), - keyboardType: TextInputType.number, - ), - ), - ), - FractionallySizedBox( - widthFactor: 1, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4LeaseTimeController, - onChanged: (value) { - if (int.tryParse(value).runtimeType == int) { - setState(() => ipv4LeaseTimeError = null); - } - else { - setState(() => ipv4LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); - } - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.timer), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4LeaseTimeError, - labelText: AppLocalizations.of(context)!.leaseTime, - ), - keyboardType: TextInputType.number, - ), - ), - ), - ], - if (selectedInterface!.ipv6Addresses.isNotEmpty) ...[ - SectionLabel( - label: AppLocalizations.of(context)!.ipv6settings, - padding: const EdgeInsets.all(16) - ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 8, bottom: 12, left: 16, right: 8) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv6StartRangeController, - onChanged: (value) => validateIpV4(value, 'ipv6StartRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_next_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv6StartRangeError, - labelText: AppLocalizations.of(context)!.startOfRange, - ), - keyboardType: TextInputType.number, - ), - ), - ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 8, bottom: 12, left: 8, right: 16) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv6EndRangeController, - onChanged: (value) => validateIpV4(value, 'ipv6EndRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_previous_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv6EndRangeError, - labelText: AppLocalizations.of(context)!.endOfRange, - ), - keyboardType: TextInputType.number, - ), - ), - ), - FractionallySizedBox( - widthFactor: 1, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv6LeaseTimeController, - onChanged: (value) { - if (int.tryParse(value).runtimeType == int) { - setState(() => ipv6LeaseTimeError = null); - } - else { - setState(() => ipv6LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); - } - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.timer), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv6LeaseTimeError, - labelText: AppLocalizations.of(context)!.leaseTime, - ), - keyboardType: TextInputType.number, - ), - ), - ), - ], - const SizedBox(height: 20), - SectionLabel( - label: AppLocalizations.of(context)!.dhcpLeases, - padding: const EdgeInsets.all(16), - ), - if (width <= 900) Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.leases, - staticLeases: false, - ) - )); - }, - child: Container( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.dhcpLeases, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - Icon( - Icons.arrow_forward_rounded, - color: Theme.of(context).colorScheme.onSurface, - ) - ], - ), - ), - ), - ), - if (width <= 900) Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, - staticLeases: true, - ) - )); - }, - child: Container( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.dhcpStatic, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - Icon( - Icons.arrow_forward_rounded, - color: Theme.of(context).colorScheme.onSurface, - ) - ], - ), - ), - ), - ), - if (width > 900) Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ElevatedButton( - onPressed: () { - if (!(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push( - DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.leases, - staticLeases: false, - ) - ); - } - else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.leases, - staticLeases: false, - ) - )); - } - }, - child: Row( - children: [ - Text(AppLocalizations.of(context)!.dhcpLeases), - const SizedBox(width: 8), - const Icon(Icons.arrow_forward_rounded) - ], - ) - ), - ElevatedButton( - onPressed: () { - if (!(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push( - DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, - staticLeases: true, - ) - ); - } - else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, - staticLeases: true, - ) - )); - } - }, - child: Row( - children: [ - Text(AppLocalizations.of(context)!.dhcpStatic), - const SizedBox(width: 8), - const Icon(Icons.arrow_forward_rounded) - ], - ) - ), - ], - ), - const SizedBox(height: 10) - ], - ), - ); - } - else { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Flexible( - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.neededSelectInterface, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5) - ), - ), - ), - const SizedBox(height: 30), - ElevatedButton( - onPressed: selectInterface, - child: Text(AppLocalizations.of(context)!.selectInterface) - ), - ], - ), - ), - ], - ); - } - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.dhcpSettingsNotLoaded, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - } - - return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.dhcpSettings), centerTitle: false, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, actions: selectedInterface != null ? [ IconButton( onPressed: checkDataValid() == true @@ -890,7 +405,494 @@ class _DhcpScreenState extends State { const SizedBox(width: 10) ] : null, ), - body: generateBody(), + body: Builder( + builder: (context) { + switch (dhcpProvider.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingDhcp, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + if (selectedInterface != null) { + return SingleChildScrollView( + child: Wrap( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + left: 16, + right: 16 + ), + child: Material( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: selectedInterface != null + ? () => setState(() => enabled = !enabled) + : null, + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.enableDhcpServer, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + if (selectedInterface != null) ...[ + Text( + selectedInterface!.name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).listTileTheme.textColor + ), + ) + ] + ], + ), + Switch( + value: enabled, + onChanged: selectedInterface != null + ? (value) => setState(() => enabled = value) + : null, + ), + ], + ), + ), + ), + ), + ), + if (selectedInterface!.ipv4Addresses.isNotEmpty) ...[ + SectionLabel( + label: AppLocalizations.of(context)!.ipv4settings, + padding: const EdgeInsets.only( + top: 24, left: 16, right: 16, bottom: 8 + ) + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4StartRangeController, + onChanged: (value) => validateIpV4(value, 'ipv4StartRangeError', AppLocalizations.of(context)!.ipNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_previous_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4StartRangeError, + labelText: AppLocalizations.of(context)!.startOfRange, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4EndRangeController, + onChanged: (value) => validateIpV4(value, 'ipv4EndRangeError', AppLocalizations.of(context)!.ipNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_next_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4EndRangeError, + labelText: AppLocalizations.of(context)!.endOfRange, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4SubnetMaskController, + onChanged: (value) => validateIpV4(value, 'ipv4SubnetMaskError', AppLocalizations.of(context)!.subnetMaskNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.hub_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4SubnetMaskError, + labelText: AppLocalizations.of(context)!.subnetMask, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4GatewayController, + onChanged: (value) => validateIpV4(value, 'ipv4GatewayError', AppLocalizations.of(context)!.gatewayNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.router_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4GatewayError, + labelText: AppLocalizations.of(context)!.gateway, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: 1, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv4LeaseTimeController, + onChanged: (value) { + if (int.tryParse(value).runtimeType == int) { + setState(() => ipv4LeaseTimeError = null); + } + else { + setState(() => ipv4LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); + } + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.timer), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4LeaseTimeError, + labelText: AppLocalizations.of(context)!.leaseTime, + ), + keyboardType: TextInputType.number, + ), + ), + ), + ], + if (selectedInterface!.ipv6Addresses.isNotEmpty) ...[ + SectionLabel( + label: AppLocalizations.of(context)!.ipv6settings, + padding: const EdgeInsets.all(16) + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 8, bottom: 12, left: 16, right: 8) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv6StartRangeController, + onChanged: (value) => validateIpV4(value, 'ipv6StartRangeError', AppLocalizations.of(context)!.ipNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_next_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv6StartRangeError, + labelText: AppLocalizations.of(context)!.startOfRange, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 8, bottom: 12, left: 8, right: 16) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv6EndRangeController, + onChanged: (value) => validateIpV4(value, 'ipv6EndRangeError', AppLocalizations.of(context)!.ipNotValid), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_previous_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv6EndRangeError, + labelText: AppLocalizations.of(context)!.endOfRange, + ), + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: 1, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: ipv6LeaseTimeController, + onChanged: (value) { + if (int.tryParse(value).runtimeType == int) { + setState(() => ipv6LeaseTimeError = null); + } + else { + setState(() => ipv6LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); + } + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.timer), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv6LeaseTimeError, + labelText: AppLocalizations.of(context)!.leaseTime, + ), + keyboardType: TextInputType.number, + ), + ), + ), + ], + const SizedBox(height: 20), + SectionLabel( + label: AppLocalizations.of(context)!.dhcpLeases, + padding: const EdgeInsets.all(16), + ), + if (width <= 900) Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.leases, + staticLeases: false, + ) + )); + }, + child: Container( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.dhcpLeases, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + Icon( + Icons.arrow_forward_rounded, + color: Theme.of(context).colorScheme.onSurface, + ) + ], + ), + ), + ), + ), + if (width <= 900) Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, + staticLeases: true, + ) + )); + }, + child: Container( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.dhcpStatic, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + Icon( + Icons.arrow_forward_rounded, + color: Theme.of(context).colorScheme.onSurface, + ) + ], + ), + ), + ), + ), + if (width > 900) Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () { + if (!(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push( + DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.leases, + staticLeases: false, + ) + ); + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.leases, + staticLeases: false, + ) + )); + } + }, + child: Row( + children: [ + Text(AppLocalizations.of(context)!.dhcpLeases), + const SizedBox(width: 8), + const Icon(Icons.arrow_forward_rounded) + ], + ) + ), + ElevatedButton( + onPressed: () { + if (!(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push( + DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, + staticLeases: true, + ) + ); + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, + staticLeases: true, + ) + )); + } + }, + child: Row( + children: [ + Text(AppLocalizations.of(context)!.dhcpStatic), + const SizedBox(width: 8), + const Icon(Icons.arrow_forward_rounded) + ], + ) + ), + ], + ), + const SizedBox(height: 10) + ], + ), + ); + } + else { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.neededSelectInterface, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5) + ), + ), + ), + const SizedBox(height: 30), + ElevatedButton( + onPressed: selectInterface, + child: Text(AppLocalizations.of(context)!.selectInterface) + ), + ], + ), + ), + ], + ); + } + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.dhcpSettingsNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ) ); } } \ No newline at end of file diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index 3763704..60a5644 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -2,6 +2,7 @@ import 'dart:io'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:animations/animations.dart'; @@ -108,6 +109,7 @@ class DhcpLeases extends StatelessWidget { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => AddStaticLeaseModal( onConfirm: createLease, dialog: false, @@ -120,6 +122,7 @@ class DhcpLeases extends StatelessWidget { return Scaffold( appBar: AppBar( + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, title: Text( staticLeases == true ? AppLocalizations.of(context)!.dhcpStatic diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index 055042d..291601a 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -1,5 +1,6 @@ // ignore_for_file: use_build_context_synchronously +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -66,6 +67,8 @@ class _BootstrapDnsScreenState extends State { final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void saveData() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); @@ -102,6 +105,7 @@ class _BootstrapDnsScreenState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.bootstrapDns), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, actions: [ IconButton( onPressed: validValues == true diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index eb5aad3..b092a8b 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -7,6 +7,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/screens/settings/dns/clear_dns_cache_dialog.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -69,6 +70,8 @@ class _CacheConfigDnsScreenState extends State { final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void saveData() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); @@ -154,6 +157,7 @@ class _CacheConfigDnsScreenState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.dnsCacheConfig), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, actions: [ IconButton( onPressed: validData == true diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index eac3c2c..1aa63fd 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -1,9 +1,6 @@ // ignore_for_file: use_build_context_synchronously import 'dart:io'; - -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:flutter/material.dart'; import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; @@ -17,13 +14,21 @@ import 'package:adguard_home_manager/screens/settings/dns/private_reverse_server import 'package:adguard_home_manager/screens/settings/dns/upstream_dns.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/clear_dns_cache.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class DnsSettings extends StatefulWidget { - const DnsSettings({Key? key}) : super(key: key); + final bool splitView; + + const DnsSettings({ + Key? key, + required this.splitView, + }) : super(key: key); @override State createState() => _DnsSettingsState(); @@ -44,106 +49,17 @@ class _DnsSettingsState extends State { final width = MediaQuery.of(context).size.width; - void navigate(Widget widget) { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push(widget); + void navigate(Widget w) { + if (widget.splitView) { + SplitView.of(context).push(w); } else { Navigator.push(context, MaterialPageRoute( - builder: (context) => widget + builder: (context) => w )); } } - Widget generateBody() { - switch (dnsProvider.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingDnsConfig, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ) - ); - - case LoadStatus.loaded: - return ListView( - children: [ - CustomListTile( - title: AppLocalizations.of(context)!.upstreamDns, - subtitle: AppLocalizations.of(context)!.upstreamDnsDescription, - onTap: () => navigate(const UpstreamDnsScreen()), - icon: Icons.upload_rounded, - ), - CustomListTile( - title: AppLocalizations.of(context)!.bootstrapDns, - subtitle: AppLocalizations.of(context)!.bootstrapDnsDescription, - onTap: () => navigate(const BootstrapDnsScreen()), - icon: Icons.dns_rounded, - ), - CustomListTile( - title: AppLocalizations.of(context)!.privateReverseDnsServers, - subtitle: AppLocalizations.of(context)!.privateReverseDnsDescription, - onTap: () => navigate(const PrivateReverseDnsServersScreen()), - icon: Icons.person_rounded, - ), - CustomListTile( - title: AppLocalizations.of(context)!.dnsServerSettings, - subtitle: AppLocalizations.of(context)!.dnsServerSettingsDescription, - onTap: () => navigate(const DnsServerSettingsScreen()), - icon: Icons.settings, - ), - CustomListTile( - title: AppLocalizations.of(context)!.dnsCacheConfig, - subtitle: AppLocalizations.of(context)!.dnsCacheConfigDescription, - onTap: () => navigate(const CacheConfigDnsScreen()), - icon: Icons.storage_rounded, - ), - ], - ); - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.dnsConfigNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - } - void clearCache() async { final result = await clearDnsCache(context, serversProvider.selectedServer!); if (result == true) { @@ -165,6 +81,7 @@ class _DnsSettingsState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.dnsSettings), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, actions: [ PopupMenuButton( itemBuilder: (context) => [ @@ -200,7 +117,96 @@ class _DnsSettingsState extends State { const SizedBox(width: 10) ], ), - body: generateBody(), + body: Builder( + builder: (context) { + switch (dnsProvider.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingDnsConfig, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ) + ); + + case LoadStatus.loaded: + return ListView( + children: [ + CustomListTile( + title: AppLocalizations.of(context)!.upstreamDns, + subtitle: AppLocalizations.of(context)!.upstreamDnsDescription, + onTap: () => navigate(const UpstreamDnsScreen()), + icon: Icons.upload_rounded, + ), + CustomListTile( + title: AppLocalizations.of(context)!.bootstrapDns, + subtitle: AppLocalizations.of(context)!.bootstrapDnsDescription, + onTap: () => navigate(const BootstrapDnsScreen()), + icon: Icons.dns_rounded, + ), + CustomListTile( + title: AppLocalizations.of(context)!.privateReverseDnsServers, + subtitle: AppLocalizations.of(context)!.privateReverseDnsDescription, + onTap: () => navigate(const PrivateReverseDnsServersScreen()), + icon: Icons.person_rounded, + ), + CustomListTile( + title: AppLocalizations.of(context)!.dnsServerSettings, + subtitle: AppLocalizations.of(context)!.dnsServerSettingsDescription, + onTap: () => navigate(const DnsServerSettingsScreen()), + icon: Icons.settings, + ), + CustomListTile( + title: AppLocalizations.of(context)!.dnsCacheConfig, + subtitle: AppLocalizations.of(context)!.dnsCacheConfigDescription, + onTap: () => navigate(const CacheConfigDnsScreen()), + icon: Icons.storage_rounded, + ), + ], + ); + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.dnsConfigNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ) ); } } \ No newline at end of file diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index 9169408..b8481a0 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -8,6 +8,7 @@ import 'package:adguard_home_manager/widgets/custom_radio_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -99,6 +100,7 @@ class _DnsServerSettingsScreenState extends State { Widget build(BuildContext context) { final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; void saveData() async { ProcessModal processModal = ProcessModal(context: context); @@ -153,6 +155,7 @@ class _DnsServerSettingsScreenState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.dnsServerSettings), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, actions: [ IconButton( onPressed: isDataValid == true diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index eb0f16a..2373d44 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -90,6 +91,8 @@ class _PrivateReverseDnsServersScreenState extends State(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void saveData() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); @@ -134,6 +137,7 @@ class _PrivateReverseDnsServersScreenState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => CommentModal( onConfirm: (value) { setState(() { @@ -123,6 +125,7 @@ class _UpstreamDnsScreenState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => CommentModal( comment: item['comment'], onConfirm: (value) { @@ -174,6 +177,7 @@ class _UpstreamDnsScreenState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.upstreamDns), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, actions: [ IconButton( onPressed: validValues == true diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index fda731e..cd4c8bd 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -11,6 +11,7 @@ import 'package:adguard_home_manager/screens/settings/dns_rewrites/delete_dns_re import 'package:adguard_home_manager/screens/settings/dns_rewrites/dns_rewrite_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/rewrite_rules_provider.dart'; @@ -129,193 +130,195 @@ class _DnsRewritesScreenState extends State { } } - Widget generateBody() { - switch (rewriteRulesProvider.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingRewriteRules, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - if (rewriteRulesProvider.rewriteRules!.isNotEmpty) { - return RefreshIndicator( - onRefresh: () async { - final result = await rewriteRulesProvider.fetchRules(); - if (result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.rewriteRulesNotLoaded, - color: Colors.red - ); - } - }, - child: ListView.builder( - controller: scrollController, - padding: const EdgeInsets.only(top: 0), - itemCount: rewriteRulesProvider.rewriteRules!.length, - itemBuilder: (context, index) => Card( - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: InkWell( - onTap: () => { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => DnsRewriteModal( - onConfirm: updateRewriteRule, - dialog: true, - rule: rewriteRulesProvider.rewriteRules![index], - onDelete: (rule) => showDialog( - context: context, - builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(rule) - ) - ), - ), - ) - } - else { - showModalBottomSheet( - context: context, - builder: (context) => DnsRewriteModal( - onConfirm: updateRewriteRule, - dialog: false, - rule: rewriteRulesProvider.rewriteRules![index], - onDelete: (rule) => showDialog( - context: context, - builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(rule) - ) - ), - ), - backgroundColor: Colors.transparent, - isScrollControlled: true, - ) - } - }, - borderRadius: BorderRadius.circular(10), - child: Padding( - padding: const EdgeInsets.only( - left: 16, top: 16, bottom: 16, right: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.domain}: ", - style: TextStyle( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Text( - rewriteRulesProvider.rewriteRules![index].domain, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - const SizedBox(height: 3), - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.answer}: ", - style: TextStyle( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Text( - rewriteRulesProvider.rewriteRules![index].answer, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ], - ), - Icon( - Icons.keyboard_arrow_right_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ) - ], - ), - ), - ), - ) - ), - ); - } - else { - return Center( - child: Text( - AppLocalizations.of(context)!.noRewriteRules, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ); - } - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.rewriteRulesNotLoaded, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - } - return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.dnsRewrites), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, centerTitle: false, ), body: Stack( children: [ - generateBody(), + Builder( + builder: (context) { + switch (rewriteRulesProvider.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingRewriteRules, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + if (rewriteRulesProvider.rewriteRules!.isNotEmpty) { + return RefreshIndicator( + onRefresh: () async { + final result = await rewriteRulesProvider.fetchRules(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.rewriteRulesNotLoaded, + color: Colors.red + ); + } + }, + child: ListView.builder( + controller: scrollController, + padding: const EdgeInsets.only(top: 0), + itemCount: rewriteRulesProvider.rewriteRules!.length, + itemBuilder: (context, index) => Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: InkWell( + onTap: () => { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => DnsRewriteModal( + onConfirm: updateRewriteRule, + dialog: true, + rule: rewriteRulesProvider.rewriteRules![index], + onDelete: (rule) => showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rule) + ) + ), + ), + ) + } + else { + showModalBottomSheet( + context: context, + useRootNavigator: true, + builder: (context) => DnsRewriteModal( + onConfirm: updateRewriteRule, + dialog: false, + rule: rewriteRulesProvider.rewriteRules![index], + onDelete: (rule) => showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rule) + ) + ), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + ) + } + }, + borderRadius: BorderRadius.circular(10), + child: Padding( + padding: const EdgeInsets.only( + left: 16, top: 16, bottom: 16, right: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.domain}: ", + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Text( + rewriteRulesProvider.rewriteRules![index].domain, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + const SizedBox(height: 3), + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.answer}: ", + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Text( + rewriteRulesProvider.rewriteRules![index].answer, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ], + ), + Icon( + Icons.keyboard_arrow_right_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ) + ], + ), + ), + ), + ) + ), + ); + } + else { + return Center( + child: Text( + AppLocalizations.of(context)!.noRewriteRules, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ); + } + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.rewriteRulesNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ), AnimatedPositioned( duration: const Duration(milliseconds: 100), curve: Curves.easeInOut, @@ -344,6 +347,7 @@ class _DnsRewritesScreenState extends State { else { showModalBottomSheet( context: context, + useRootNavigator: true, builder: (context) => DnsRewriteModal( onConfirm: addDnsRewrite, dialog: false, diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index de75918..3c4744c 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -14,6 +14,7 @@ import 'package:adguard_home_manager/screens/settings/encryption/encryption_func import 'package:adguard_home_manager/screens/settings/encryption/error_message.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/base64.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -272,379 +273,10 @@ class _EncryptionSettingsWidgetState extends State { } } - Widget generateBody() { - switch (loadStatus) { - case 0: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingEncryptionSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ) - ); - - case 1: - return ListView( - children: [ - EncryptionMasterSwitch( - value: enabled, - onChange: (value) { - setState(() => enabled = value); - onEditValidate(); - } - ), - SectionLabel( - label: AppLocalizations.of(context)!.serverConfiguration, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), - ), - EncryptionTextField( - enabled: enabled, - controller: domainNameController, - icon: Icons.link_rounded, - onChanged: (value) { - setState(() => domainError = validateDomain(context, value)); - onEditValidate(); - }, - errorText: domainError, - label: AppLocalizations.of(context)!.domainName, - helperText: AppLocalizations.of(context)!.domainNameDescription, - ), - const SizedBox(height: 10), - CustomSwitchListTile( - value: redirectHttps, - onChanged: (value) { - setState(() => redirectHttps = value); - onEditValidate(); - }, - title: AppLocalizations.of(context)!.redirectHttps, - disabled: !enabled, - ), - const SizedBox(height: 10), - Wrap( - children: [ - FractionallySizedBox( - widthFactor: width > 900 ? 0.33 : 1, - child: EncryptionTextField( - enabled: enabled, - controller: httpsPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => httpsPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: httpsPortError, - label: AppLocalizations.of(context)!.httpsPort, - keyboardType: TextInputType.number, - ), - ), - Padding( - padding: width <= 900 - ? const EdgeInsets.symmetric(vertical: 24) - : const EdgeInsets.all(0), - child: FractionallySizedBox( - widthFactor: width > 900 ? 0.33 : 1, - child: EncryptionTextField( - enabled: enabled, - controller: tlsPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => tlsPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: tlsPortError, - label: AppLocalizations.of(context)!.tlsPort, - keyboardType: TextInputType.number, - ), - ), - ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.33 : 1, - child: EncryptionTextField( - enabled: enabled, - controller: dnsOverQuicPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => dnsOverQuicPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: dnsOverQuicPortError, - label: AppLocalizations.of(context)!.dnsOverQuicPort, - keyboardType: TextInputType.number, - ), - ), - ], - ), - SectionLabel( - label: AppLocalizations.of(context)!.certificates, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), - ), - Card( - margin: const EdgeInsets.symmetric(horizontal: 16), - child: Padding( - padding: const EdgeInsets.all(20), - child: Row( - children: [ - Icon( - Icons.info_rounded, - color: Theme.of(context).listTileTheme.iconColor, - ), - const SizedBox(width: 20), - Flexible( - child: Text( - AppLocalizations.of(context)!.certificatesDescription, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - ), - ) - ) - ], - ), - ), - ), - const SizedBox(height: 20), - RadioListTile( - value: 0, - groupValue: certificateOption, - onChanged: enabled == true - ? (value) { - setState(() => certificateOption = int.parse(value.toString())); - onEditValidate(); - } - : null, - title: Text( - AppLocalizations.of(context)!.certificateFilePath, - style: const TextStyle( - fontWeight: FontWeight.normal - ), - ), - ), - RadioListTile( - value: 1, - groupValue: certificateOption, - onChanged: enabled == true - ? (value) { - setState(() => certificateOption = int.parse(value.toString())); - onEditValidate(); - } - : null, - title: Text( - AppLocalizations.of(context)!.pasteCertificateContent, - style: const TextStyle( - fontWeight: FontWeight.normal - ), - ), - ), - const SizedBox(height: 10), - if (certificateOption == 0) EncryptionTextField( - enabled: enabled, - controller: certificatePathController, - icon: Icons.description_rounded, - onChanged: (value) { - setState(() => certificatePathError = validatePath(context, value)); - onEditValidate(); - }, - label: AppLocalizations.of(context)!.certificatePath, - errorText: certificatePathError, - ), - if (certificateOption == 1) EncryptionTextField( - enabled: enabled, - controller: certificateContentController, - icon: Icons.description_rounded, - onChanged: (value) { - setState(() => certificateContentError = validateCertificate(context, value)); - onEditValidate(); - }, - label: AppLocalizations.of(context)!.certificateContent, - errorText: certificateContentError, - multiline: true, - keyboardType: TextInputType.multiline, - ), - if (certKeyValid != null && (certificateContentController.text != '' || certificatePathController.text != '')) ...[ - const SizedBox(height: 20), - if (certKeyValid!['valid_chain'] != null) ...[ - Status( - valid: certKeyValid!['valid_chain'], - label: certKeyValid!['valid_chain'] == true - ? AppLocalizations.of(context)!.validCertificateChain - : AppLocalizations.of(context)!.invalidCertificateChain, - ), - const SizedBox(height: 10), - ], - if (certKeyValid!['subject'] != null) ...[ - Status( - valid: true, - label: "${AppLocalizations.of(context)!.subject}: ${certKeyValid!['subject']}" - ), - const SizedBox(height: 10), - ], - if (certKeyValid!['issuer'] != null) ...[ - Status( - valid: true, - label: "${AppLocalizations.of(context)!.issuer}: ${certKeyValid!['issuer']}" - ), - const SizedBox(height: 10), - ], - if (certKeyValid!['not_after'] != null) ...[ - Status( - valid: true, - label: "${AppLocalizations.of(context)!.expirationDate}: ${certKeyValid!['not_after']}" - ), - const SizedBox(height: 10), - ], - if (certKeyValid!['dns_names'] != null) ...[ - Status( - valid: true, - label: "${AppLocalizations.of(context)!.hostNames}: ${certKeyValid!['dns_names'].join(', ')}" - ), - const SizedBox(height: 10), - ], - ], - SectionLabel( - label: AppLocalizations.of(context)!.privateKey, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), - ), - RadioListTile( - value: 0, - groupValue: privateKeyOption, - onChanged: enabled == true - ? (value) { - setState(() => privateKeyOption = int.parse(value.toString())); - onEditValidate(); - } - : null, - title: Text( - AppLocalizations.of(context)!.privateKeyFile, - style: const TextStyle( - fontWeight: FontWeight.normal - ), - ), - ), - RadioListTile( - value: 1, - groupValue: privateKeyOption, - onChanged: enabled == true - ? (value) { - setState(() => privateKeyOption = int.parse(value.toString())); - onEditValidate(); - } - : null, - title: Text( - AppLocalizations.of(context)!.pastePrivateKey, - style: const TextStyle( - fontWeight: FontWeight.normal - ), - ), - ), - if (privateKeyOption == 0) const SizedBox(height: 10), - if (privateKeyOption == 1) ...[ - CustomSwitchListTile( - value: usePreviouslySavedKey, - onChanged: (value) => setState(() => usePreviouslySavedKey = value), - title: AppLocalizations.of(context)!.usePreviousKey, - ), - const SizedBox(height: 10) - ], - if (privateKeyOption == 0) EncryptionTextField( - enabled: enabled, - controller: privateKeyPathController, - icon: Icons.description_rounded, - onChanged: (value) { - setState(() => privateKeyPathError = validatePath(context, value)); - onEditValidate(); - }, - label: AppLocalizations.of(context)!.privateKeyPath, - errorText: privateKeyPathError, - ), - if (privateKeyOption == 1) EncryptionTextField( - enabled: enabled == true - ? !usePreviouslySavedKey - : false, - controller: pastePrivateKeyController, - icon: Icons.description_rounded, - onChanged: (value) { - setState(() => pastePrivateKeyError = validatePrivateKey(context, value)); - onEditValidate(); - }, - label: AppLocalizations.of(context)!.pastePrivateKey, - errorText: pastePrivateKeyError, - keyboardType: TextInputType.multiline, - multiline: true, - ), - const SizedBox(height: 20), - if (certKeyValid != null && (privateKeyPathController.text != '' || pastePrivateKeyController.text != '' || usePreviouslySavedKey == true)) ...[ - if (certKeyValid!['valid_key'] != null) ...[ - Status( - valid: certKeyValid!['valid_key'], - label: certKeyValid!['valid_key'] == true - ? AppLocalizations.of(context)!.validPrivateKey - : AppLocalizations.of(context)!.invalidPrivateKey, - ), - const SizedBox(height: 10) - ], - if (certKeyValid!['valid_pair'] != null && certKeyValid!['valid_pair'] == false) ...[ - Status( - valid: false, - label: AppLocalizations.of(context)!.keysNotMatch, - ), - const SizedBox(height: 10) - ], - if (certKeyValid!['key_type'] != null) ...[ - Status( - valid: true, - label: "${AppLocalizations.of(context)!.keyType}: ${certKeyValid!['key_type']}" - ), - const SizedBox(height: 10), - ], - const SizedBox(height: 10) - ] - ], - ); - - case 2: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.encryptionSettingsNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - } - return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.encryptionSettings), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, centerTitle: false, actions: [ IconButton( @@ -668,7 +300,377 @@ class _EncryptionSettingsWidgetState extends State { const SizedBox(width: 10), ], ), - body: generateBody(), + body: Builder( + builder: (context) { + switch (loadStatus) { + case 0: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingEncryptionSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ) + ); + + case 1: + return ListView( + children: [ + EncryptionMasterSwitch( + value: enabled, + onChange: (value) { + setState(() => enabled = value); + onEditValidate(); + } + ), + SectionLabel( + label: AppLocalizations.of(context)!.serverConfiguration, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + ), + EncryptionTextField( + enabled: enabled, + controller: domainNameController, + icon: Icons.link_rounded, + onChanged: (value) { + setState(() => domainError = validateDomain(context, value)); + onEditValidate(); + }, + errorText: domainError, + label: AppLocalizations.of(context)!.domainName, + helperText: AppLocalizations.of(context)!.domainNameDescription, + ), + const SizedBox(height: 10), + CustomSwitchListTile( + value: redirectHttps, + onChanged: (value) { + setState(() => redirectHttps = value); + onEditValidate(); + }, + title: AppLocalizations.of(context)!.redirectHttps, + disabled: !enabled, + ), + const SizedBox(height: 10), + Wrap( + children: [ + FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: httpsPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => httpsPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: httpsPortError, + label: AppLocalizations.of(context)!.httpsPort, + keyboardType: TextInputType.number, + ), + ), + Padding( + padding: width <= 900 + ? const EdgeInsets.symmetric(vertical: 24) + : const EdgeInsets.all(0), + child: FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: tlsPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => tlsPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: tlsPortError, + label: AppLocalizations.of(context)!.tlsPort, + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: dnsOverQuicPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => dnsOverQuicPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: dnsOverQuicPortError, + label: AppLocalizations.of(context)!.dnsOverQuicPort, + keyboardType: TextInputType.number, + ), + ), + ], + ), + SectionLabel( + label: AppLocalizations.of(context)!.certificates, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 16), + child: Padding( + padding: const EdgeInsets.all(20), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).listTileTheme.iconColor, + ), + const SizedBox(width: 20), + Flexible( + child: Text( + AppLocalizations.of(context)!.certificatesDescription, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ) + ) + ], + ), + ), + ), + const SizedBox(height: 20), + RadioListTile( + value: 0, + groupValue: certificateOption, + onChanged: enabled == true + ? (value) { + setState(() => certificateOption = int.parse(value.toString())); + onEditValidate(); + } + : null, + title: Text( + AppLocalizations.of(context)!.certificateFilePath, + style: const TextStyle( + fontWeight: FontWeight.normal + ), + ), + ), + RadioListTile( + value: 1, + groupValue: certificateOption, + onChanged: enabled == true + ? (value) { + setState(() => certificateOption = int.parse(value.toString())); + onEditValidate(); + } + : null, + title: Text( + AppLocalizations.of(context)!.pasteCertificateContent, + style: const TextStyle( + fontWeight: FontWeight.normal + ), + ), + ), + const SizedBox(height: 10), + if (certificateOption == 0) EncryptionTextField( + enabled: enabled, + controller: certificatePathController, + icon: Icons.description_rounded, + onChanged: (value) { + setState(() => certificatePathError = validatePath(context, value)); + onEditValidate(); + }, + label: AppLocalizations.of(context)!.certificatePath, + errorText: certificatePathError, + ), + if (certificateOption == 1) EncryptionTextField( + enabled: enabled, + controller: certificateContentController, + icon: Icons.description_rounded, + onChanged: (value) { + setState(() => certificateContentError = validateCertificate(context, value)); + onEditValidate(); + }, + label: AppLocalizations.of(context)!.certificateContent, + errorText: certificateContentError, + multiline: true, + keyboardType: TextInputType.multiline, + ), + if (certKeyValid != null && (certificateContentController.text != '' || certificatePathController.text != '')) ...[ + const SizedBox(height: 20), + if (certKeyValid!['valid_chain'] != null) ...[ + Status( + valid: certKeyValid!['valid_chain'], + label: certKeyValid!['valid_chain'] == true + ? AppLocalizations.of(context)!.validCertificateChain + : AppLocalizations.of(context)!.invalidCertificateChain, + ), + const SizedBox(height: 10), + ], + if (certKeyValid!['subject'] != null) ...[ + Status( + valid: true, + label: "${AppLocalizations.of(context)!.subject}: ${certKeyValid!['subject']}" + ), + const SizedBox(height: 10), + ], + if (certKeyValid!['issuer'] != null) ...[ + Status( + valid: true, + label: "${AppLocalizations.of(context)!.issuer}: ${certKeyValid!['issuer']}" + ), + const SizedBox(height: 10), + ], + if (certKeyValid!['not_after'] != null) ...[ + Status( + valid: true, + label: "${AppLocalizations.of(context)!.expirationDate}: ${certKeyValid!['not_after']}" + ), + const SizedBox(height: 10), + ], + if (certKeyValid!['dns_names'] != null) ...[ + Status( + valid: true, + label: "${AppLocalizations.of(context)!.hostNames}: ${certKeyValid!['dns_names'].join(', ')}" + ), + const SizedBox(height: 10), + ], + ], + SectionLabel( + label: AppLocalizations.of(context)!.privateKey, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + ), + RadioListTile( + value: 0, + groupValue: privateKeyOption, + onChanged: enabled == true + ? (value) { + setState(() => privateKeyOption = int.parse(value.toString())); + onEditValidate(); + } + : null, + title: Text( + AppLocalizations.of(context)!.privateKeyFile, + style: const TextStyle( + fontWeight: FontWeight.normal + ), + ), + ), + RadioListTile( + value: 1, + groupValue: privateKeyOption, + onChanged: enabled == true + ? (value) { + setState(() => privateKeyOption = int.parse(value.toString())); + onEditValidate(); + } + : null, + title: Text( + AppLocalizations.of(context)!.pastePrivateKey, + style: const TextStyle( + fontWeight: FontWeight.normal + ), + ), + ), + if (privateKeyOption == 0) const SizedBox(height: 10), + if (privateKeyOption == 1) ...[ + CustomSwitchListTile( + value: usePreviouslySavedKey, + onChanged: (value) => setState(() => usePreviouslySavedKey = value), + title: AppLocalizations.of(context)!.usePreviousKey, + ), + const SizedBox(height: 10) + ], + if (privateKeyOption == 0) EncryptionTextField( + enabled: enabled, + controller: privateKeyPathController, + icon: Icons.description_rounded, + onChanged: (value) { + setState(() => privateKeyPathError = validatePath(context, value)); + onEditValidate(); + }, + label: AppLocalizations.of(context)!.privateKeyPath, + errorText: privateKeyPathError, + ), + if (privateKeyOption == 1) EncryptionTextField( + enabled: enabled == true + ? !usePreviouslySavedKey + : false, + controller: pastePrivateKeyController, + icon: Icons.description_rounded, + onChanged: (value) { + setState(() => pastePrivateKeyError = validatePrivateKey(context, value)); + onEditValidate(); + }, + label: AppLocalizations.of(context)!.pastePrivateKey, + errorText: pastePrivateKeyError, + keyboardType: TextInputType.multiline, + multiline: true, + ), + const SizedBox(height: 20), + if (certKeyValid != null && (privateKeyPathController.text != '' || pastePrivateKeyController.text != '' || usePreviouslySavedKey == true)) ...[ + if (certKeyValid!['valid_key'] != null) ...[ + Status( + valid: certKeyValid!['valid_key'], + label: certKeyValid!['valid_key'] == true + ? AppLocalizations.of(context)!.validPrivateKey + : AppLocalizations.of(context)!.invalidPrivateKey, + ), + const SizedBox(height: 10) + ], + if (certKeyValid!['valid_pair'] != null && certKeyValid!['valid_pair'] == false) ...[ + Status( + valid: false, + label: AppLocalizations.of(context)!.keysNotMatch, + ), + const SizedBox(height: 10) + ], + if (certKeyValid!['key_type'] != null) ...[ + Status( + valid: true, + label: "${AppLocalizations.of(context)!.keyType}: ${certKeyValid!['key_type']}" + ), + const SizedBox(height: 10), + ], + const SizedBox(height: 10) + ] + ], + ); + + case 2: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.encryptionSettingsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ) ); } } \ No newline at end of file diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index 9ead014..cef6a8f 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -13,6 +13,7 @@ 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/check_app_updates.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/functions/app_update_download_link.dart'; @@ -34,6 +35,8 @@ class _GeneralSettingsState extends State { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + Future updateSettings({ required bool newStatus, required Future Function(bool) function @@ -113,6 +116,7 @@ class _GeneralSettingsState extends State { return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.generalSettings), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, ), body: ListView( children: [ diff --git a/lib/screens/settings/general_settings/reorderable_top_items_home.dart b/lib/screens/settings/general_settings/reorderable_top_items_home.dart index 75ad9cc..b649ff5 100644 --- a/lib/screens/settings/general_settings/reorderable_top_items_home.dart +++ b/lib/screens/settings/general_settings/reorderable_top_items_home.dart @@ -1,5 +1,6 @@ // ignore_for_file: use_build_context_synchronously +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -91,6 +92,8 @@ class _ReorderableTopItemsHomeState extends State { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + Widget tile(HomeTopItems title) { switch (title) { case HomeTopItems.queriedDomains: @@ -177,6 +180,7 @@ class _ReorderableTopItemsHomeState extends State { child: Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.topItemsOrder), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, actions: [ IconButton( onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList) diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 461b6a6..9ef8359 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -1,5 +1,6 @@ // ignore_for_file: use_build_context_synchronously +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -70,6 +71,8 @@ class _SafeSearchSettingsScreenState extends State { final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void saveConfig() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingSettings); @@ -104,167 +107,10 @@ class _SafeSearchSettingsScreenState extends State { } } - Widget body() { - switch (statusProvider.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingSafeSearchSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - return RefreshIndicator( - onRefresh: requestSafeSearchSettings, - child: ListView( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 16, - left: 16, - right: 16, - bottom: 8 - ), - child: Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(28), - child: InkWell( - borderRadius: BorderRadius.circular(28), - onTap: () => setState(() => generalEnabled = !generalEnabled), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 12 - ), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(28) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.enableSafeSearch, - style: const TextStyle( - fontSize: 18 - ), - ), - Switch( - value: generalEnabled, - onChanged: (value) => setState(() => generalEnabled = value) - ) - ], - ), - ), - ), - ), - ), - CustomCheckboxListTile( - value: bingEnabled, - onChanged: (value) => setState(() => bingEnabled = value), - title: "Bing", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 - ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: duckduckgoEnabled, - onChanged: (value) => setState(() => duckduckgoEnabled = value), - title: "DuckDuckGo", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 - ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: googleEnabled, - onChanged: (value) => setState(() => googleEnabled = value), - title: "Google", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 - ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: pixabayEnabled, - onChanged: (value) => setState(() => pixabayEnabled = value), - title: "Pixabay", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 - ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: yandexEnabled, - onChanged: (value) => setState(() => yandexEnabled = value), - title: "Yandex", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 - ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: youtubeEnabled, - onChanged: (value) => setState(() => youtubeEnabled = value), - title: "YouTube", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 - ), - disabled: !generalEnabled, - ), - ], - ), - ); - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.safeSearchSettingsNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - - default: - return const SizedBox(); - } - } - return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.safeSearchSettings), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, centerTitle: false, actions: [ IconButton( @@ -277,7 +123,165 @@ class _SafeSearchSettingsScreenState extends State { const SizedBox(width: 8) ], ), - body: body(), + body: Builder( + builder: (context) { + switch (statusProvider.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingSafeSearchSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + return RefreshIndicator( + onRefresh: requestSafeSearchSettings, + child: ListView( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 16, + left: 16, + right: 16, + bottom: 8 + ), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + borderRadius: BorderRadius.circular(28), + onTap: () => setState(() => generalEnabled = !generalEnabled), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 12 + ), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(28) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.enableSafeSearch, + style: const TextStyle( + fontSize: 18 + ), + ), + Switch( + value: generalEnabled, + onChanged: (value) => setState(() => generalEnabled = value) + ) + ], + ), + ), + ), + ), + ), + CustomCheckboxListTile( + value: bingEnabled, + onChanged: (value) => setState(() => bingEnabled = value), + title: "Bing", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomCheckboxListTile( + value: duckduckgoEnabled, + onChanged: (value) => setState(() => duckduckgoEnabled = value), + title: "DuckDuckGo", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomCheckboxListTile( + value: googleEnabled, + onChanged: (value) => setState(() => googleEnabled = value), + title: "Google", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomCheckboxListTile( + value: pixabayEnabled, + onChanged: (value) => setState(() => pixabayEnabled = value), + title: "Pixabay", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomCheckboxListTile( + value: yandexEnabled, + onChanged: (value) => setState(() => yandexEnabled = value), + title: "Yandex", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + CustomCheckboxListTile( + value: youtubeEnabled, + onChanged: (value) => setState(() => youtubeEnabled = value), + title: "YouTube", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, + ), + ], + ), + ); + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.safeSearchSettingsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + + default: + return const SizedBox(); + } + }, + ) ); } } \ No newline at end of file diff --git a/lib/screens/settings/server_info/server_info.dart b/lib/screens/settings/server_info/server_info.dart index a6a9fcc..2a51a16 100644 --- a/lib/screens/settings/server_info/server_info.dart +++ b/lib/screens/settings/server_info/server_info.dart @@ -1,4 +1,5 @@ import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -66,121 +67,123 @@ class _ServerInformationWidgetState extends State { @override Widget build(BuildContext context) { - Widget generateBody() { - switch (serverInfo.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.loadingServerInfo, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - return ListView( - children: [ - CustomListTile( - title: AppLocalizations.of(context)!.dnsAddresses, - subtitle: AppLocalizations.of(context)!.seeDnsAddresses, - onTap: () { - showModal( - context: context, - builder: (context) => DnsAddressesModal( - dnsAddresses: serverInfo.data!.dnsAddresses - ) - ); - }, - ), - CustomListTile( - title: AppLocalizations.of(context)!.dnsPort, - subtitle: serverInfo.data!.dnsPort.toString(), - ), - CustomListTile( - title: AppLocalizations.of(context)!.httpPort, - subtitle: serverInfo.data!.httpPort.toString(), - ), - CustomListTile( - title: AppLocalizations.of(context)!.protectionEnabled, - subtitle: serverInfo.data!.protectionEnabled == true - ? AppLocalizations.of(context)!.yes - : AppLocalizations.of(context)!.no, - ), - CustomListTile( - title: AppLocalizations.of(context)!.dhcpAvailable, - subtitle: serverInfo.data!.dhcpAvailable == true - ? AppLocalizations.of(context)!.yes - : AppLocalizations.of(context)!.no, - ), - CustomListTile( - title: AppLocalizations.of(context)!.serverRunning, - subtitle: serverInfo.data!.running == true - ? AppLocalizations.of(context)!.yes - : AppLocalizations.of(context)!.no, - ), - CustomListTile( - title: AppLocalizations.of(context)!.serverVersion, - subtitle: serverInfo.data!.version, - ), - CustomListTile( - title: AppLocalizations.of(context)!.serverLanguage, - subtitle: serverInfo.data!.language, - ), - ] - ); - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.serverInfoNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - } - + final width = MediaQuery.of(context).size.width; return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.serverInformation), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, centerTitle: false, ), - body: generateBody() + body: Builder( + builder: (context) { + switch (serverInfo.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.loadingServerInfo, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + return ListView( + children: [ + CustomListTile( + title: AppLocalizations.of(context)!.dnsAddresses, + subtitle: AppLocalizations.of(context)!.seeDnsAddresses, + onTap: () { + showModal( + context: context, + builder: (context) => DnsAddressesModal( + dnsAddresses: serverInfo.data!.dnsAddresses + ) + ); + }, + ), + CustomListTile( + title: AppLocalizations.of(context)!.dnsPort, + subtitle: serverInfo.data!.dnsPort.toString(), + ), + CustomListTile( + title: AppLocalizations.of(context)!.httpPort, + subtitle: serverInfo.data!.httpPort.toString(), + ), + CustomListTile( + title: AppLocalizations.of(context)!.protectionEnabled, + subtitle: serverInfo.data!.protectionEnabled == true + ? AppLocalizations.of(context)!.yes + : AppLocalizations.of(context)!.no, + ), + CustomListTile( + title: AppLocalizations.of(context)!.dhcpAvailable, + subtitle: serverInfo.data!.dhcpAvailable == true + ? AppLocalizations.of(context)!.yes + : AppLocalizations.of(context)!.no, + ), + CustomListTile( + title: AppLocalizations.of(context)!.serverRunning, + subtitle: serverInfo.data!.running == true + ? AppLocalizations.of(context)!.yes + : AppLocalizations.of(context)!.no, + ), + CustomListTile( + title: AppLocalizations.of(context)!.serverVersion, + subtitle: serverInfo.data!.version, + ), + CustomListTile( + title: AppLocalizations.of(context)!.serverLanguage, + subtitle: serverInfo.data!.language, + ), + ] + ); + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.serverInfoNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ) ); } } \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 87d23ef..0f01b44 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -189,7 +189,9 @@ class SettingsWidget extends StatelessWidget { title: AppLocalizations.of(context)!.dnsSettings, subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, thisItem: 3, - screenToNavigate: const DnsSettings(), + screenToNavigate: DnsSettings( + splitView: twoColumns, + ), ), settingsTile( icon: Icons.security_rounded, From a0772032b49bb0ca1174d5b9d7eddc0ba85e7e88 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 02:49:34 +0100 Subject: [PATCH 346/676] Removed unused imports --- lib/screens/filters/add_button.dart | 1 - lib/screens/logs/log_tile.dart | 2 -- lib/screens/settings/dns/dns.dart | 1 - lib/widgets/bottom_nav_bar.dart | 2 -- lib/widgets/layout.dart | 1 - 5 files changed, 7 deletions(-) diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 7afccf0..e96bb51 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -2,7 +2,6 @@ import 'dart:io'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 40f3b0d..14c5262 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -34,8 +34,6 @@ class LogTile extends StatelessWidget { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - final width = MediaQuery.of(context).size.width; - Widget logStatusWidget({ required IconData icon, required Color color, diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 1aa63fd..7d0760b 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -1,6 +1,5 @@ // ignore_for_file: use_build_context_synchronously -import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index 0f16dcd..490138c 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -3,7 +3,6 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; -import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/app_screen.dart'; @@ -15,7 +14,6 @@ class BottomNavBar extends StatelessWidget { Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); List screens = serversProvider.selectedServer != null && serversProvider.apiClient != null ? screensServerConnected diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index 3513bb9..6104b6f 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -1,4 +1,3 @@ -import 'package:adguard_home_manager/widgets/bottom_nav_bar.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:go_router/go_router.dart'; From f966ab7fc59aa54f601511df0be239ab0b4c1bd8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 02:55:37 +0100 Subject: [PATCH 347/676] Removed base --- lib/base.dart | 116 -------------------------------------------- lib/main.dart | 132 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 88 insertions(+), 160 deletions(-) delete mode 100644 lib/base.dart diff --git a/lib/base.dart b/lib/base.dart deleted file mode 100644 index d57dd72..0000000 --- a/lib/base.dart +++ /dev/null @@ -1,116 +0,0 @@ -// ignore_for_file: use_build_context_synchronously, depend_on_referenced_packages - -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:animations/animations.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:provider/provider.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:flutter/services.dart'; - -import 'package:adguard_home_manager/widgets/bottom_nav_bar.dart'; -import 'package:adguard_home_manager/widgets/menu_bar.dart'; -import 'package:adguard_home_manager/widgets/update_modal.dart'; -import 'package:adguard_home_manager/widgets/navigation_rail.dart'; - -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/functions/check_app_updates.dart'; -import 'package:adguard_home_manager/functions/open_url.dart'; -import 'package:adguard_home_manager/models/app_screen.dart'; -import 'package:adguard_home_manager/config/app_screens.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; - -class Base extends StatefulWidget { - const Base({Key? key}) : super(key: key); - - @override - State createState() => _BaseState(); -} - -class _BaseState extends State with WidgetsBindingObserver { - int selectedScreen = 0; - - @override - void initState() { - WidgetsBinding.instance.addObserver(this); - - super.initState(); - - WidgetsBinding.instance.addPostFrameCallback((_) async { - final appConfigProvider = Provider.of(context, listen: false); - final result = await checkAppUpdates( - currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, - installationSource: appConfigProvider.installationSource, - setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, - isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), - ); - - if (result != null && appConfigProvider.doNotRememberVersion != result.tagName) { - await showDialog( - context: context, - builder: (context) => UpdateModal( - gitHubRelease: result, - onDownload: (link, version) => openUrl(link), - ), - ); - } - }); - } - - @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - final width = MediaQuery.of(context).size.width; - - List screens = serversProvider.selectedServer != null - ? screensServerConnected - : screensSelectServer; - - if (kDebugMode && dotenv.env['ENABLE_SENTRY'] == "true") { - Sentry.captureMessage("Debug mode"); - } - - return CustomMenuBar( - child: AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarColor: Colors.transparent, - statusBarBrightness: Theme.of(context).brightness == Brightness.light - ? Brightness.light - : Brightness.dark, - statusBarIconBrightness: Theme.of(context).brightness == Brightness.light - ? Brightness.dark - : Brightness.light, - systemNavigationBarColor: Theme.of(context).scaffoldBackgroundColor, - systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light - ? Brightness.dark - : Brightness.light, - ), - child: Scaffold( - body: Row( - children: [ - if (width > 900) const SideNavigationRail(), - Expanded( - child: PageTransitionSwitcher( - duration: const Duration(milliseconds: 200), - transitionBuilder: ( - (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( - animation: primaryAnimation, - secondaryAnimation: secondaryAnimation, - child: child, - ) - ), - child: SizedBox() - ), - ), - ], - ), - bottomNavigationBar: width <= 900 - ? const BottomNavBar() - : null, - ) - ), - ); - } -} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index fafb46e..1548e4a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,9 +2,10 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_displaymode/flutter_displaymode.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -15,6 +16,10 @@ import 'package:window_size/window_size.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/menu_bar.dart'; +import 'package:adguard_home_manager/functions/check_app_updates.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; +import 'package:adguard_home_manager/widgets/update_modal.dart'; import 'package:adguard_home_manager/routes/router.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -175,7 +180,7 @@ class Main extends StatefulWidget { State
createState() => _MainState(); } -class _MainState extends State
{ +class _MainState extends State
with WidgetsBindingObserver { List modes = []; DisplayMode? active; DisplayMode? preferred; @@ -195,54 +200,93 @@ class _MainState extends State
{ @override void initState() { displayMode(); + + WidgetsBinding.instance.addObserver(this); + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback((_) async { + final appConfigProvider = Provider.of(context, listen: false); + final result = await checkAppUpdates( + currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, + installationSource: appConfigProvider.installationSource, + setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, + isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), + ); + if (result != null && appConfigProvider.doNotRememberVersion != result.tagName && mounted) { + await showDialog( + context: context, + builder: (context) => UpdateModal( + gitHubRelease: result, + onDownload: (link, version) => openUrl(link), + ), + ); + } + }); } @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - - return DynamicColorBuilder( - builder: (lightDynamic, darkDynamic) => MaterialApp.router( - title: 'AdGuard Home Manager', - theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? lightTheme(lightDynamic) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]), - darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? darkTheme(darkDynamic) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]), - themeMode: appConfigProvider.selectedTheme, - debugShowCheckedModeBanner: false, - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - AppLocalizations.delegate, - ], - supportedLocales: const [ - Locale('en', ''), - Locale('es', ''), - Locale('zh', ''), - Locale('zh', 'CN'), - Locale('pl', ''), - Locale('tr', '') - ], - scaffoldMessengerKey: scaffoldMessengerKey, - builder: (context, child) { - return MediaQuery( - data: MediaQuery.of(context).copyWith( - textScaleFactor: !(Platform.isAndroid || Platform.isIOS) - ? 0.9 - : 1.0 - ), - child: child!, - ); - }, - routerConfig: goRouter, + + return AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarBrightness: Theme.of(context).brightness == Brightness.light + ? Brightness.light + : Brightness.dark, + statusBarIconBrightness: Theme.of(context).brightness == Brightness.light + ? Brightness.dark + : Brightness.light, + systemNavigationBarColor: Theme.of(context).scaffoldBackgroundColor, + systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light + ? Brightness.dark + : Brightness.light, + ), + child: DynamicColorBuilder( + builder: (lightDynamic, darkDynamic) => MaterialApp.router( + title: 'AdGuard Home Manager', + theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 + ? appConfigProvider.useDynamicColor == true + ? lightTheme(lightDynamic) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]), + darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 + ? appConfigProvider.useDynamicColor == true + ? darkTheme(darkDynamic) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]), + themeMode: appConfigProvider.selectedTheme, + debugShowCheckedModeBanner: false, + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + AppLocalizations.delegate, + ], + supportedLocales: const [ + Locale('en', ''), + Locale('es', ''), + Locale('zh', ''), + Locale('zh', 'CN'), + Locale('pl', ''), + Locale('tr', '') + ], + scaffoldMessengerKey: scaffoldMessengerKey, + builder: (context, child) { + return CustomMenuBar( + child: MediaQuery( + data: MediaQuery.of(context).copyWith( + textScaleFactor: !(Platform.isAndroid || Platform.isIOS) + ? 0.9 + : 1.0 + ), + child: child!, + ), + ); + }, + routerConfig: goRouter, + ), ), ); } From 5c50a486c42e7f69e2011315289737fc60fe765f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 03:04:45 +0100 Subject: [PATCH 348/676] Changes --- lib/routes/routes.dart | 56 +++++++++++++++++++++++++++++---- lib/widgets/bottom_nav_bar.dart | 15 --------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/lib/routes/routes.dart b/lib/routes/routes.dart index a216446..9a79603 100644 --- a/lib/routes/routes.dart +++ b/lib/routes/routes.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:adguard_home_manager/screens/home/home.dart'; @@ -8,6 +9,7 @@ import 'package:adguard_home_manager/screens/logs/logs.dart'; import 'package:adguard_home_manager/screens/settings/settings.dart'; import 'package:adguard_home_manager/widgets/layout.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/constants/routes_names.dart'; @@ -27,7 +29,14 @@ final List routes = [ GoRoute( parentNavigatorKey: homeNavigatorKey, path: RoutesNames.home, - builder: (context, state) => const Home(), + pageBuilder: (context, state) { + if (isDesktop(MediaQuery.of(context).size.width)) { + return const NoTransitionPage(child: Home()); + } + else { + return const MaterialPage(child: Home()); + } + }, ), ] ), @@ -37,7 +46,14 @@ final List routes = [ GoRoute( parentNavigatorKey: clientsNavigatorKey, path: RoutesNames.clients, - builder: (context, state) => const Clients(), + pageBuilder: (context, state) { + if (isDesktop(MediaQuery.of(context).size.width)) { + return const NoTransitionPage(child: Clients()); + } + else { + return const MaterialPage(child: Clients()); + } + }, ) ] ), @@ -47,7 +63,14 @@ final List routes = [ GoRoute( parentNavigatorKey: logsNavigatorKey, path: RoutesNames.logs, - builder: (context, state) => const Logs(), + pageBuilder: (context, state) { + if (isDesktop(MediaQuery.of(context).size.width)) { + return const NoTransitionPage(child: Logs()); + } + else { + return const MaterialPage(child: Logs()); + } + }, ) ] ), @@ -57,7 +80,14 @@ final List routes = [ GoRoute( parentNavigatorKey: filtersNavigatorKey, path: RoutesNames.filters, - builder: (context, state) => const Filters(), + pageBuilder: (context, state) { + if (isDesktop(MediaQuery.of(context).size.width)) { + return const NoTransitionPage(child: Filters()); + } + else { + return const MaterialPage(child: Filters()); + } + }, ) ] ), @@ -67,7 +97,14 @@ final List routes = [ GoRoute( parentNavigatorKey: settingsNavigatorKey, path: RoutesNames.settings, - builder: (context, state) => const Settings(), + pageBuilder: (context, state) { + if (isDesktop(MediaQuery.of(context).size.width)) { + return const NoTransitionPage(child: Settings()); + } + else { + return const MaterialPage(child: Settings()); + } + }, ) ] ), @@ -76,7 +113,14 @@ final List routes = [ routes: [ GoRoute( path: RoutesNames.connect, - builder: (context, state) => const Connect(), + pageBuilder: (context, state) { + if (isDesktop(MediaQuery.of(context).size.width)) { + return const NoTransitionPage(child: Connect()); + } + else { + return const MaterialPage(child: Connect()); + } + }, ) ] ), diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index 490138c..b5ff9df 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -82,21 +82,6 @@ class BottomNavBar extends StatelessWidget { ), label: translatedName(screen.name) )).toList(), - // onDestinationSelected: (value) { - // // Reset clients tab to 0 when changing screen - // if (value != 1) { - // appConfigProvider.setSelectedClientsTab(0); - // } - // // Reset logs filters when changing screen - // if (value != 2) { - // logsProvider.resetFilters(); - // } - // // Reset settings selected screen - // if (value != screens.length-1) { - // appConfigProvider.setSelectedSettingsScreen(screen: null); - // } - // appConfigProvider.setSelectedScreen(value); - // }, ); } } \ No newline at end of file From a8bd57904ceeef508500c37aa4a79348bb5d797b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 03:08:15 +0100 Subject: [PATCH 349/676] Changed size ring chart --- README.md | 2 ++ lib/screens/home/top_items.dart | 2 +- lib/widgets/custom_pie_chart.dart | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 864b3de..4128ac3 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,8 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [flutter dotenv](https://pub.dev/packages/flutter_dotenv) - [flutter reorderable list](https://pub.dev/packages/flutter_reorderable_list) - [pie chart](https://pub.dev/packages/pie_chart) +- [go router](https://pub.dev/packages/go_router) +- [flutter hooks](https://pub.dev/packages/flutter_hooks)
diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 06ef00e..ebf4e94 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -186,7 +186,7 @@ class _TopItemsState extends State { if (widget.data.isNotEmpty && width <= 700) ...[ if (_showChart) ...[ SizedBox( - height: 300, + height: 150, child: chart ), const SizedBox(height: 16), diff --git a/lib/widgets/custom_pie_chart.dart b/lib/widgets/custom_pie_chart.dart index 2968568..6af7e11 100644 --- a/lib/widgets/custom_pie_chart.dart +++ b/lib/widgets/custom_pie_chart.dart @@ -16,7 +16,6 @@ class CustomPieChart extends StatelessWidget { return PieChart( dataMap: data, animationDuration: const Duration(milliseconds: 800), - chartRadius: MediaQuery.of(context).size.width / 3, colorList: colors, initialAngleInDegree: 270, chartType: ChartType.ring, From 79cbb1beae00c20a66e1f07856efdd7608e59d8e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 13:59:36 +0100 Subject: [PATCH 350/676] Refactor code management modal --- lib/screens/home/combined_chart.dart | 117 +++-- lib/screens/home/fab.dart | 2 +- lib/screens/home/home.dart | 230 ++++----- lib/screens/home/management_modal.dart | 476 ------------------ .../home/management_modal/main_switch.dart | 266 ++++++++++ .../management_modal/management_modal.dart | 269 ++++++++++ .../home/management_modal/small_switch.dart | 65 +++ 7 files changed, 774 insertions(+), 651 deletions(-) delete mode 100644 lib/screens/home/management_modal.dart create mode 100644 lib/screens/home/management_modal/main_switch.dart create mode 100644 lib/screens/home/management_modal/management_modal.dart create mode 100644 lib/screens/home/management_modal/small_switch.dart diff --git a/lib/screens/home/combined_chart.dart b/lib/screens/home/combined_chart.dart index f781b7d..89519db 100644 --- a/lib/screens/home/combined_chart.dart +++ b/lib/screens/home/combined_chart.dart @@ -104,51 +104,6 @@ class CombinedHomeChart extends StatelessWidget { ) , ); - Widget legend({ - required String label, - required Color color, - required String primaryValue, - String? secondaryValue - }) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Flexible( - child: Text( - label, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: color - ), - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - primaryValue, - style: TextStyle( - color: color, - fontSize: 16, - fontWeight: FontWeight.w500 - ), - ), - if (secondaryValue != null) Text( - secondaryValue, - style: TextStyle( - fontSize: 10, - color: color - ), - ) - ], - ) - ], - ); - } - final hoursInterval = statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1; List dateTimes = []; @@ -193,28 +148,28 @@ class CombinedHomeChart extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - legend( + _Legend( label: data.totalQueries.label, color: data.totalQueries.color, primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", ), const SizedBox(height: 16), - if (data.blockedFilters != null) legend( + if (data.blockedFilters != null) _Legend( label: data.blockedFilters!.label, color: data.blockedFilters!.color, primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), - if (data.replacedSafeBrowsing != null) legend( + if (data.replacedSafeBrowsing != null) _Legend( label: data.replacedSafeBrowsing!.label, color: data.replacedSafeBrowsing!.color, primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), - if (data.replacedParental != null) legend( + if (data.replacedParental != null) _Legend( label: data.replacedParental!.label, color: data.replacedParental!.color, primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), @@ -259,28 +214,28 @@ class CombinedHomeChart extends StatelessWidget { ), ), const SizedBox(height: 16), - legend( + _Legend( label: data.totalQueries.label, color: data.totalQueries.color, primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", ), const SizedBox(height: 16), - if (data.blockedFilters != null) legend( + if (data.blockedFilters != null) _Legend( label: data.blockedFilters!.label, color: data.blockedFilters!.color, primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), - if (data.replacedSafeBrowsing != null) legend( + if (data.replacedSafeBrowsing != null) _Legend( label: data.replacedSafeBrowsing!.label, color: data.replacedSafeBrowsing!.color, primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), - if (data.replacedParental != null) legend( + if (data.replacedParental != null) _Legend( label: data.replacedParental!.label, color: data.replacedParental!.color, primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), @@ -302,4 +257,60 @@ class CombinedHomeChart extends StatelessWidget { return const SizedBox(); } } +} + +class _Legend extends StatelessWidget { + final String label; + final Color color; + final String primaryValue; + final String? secondaryValue; + + const _Legend({ + Key? key, + required this.label, + required this.color, + required this.primaryValue, + this.secondaryValue + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + child: Text( + label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: color + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + primaryValue, + style: TextStyle( + color: color, + fontSize: 16, + fontWeight: FontWeight.w500 + ), + ), + if (secondaryValue != null) Text( + secondaryValue!, + style: TextStyle( + fontSize: 10, + color: color + ), + ) + ], + ) + ], + ); + } } \ No newline at end of file diff --git a/lib/screens/home/fab.dart b/lib/screens/home/fab.dart index d0701cc..bd77be7 100644 --- a/lib/screens/home/fab.dart +++ b/lib/screens/home/fab.dart @@ -1,7 +1,7 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; -import 'package:adguard_home_manager/screens/home/management_modal.dart'; +import 'package:adguard_home_manager/screens/home/management_modal/management_modal.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index fcac0cc..293eef3 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -61,124 +61,6 @@ class _HomeState extends State { final width = MediaQuery.of(context).size.width; - Widget loading() { - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingStatus, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - } - - Widget loadError() { - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.errorLoadServerStatus, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - } - - List listItems() { - return [ - ServerStatusWidget(serverStatus: statusProvider.serverStatus!), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), - ), - ), - const SizedBox(height: 16), - - if (appConfigProvider.combinedChartHome == false) Wrap( - children: [ - FractionallySizedBox( - widthFactor: width > 700 ? 0.5 : 1, - child: HomeChart( - data: statusProvider.serverStatus!.stats.dnsQueries, - label: AppLocalizations.of(context)!.dnsQueries, - primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), - secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", - color: Colors.blue, - hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, - ), - ), - FractionallySizedBox( - widthFactor: width > 700 ? 0.5 : 1, - child: HomeChart( - data: statusProvider.serverStatus!.stats.blockedFiltering, - label: AppLocalizations.of(context)!.blockedFilters, - primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), - secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", - color: Colors.red, - hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, - ), - ), - FractionallySizedBox( - widthFactor: width > 700 ? 0.5 : 1, - child: HomeChart( - data: statusProvider.serverStatus!.stats.replacedSafebrowsing, - label: AppLocalizations.of(context)!.malwarePhishingBlocked, - primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), - secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", - color: Colors.green, - hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, - ), - ), - FractionallySizedBox( - widthFactor: width > 700 ? 0.5 : 1, - child: HomeChart( - data: statusProvider.serverStatus!.stats.replacedParental, - label: AppLocalizations.of(context)!.blockedAdultWebsites, - primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), - secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", - color: Colors.orange, - hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, - ), - ), - ], - ), - - if (appConfigProvider.combinedChartHome == true) const Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: CombinedHomeChart(), - ), - - TopItemsLists(order: appConfigProvider.homeTopItemsOrder), - ]; - } - return Scaffold( body: SafeArea( top: false, @@ -215,13 +97,119 @@ class _HomeState extends State { handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), if (statusProvider.loadStatus == LoadStatus.loading) SliverFillRemaining( - child: loading(), + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) ), if (statusProvider.loadStatus == LoadStatus.loaded) SliverList.list( - children: listItems() + children: [ + ServerStatusWidget(serverStatus: statusProvider.serverStatus!), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + ), + const SizedBox(height: 16), + + if (appConfigProvider.combinedChartHome == false) Wrap( + children: [ + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: statusProvider.serverStatus!.stats.dnsQueries, + label: AppLocalizations.of(context)!.dnsQueries, + primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + color: Colors.blue, + hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, + ), + ), + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: statusProvider.serverStatus!.stats.blockedFiltering, + label: AppLocalizations.of(context)!.blockedFilters, + primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + color: Colors.red, + hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, + ), + ), + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: statusProvider.serverStatus!.stats.replacedSafebrowsing, + label: AppLocalizations.of(context)!.malwarePhishingBlocked, + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + color: Colors.green, + hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, + ), + ), + FractionallySizedBox( + widthFactor: width > 700 ? 0.5 : 1, + child: HomeChart( + data: statusProvider.serverStatus!.stats.replacedParental, + label: AppLocalizations.of(context)!.blockedAdultWebsites, + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + color: Colors.orange, + hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, + ), + ), + ], + ), + + if (appConfigProvider.combinedChartHome == true) const Padding( + padding: EdgeInsets.symmetric(horizontal: 16), + child: CombinedHomeChart(), + ), + + TopItemsLists(order: appConfigProvider.homeTopItemsOrder), + ], ), if (statusProvider.loadStatus == LoadStatus.error) SliverFillRemaining( - child: loadError(), + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.errorLoadServerStatus, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) ), ], ) diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart deleted file mode 100644 index 9b94b58..0000000 --- a/lib/screens/home/management_modal.dart +++ /dev/null @@ -1,476 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'dart:async'; -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:expandable/expandable.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/functions/format_time.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; - -class ManagementModal extends StatefulWidget { - final bool dialog; - - const ManagementModal({ - Key? key, - required this.dialog - }) : super(key: key); - - @override - State createState() => _ManagementModalState(); -} - -class _ManagementModalState extends State with SingleTickerProviderStateMixin { - late AnimationController animationController; - late Animation animation; - final ExpandableController expandableController = ExpandableController(); - - final _chipsScrollController = ScrollController(); - - @override - void initState() { - expandableController.addListener(() async { - await Future.delayed(const Duration(milliseconds: 200)); - if (expandableController.value == false) { - animationController.animateTo(0); - } - else { - animationController.animateBack(1); - } - }); - - animationController = AnimationController( - duration: const Duration(milliseconds: 200), - vsync: this, - ) - ..addListener(() => setState(() => {})); - animation = Tween( - begin: 0.0, - end: 0.5, - ).animate(CurvedAnimation( - parent: animationController, - curve: Curves.easeInOut - )); - - super.initState(); - } - - @override - void dispose() { - animationController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - void updateBlocking({ - required bool value, - required String filter, - int? time - }) async { - final result = await statusProvider.updateBlocking( - block: filter, - newStatus: value, - time: time - ); - if (mounted && result != null) { - if (result != false) { - appConfigProvider.addLog(result); - } - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.invalidUsernamePassword, - color: Colors.red - ); - } - } - - void disableWithCountdown(int time) async { - updateBlocking(value: false, filter: 'general', time: time); - expandableController.toggle(); - } - - Widget mainSwitch() { - Widget topRow({required bool legacyMode}) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - if (legacyMode == false) ...[ - RotationTransition( - turns: animation, - child: Icon( - Icons.keyboard_arrow_down_rounded, - size: 26, - color: statusProvider.serverStatus!.generalEnabled == true - ? Theme.of(context).colorScheme.onSurfaceVariant - : Colors.grey, - ), - ), - const SizedBox(width: 8), - ], - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.allProtections, - style: const TextStyle( - fontSize: 18, - ), - ), - if (statusProvider.serverStatus!.timeGeneralDisabled > 0) ...[ - const SizedBox(height: 2), - if (statusProvider.currentDeadline != null) Text( - "${AppLocalizations.of(context)!.remainingTime}: ${formatRemainingSeconds(statusProvider.remainingTime)}" - ) - ] - ], - ), - ], - ), - Switch( - value: statusProvider.serverStatus!.generalEnabled, - onChanged: statusProvider.protectionsManagementProcess.contains('general') == false - ? (value) { - if (value == false && expandableController.expanded == true && legacyMode == false) { - expandableController.toggle(); - } - updateBlocking( - value: value, - filter: legacyMode == true ? 'general_legacy' : 'general' - ); - } : null, - ) - ] - ); - } - - Widget bottomRow() { - return Container( - height: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 50 : 40, - margin: const EdgeInsets.only(top: 8), - child: Scrollbar( - controller: _chipsScrollController, - thumbVisibility: Platform.isMacOS || Platform.isLinux || Platform.isWindows, - interactive: Platform.isMacOS || Platform.isLinux || Platform.isWindows, - thickness: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 8 : 0, - child: Padding( - padding: EdgeInsets.only( - bottom: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 16 : 0 - ), - child: ListView( - controller: _chipsScrollController, - scrollDirection: Axis.horizontal, - children: [ - ActionChip( - label: Text(AppLocalizations.of(context)!.seconds(30)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(29000) - : null, - ), - const SizedBox(width: 8), - ActionChip( - label: Text(AppLocalizations.of(context)!.minute(1)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(59000) - : null, - ), - const SizedBox(width: 8), - ActionChip( - label: Text(AppLocalizations.of(context)!.minutes(10)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(599000) - : null, - ), - const SizedBox(width: 8), - ActionChip( - label: Text(AppLocalizations.of(context)!.hour(1)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(3599000) - : null, - ), - const SizedBox(width: 8), - ActionChip( - label: Text(AppLocalizations.of(context)!.hours(24)), - onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true - ? () => disableWithCountdown(86399000) - : null, - ), - ], - ), - ), - ), - ); - } - - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? ExpandableNotifier( - controller: expandableController, - child: Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: statusProvider.serverStatus!.generalEnabled == true && !statusProvider.protectionsManagementProcess.contains('general') - ? () => expandableController.toggle() - : null, - borderRadius: BorderRadius.circular(28), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12 - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(28), - color: Theme.of(context).colorScheme.primary.withOpacity(0.1) - ), - child: Expandable( - theme: const ExpandableThemeData( - animationDuration: Duration(milliseconds: 200), - fadeCurve: Curves.ease - ), - collapsed: topRow(legacyMode: false), - expanded: Column( - children: [ - topRow(legacyMode: false), - bottomRow(), - const SizedBox(height: 8) - ], - ) - ), - ), - ), - ) - ) - : Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: statusProvider.protectionsManagementProcess.contains('general') == false - ? () => updateBlocking( - value: !statusProvider.serverStatus!.generalEnabled, - filter: 'general_legacy' - ) : null, - borderRadius: BorderRadius.circular(28), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12 - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(28), - color: Theme.of(context).primaryColor.withOpacity(0.1) - ), - child: topRow(legacyMode: true) - ), - ), - ) - ); - } - - Widget smallSwitch(String label, IconData icon, bool value, Function(bool) onChange, bool disabled) { - return Material( - color: Colors.transparent, - child: InkWell( - onTap: disabled == false - ? () => onChange(!value) - : null, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 44, - vertical: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Icon( - icon, - size: 24, - color: Theme.of(context).listTileTheme.iconColor, - ), - const SizedBox(width: 16), - Text( - label, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ], - ), - Switch( - value: value, - onChanged: disabled == false - ? onChange - : null, - ) - ], - ), - ), - ), - ); - } - - Widget header() { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Text( - AppLocalizations.of(context)!.manageServer, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ), - ], - ), - ], - ); - } - - List toggles() { - return [ - mainSwitch(), - Container(height: 10), - smallSwitch( - AppLocalizations.of(context)!.ruleFiltering, - Icons.filter_list_rounded, - statusProvider.serverStatus!.filteringEnabled, - (value) => updateBlocking(value: value, filter: 'filtering'), - statusProvider.protectionsManagementProcess.contains('filtering') - ), - smallSwitch( - AppLocalizations.of(context)!.safeBrowsing, - Icons.vpn_lock_rounded, - statusProvider.serverStatus!.safeBrowsingEnabled, - (value) => updateBlocking(value: value, filter: 'safeBrowsing'), - statusProvider.protectionsManagementProcess.contains('safeBrowsing') - ), - smallSwitch( - AppLocalizations.of(context)!.parentalFiltering, - Icons.block, - statusProvider.serverStatus!.parentalControlEnabled, - (value) => updateBlocking(value: value, filter: 'parentalControl'), - statusProvider.protectionsManagementProcess.contains('parentalControl') - ), - smallSwitch( - AppLocalizations.of(context)!.safeSearch, - Icons.search_rounded, - statusProvider.serverStatus!.safeSearchEnabled, - (value) => updateBlocking(value: value, filter: 'safeSearch'), - statusProvider.protectionsManagementProcess.contains('safeSearch') - ), - ]; - } - - if (widget.dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 400 - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - header(), - ...toggles() - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close), - ), - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ), - ), - ); - } - else { - return Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ) - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - header(), - ...toggles() - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close), - ), - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ), - ); - } - } -} \ No newline at end of file diff --git a/lib/screens/home/management_modal/main_switch.dart b/lib/screens/home/management_modal/main_switch.dart new file mode 100644 index 0000000..6c7b2ae --- /dev/null +++ b/lib/screens/home/management_modal/main_switch.dart @@ -0,0 +1,266 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:expandable/expandable.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/functions/format_time.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; + +class MainSwitch extends StatelessWidget { + final ExpandableController expandableController; + final void Function({ required bool value, required String filter }) updateBlocking; + final void Function(int) disableWithCountdown; + final Animation animation; + + const MainSwitch({ + Key? key, + required this.expandableController, + required this.updateBlocking, + required this.disableWithCountdown, + required this.animation, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: serverVersionIsAhead( + currentVersion: statusProvider.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? ExpandableNotifier( + controller: expandableController, + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: statusProvider.serverStatus!.generalEnabled == true && !statusProvider.protectionsManagementProcess.contains('general') + ? () => expandableController.toggle() + : null, + borderRadius: BorderRadius.circular(28), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: Theme.of(context).colorScheme.primary.withOpacity(0.1) + ), + child: Expandable( + theme: const ExpandableThemeData( + animationDuration: Duration(milliseconds: 200), + fadeCurve: Curves.ease + ), + collapsed: _TopRow( + legacyMode: false, + expandableController: expandableController, + updateBlocking: updateBlocking, + animation: animation, + ), + expanded: Column( + children: [ + _TopRow( + legacyMode: false, + expandableController: expandableController, + updateBlocking: updateBlocking, + animation: animation, + ), + _BottomRow( + disableWithCountdown: disableWithCountdown, + ), + const SizedBox(height: 8) + ], + ) + ), + ), + ), + ) + ) + : Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: statusProvider.protectionsManagementProcess.contains('general') == false + ? () => updateBlocking( + value: !statusProvider.serverStatus!.generalEnabled, + filter: 'general_legacy' + ) : null, + borderRadius: BorderRadius.circular(28), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + color: Theme.of(context).primaryColor.withOpacity(0.1) + ), + child: _TopRow( + legacyMode: true, + expandableController: expandableController, + updateBlocking: updateBlocking, + animation: animation, + ) + ), + ), + ) + ); + } +} + +class _TopRow extends StatelessWidget { + final bool legacyMode; + final ExpandableController expandableController; + final void Function({ required bool value, required String filter }) updateBlocking; + final Animation animation; + + const _TopRow({ + Key? key, + required this.legacyMode, + required this.expandableController, + required this.updateBlocking, + required this.animation, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + if (legacyMode == false) ...[ + RotationTransition( + turns: animation, + child: Icon( + Icons.keyboard_arrow_down_rounded, + size: 26, + color: statusProvider.serverStatus!.generalEnabled == true + ? Theme.of(context).colorScheme.onSurfaceVariant + : Colors.grey, + ), + ), + const SizedBox(width: 8), + ], + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.allProtections, + style: const TextStyle( + fontSize: 18, + ), + ), + if (statusProvider.serverStatus!.timeGeneralDisabled > 0) ...[ + const SizedBox(height: 2), + if (statusProvider.currentDeadline != null) Text( + "${AppLocalizations.of(context)!.remainingTime}: ${formatRemainingSeconds(statusProvider.remainingTime)}" + ) + ] + ], + ), + ], + ), + Switch( + value: statusProvider.serverStatus!.generalEnabled, + onChanged: statusProvider.protectionsManagementProcess.contains('general') == false + ? (value) { + if (value == false && expandableController.expanded == true && legacyMode == false) { + expandableController.toggle(); + } + updateBlocking( + value: value, + filter: legacyMode == true ? 'general_legacy' : 'general' + ); + } : null, + ) + ] + ); + } +} + +class _BottomRow extends StatefulWidget { + final void Function(int) disableWithCountdown; + + const _BottomRow({ + Key? key, + required this.disableWithCountdown, + }) : super(key: key); + + @override + State<_BottomRow> createState() => _BottomRowState(); +} + +class _BottomRowState extends State<_BottomRow> { + final _chipsScrollController = ScrollController(); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + + return Container( + height: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 50 : 40, + margin: const EdgeInsets.only(top: 8), + child: Scrollbar( + controller: _chipsScrollController, + thumbVisibility: Platform.isMacOS || Platform.isLinux || Platform.isWindows, + interactive: Platform.isMacOS || Platform.isLinux || Platform.isWindows, + thickness: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 8 : 0, + child: Padding( + padding: EdgeInsets.only( + bottom: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 16 : 0 + ), + child: ListView( + controller: _chipsScrollController, + scrollDirection: Axis.horizontal, + children: [ + ActionChip( + label: Text(AppLocalizations.of(context)!.seconds(30)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => widget.disableWithCountdown(29000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.minute(1)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => widget.disableWithCountdown(59000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.minutes(10)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => widget.disableWithCountdown(599000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.hour(1)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => widget.disableWithCountdown(3599000) + : null, + ), + const SizedBox(width: 8), + ActionChip( + label: Text(AppLocalizations.of(context)!.hours(24)), + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true + ? () => widget.disableWithCountdown(86399000) + : null, + ), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/home/management_modal/management_modal.dart b/lib/screens/home/management_modal/management_modal.dart new file mode 100644 index 0000000..8fa968c --- /dev/null +++ b/lib/screens/home/management_modal/management_modal.dart @@ -0,0 +1,269 @@ +// ignore_for_file: use_build_context_synchronously + +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:expandable/expandable.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/home/management_modal/main_switch.dart'; +import 'package:adguard_home_manager/screens/home/management_modal/small_switch.dart'; + +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; + +class ManagementModal extends StatefulWidget { + final bool dialog; + + const ManagementModal({ + Key? key, + required this.dialog + }) : super(key: key); + + @override + State createState() => _ManagementModalState(); +} + +class _ManagementModalState extends State with SingleTickerProviderStateMixin { + late AnimationController animationController; + late Animation animation; + final ExpandableController expandableController = ExpandableController(); + + @override + void initState() { + expandableController.addListener(() async { + await Future.delayed(const Duration(milliseconds: 200)); + if (expandableController.value == false) { + animationController.animateTo(0); + } + else { + animationController.animateBack(1); + } + }); + + animationController = AnimationController( + duration: const Duration(milliseconds: 200), + vsync: this, + ) + ..addListener(() => setState(() => {})); + animation = Tween( + begin: 0.0, + end: 0.5, + ).animate(CurvedAnimation( + parent: animationController, + curve: Curves.easeInOut + )); + + super.initState(); + } + + @override + void dispose() { + animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void updateBlocking({ + required bool value, + required String filter, + int? time + }) async { + final result = await statusProvider.updateBlocking( + block: filter, + newStatus: value, + time: time + ); + if (mounted && result != null) { + if (result != false) { + appConfigProvider.addLog(result); + } + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.invalidUsernamePassword, + color: Colors.red + ); + } + } + + void disableWithCountdown(int time) async { + updateBlocking(value: false, filter: 'general', time: time); + expandableController.toggle(); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: _Modal( + expandableController: expandableController, + updateBlocking: updateBlocking, + disableWithCountdown: disableWithCountdown, + animation: animation, + ) + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close), + ), + ], + ), + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ), + ), + ); + } + else { + return Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ) + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: _Modal( + expandableController: expandableController, + updateBlocking: updateBlocking, + disableWithCountdown: disableWithCountdown, + animation: animation, + ) + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close), + ), + ], + ), + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ), + ); + } + } +} + +class _Modal extends StatelessWidget { + final ExpandableController expandableController; + final void Function({ required bool value, required String filter }) updateBlocking; + final void Function(int) disableWithCountdown; + final Animation animation; + + const _Modal({ + Key? key, + required this.expandableController, + required this.updateBlocking, + required this.disableWithCountdown, + required this.animation, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + + return Wrap( + children: [ + // Header + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Text( + AppLocalizations.of(context)!.manageServer, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ), + ], + ), + ], + ), + + MainSwitch( + expandableController: expandableController, + updateBlocking: updateBlocking, + disableWithCountdown: disableWithCountdown, + animation: animation, + ), + Container(height: 10), + SmallSwitch( + label: AppLocalizations.of(context)!.ruleFiltering, + icon: Icons.filter_list_rounded, + value: statusProvider.serverStatus!.filteringEnabled, + onChange: (value) => updateBlocking(value: value, filter: 'filtering'), + disabled: statusProvider.protectionsManagementProcess.contains('filtering') + ), + SmallSwitch( + label: AppLocalizations.of(context)!.safeBrowsing, + icon: Icons.vpn_lock_rounded, + value: statusProvider.serverStatus!.safeBrowsingEnabled, + onChange: (value) => updateBlocking(value: value, filter: 'safeBrowsing'), + disabled: statusProvider.protectionsManagementProcess.contains('safeBrowsing') + ), + SmallSwitch( + label: AppLocalizations.of(context)!.parentalFiltering, + icon: Icons.block, + value: statusProvider.serverStatus!.parentalControlEnabled, + onChange: (value) => updateBlocking(value: value, filter: 'parentalControl'), + disabled: statusProvider.protectionsManagementProcess.contains('parentalControl') + ), + SmallSwitch( + label: AppLocalizations.of(context)!.safeSearch, + icon: Icons.search_rounded, + value: statusProvider.serverStatus!.safeSearchEnabled, + onChange: (value) => updateBlocking(value: value, filter: 'safeSearch'), + disabled: statusProvider.protectionsManagementProcess.contains('safeSearch') + ), + ], + ); + } +} diff --git a/lib/screens/home/management_modal/small_switch.dart b/lib/screens/home/management_modal/small_switch.dart new file mode 100644 index 0000000..4e34d68 --- /dev/null +++ b/lib/screens/home/management_modal/small_switch.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; + +class SmallSwitch extends StatelessWidget { + final String label; + final IconData icon; + final bool value; + final void Function(bool) onChange; + final bool disabled; + + const SmallSwitch({ + Key? key, + required this.label, + required this.icon, + required this.value, + required this.onChange, + required this.disabled, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: disabled == false + ? () => onChange(!value) + : null, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 44, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Icon( + icon, + size: 24, + color: Theme.of(context).listTileTheme.iconColor, + ), + const SizedBox(width: 16), + Text( + label, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ], + ), + Switch( + value: value, + onChanged: disabled == false + ? onChange + : null, + ) + ], + ), + ), + ), + ); + } +} \ No newline at end of file From c391c76f5ab2c459d027144dc0f3e6fe7b1864d8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 14:31:11 +0100 Subject: [PATCH 351/676] Navigate with root key --- lib/routes/routes.dart | 92 +++++++++---------- .../clients/client/logs_list_client.dart | 13 ++- lib/screens/clients/clients_lists.dart | 17 ++-- lib/screens/filters/filters.dart | 3 +- lib/screens/home/appbar.dart | 5 +- lib/screens/home/top_items.dart | 3 +- lib/screens/logs/logs_list.dart | 13 ++- lib/screens/settings/dhcp/dhcp.dart | 49 ++++++---- lib/screens/settings/dns/dns.dart | 9 +- .../general_settings/general_settings.dart | 9 +- lib/screens/settings/settings.dart | 3 +- 11 files changed, 121 insertions(+), 95 deletions(-) diff --git a/lib/routes/routes.dart b/lib/routes/routes.dart index 9a79603..351906a 100644 --- a/lib/routes/routes.dart +++ b/lib/routes/routes.dart @@ -13,6 +13,26 @@ import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/constants/routes_names.dart'; +Page routePage({ + required BuildContext context, + required Widget child +}) { + if (isDesktop(MediaQuery.of(context).size.width)) { + return NoTransitionPage(child: child); + } + else { + return CustomTransitionPage( + child: child, + transitionsBuilder: (context, anim1, anim2, child) { + return FadeTransition( + opacity: anim1, + child: child, + ); + }, + ); + } +} + final List routes = [ GoRoute( path: "/", @@ -29,14 +49,10 @@ final List routes = [ GoRoute( parentNavigatorKey: homeNavigatorKey, path: RoutesNames.home, - pageBuilder: (context, state) { - if (isDesktop(MediaQuery.of(context).size.width)) { - return const NoTransitionPage(child: Home()); - } - else { - return const MaterialPage(child: Home()); - } - }, + pageBuilder: (context, state) => routePage( + context: context, + child: const Home() + ) ), ] ), @@ -46,14 +62,10 @@ final List routes = [ GoRoute( parentNavigatorKey: clientsNavigatorKey, path: RoutesNames.clients, - pageBuilder: (context, state) { - if (isDesktop(MediaQuery.of(context).size.width)) { - return const NoTransitionPage(child: Clients()); - } - else { - return const MaterialPage(child: Clients()); - } - }, + pageBuilder: (context, state) => routePage( + context: context, + child: const Clients() + ) ) ] ), @@ -63,14 +75,10 @@ final List routes = [ GoRoute( parentNavigatorKey: logsNavigatorKey, path: RoutesNames.logs, - pageBuilder: (context, state) { - if (isDesktop(MediaQuery.of(context).size.width)) { - return const NoTransitionPage(child: Logs()); - } - else { - return const MaterialPage(child: Logs()); - } - }, + pageBuilder: (context, state) => routePage( + context: context, + child: const Logs() + ) ) ] ), @@ -80,14 +88,10 @@ final List routes = [ GoRoute( parentNavigatorKey: filtersNavigatorKey, path: RoutesNames.filters, - pageBuilder: (context, state) { - if (isDesktop(MediaQuery.of(context).size.width)) { - return const NoTransitionPage(child: Filters()); - } - else { - return const MaterialPage(child: Filters()); - } - }, + pageBuilder: (context, state) => routePage( + context: context, + child: const Filters() + ) ) ] ), @@ -97,14 +101,10 @@ final List routes = [ GoRoute( parentNavigatorKey: settingsNavigatorKey, path: RoutesNames.settings, - pageBuilder: (context, state) { - if (isDesktop(MediaQuery.of(context).size.width)) { - return const NoTransitionPage(child: Settings()); - } - else { - return const MaterialPage(child: Settings()); - } - }, + pageBuilder: (context, state) => routePage( + context: context, + child: const Settings() + ) ) ] ), @@ -113,14 +113,10 @@ final List routes = [ routes: [ GoRoute( path: RoutesNames.connect, - pageBuilder: (context, state) { - if (isDesktop(MediaQuery.of(context).size.width)) { - return const NoTransitionPage(child: Connect()); - } - else { - return const MaterialPage(child: Connect()); - } - }, + pageBuilder: (context, state) => routePage( + context: context, + child: const Connect() + ) ) ] ), diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index 5d8f6ed..fa95e60 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -8,6 +8,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -212,12 +213,14 @@ class _LogsListClientState extends State { ) } else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false + rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false + ) ) - )) + ) } }, twoColumns: widget.splitView, diff --git a/lib/screens/clients/clients_lists.dart b/lib/screens/clients/clients_lists.dart index ec451bc..47e7d12 100644 --- a/lib/screens/clients/clients_lists.dart +++ b/lib/screens/clients/clients_lists.dart @@ -8,6 +8,7 @@ import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dar import 'package:adguard_home_manager/screens/clients/clients_list.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -71,9 +72,11 @@ class _ClientsListsState extends State with TickerProviderStateMix SplitView.of(context).push(w); } else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => w, - )); + rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => w, + ) + ); } } @@ -89,9 +92,11 @@ class _ClientsListsState extends State with TickerProviderStateMix SplitView.of(context).push(w); } else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => w, - )); + rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => w, + ) + ); } } diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 5975cf6..919f22c 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -14,6 +14,7 @@ import 'package:adguard_home_manager/screens/filters/remove_custom_rule_modal.da import 'package:adguard_home_manager/screens/filters/blocked_services_screen.dart'; import 'package:adguard_home_manager/screens/filters/update_interval_lists_modal.dart'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -202,7 +203,7 @@ class _FiltersState extends State { ); } else { - Navigator.of(context).push( + rootNavigatorKey.currentState!.push( MaterialPageRoute( builder: (context) => ListDetailsScreen( listId: filter.id, diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 34893b6..2bccc66 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -1,10 +1,11 @@ -import 'package:adguard_home_manager/functions/desktop_mode.dart'; 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/servers/servers.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; @@ -32,7 +33,7 @@ class HomeAppBar extends StatelessWidget { void navigateServers() { Future.delayed(const Duration(milliseconds: 0), (() { - Navigator.of(context).push( + rootNavigatorKey.currentState!.push( MaterialPageRoute(builder: (context) => const Servers()) ); })); diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index 06ef00e..dce0f52 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -11,6 +11,7 @@ import 'package:adguard_home_manager/widgets/domain_options.dart'; import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; @@ -217,7 +218,7 @@ class _TopItemsState extends State { ) } else { - Navigator.of(context).push( + rootNavigatorKey.currentState!.push( MaterialPageRoute( builder: (context) => TopItemsScreen( type: widget.type, diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart index 6fd80e6..fa1aed2 100644 --- a/lib/screens/logs/logs_list.dart +++ b/lib/screens/logs/logs_list.dart @@ -12,6 +12,7 @@ import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart'; import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; @@ -463,12 +464,14 @@ class _LogsListWidgetState extends State { isLogSelected: widget.selectedLog != null && widget.selectedLog == logsProvider.logsData!.data[index], onLogTap: (log) { if (!widget.twoColumns) { - Navigator.push(context, MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false, + rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + ) ) - )); + ); } widget.onLogSelected(log); }, diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index aa44414..ccd50e7 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -12,6 +12,7 @@ import 'package:adguard_home_manager/widgets/confirm_action_modal.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_leases.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/select_interface_modal.dart'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -705,12 +706,14 @@ class _DhcpScreenState extends State { color: Colors.transparent, child: InkWell( onTap: () { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.leases, - staticLeases: false, + rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.leases, + staticLeases: false, + ) ) - )); + ); }, child: Container( padding: const EdgeInsets.all(16), @@ -738,12 +741,14 @@ class _DhcpScreenState extends State { color: Colors.transparent, child: InkWell( onTap: () { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, - staticLeases: true, + rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, + staticLeases: true, + ) ) - )); + ); }, child: Container( padding: const EdgeInsets.all(16), @@ -781,12 +786,14 @@ class _DhcpScreenState extends State { ); } else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.leases, - staticLeases: false, + rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.leases, + staticLeases: false, + ) ) - )); + ); } }, child: Row( @@ -808,12 +815,14 @@ class _DhcpScreenState extends State { ); } else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, - staticLeases: true, + rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, + staticLeases: true, + ) ) - )); + ); } }, child: Row( diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 7d0760b..063b9a3 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -14,6 +14,7 @@ import 'package:adguard_home_manager/screens/settings/dns/upstream_dns.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/clear_dns_cache.dart'; @@ -53,9 +54,11 @@ class _DnsSettingsState extends State { SplitView.of(context).push(w); } else { - Navigator.push(context, MaterialPageRoute( - builder: (context) => w - )); + rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => w + ) + ); } } diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index cef6a8f..e91156b 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -12,6 +12,7 @@ import 'package:adguard_home_manager/screens/settings/general_settings/reorderab import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; +import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/check_app_updates.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -191,9 +192,11 @@ class _GeneralSettingsState extends State { icon: Icons.reorder_rounded, title: AppLocalizations.of(context)!.topItemsOrder, subtitle: AppLocalizations.of(context)!.topItemsOrderDescription, - onTap: () => Navigator.push(context, MaterialPageRoute( - builder: (context) => const ReorderableTopItemsHome() - )), + onTap: () => rootNavigatorKey.currentState!.push( + MaterialPageRoute( + builder: (context) => const ReorderableTopItemsHome() + ) + ) ), CustomListTile( icon: Icons.donut_large_rounded, diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 0f01b44..ce6ea5f 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -23,6 +23,7 @@ import 'package:adguard_home_manager/widgets/custom_settings_tile.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/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; @@ -119,7 +120,7 @@ class SettingsWidget extends StatelessWidget { icon: icon, trailing: trailing, onTap: () { - Navigator.of(context).push( + rootNavigatorKey.currentState!.push( MaterialPageRoute(builder: (context) => screenToNavigate) ); }, From af14484a9512fc6f7c9c349cad269f093d040b28 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 15:38:17 +0100 Subject: [PATCH 352/676] Removed go router --- lib/config/app_screens.dart | 14 ++ lib/main.dart | 7 +- lib/models/app_screen.dart | 4 +- lib/routes/router.dart | 20 --- lib/routes/router_globals.dart | 10 -- lib/routes/routes.dart | 125 ------------------ .../clients/client/logs_list_client.dart | 3 +- lib/screens/clients/clients_lists.dart | 5 +- lib/screens/filters/filters.dart | 3 +- lib/screens/home/appbar.dart | 3 +- lib/screens/home/top_items.dart | 3 +- lib/screens/logs/logs_list.dart | 3 +- lib/screens/settings/dhcp/dhcp.dart | 9 +- lib/screens/settings/dns/dns.dart | 3 +- .../general_settings/general_settings.dart | 3 +- lib/screens/settings/settings.dart | 22 ++- lib/widgets/layout.dart | 52 +++++--- pubspec.lock | 16 --- pubspec.yaml | 1 - 19 files changed, 85 insertions(+), 221 deletions(-) delete mode 100644 lib/routes/router.dart delete mode 100644 lib/routes/router_globals.dart delete mode 100644 lib/routes/routes.dart diff --git a/lib/config/app_screens.dart b/lib/config/app_screens.dart index 4f9a97d..2326e31 100644 --- a/lib/config/app_screens.dart +++ b/lib/config/app_screens.dart @@ -1,15 +1,24 @@ import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/screens/clients/clients.dart'; +import 'package:adguard_home_manager/screens/connect/connect.dart'; +import 'package:adguard_home_manager/screens/filters/filters.dart'; +import 'package:adguard_home_manager/screens/home/home.dart'; +import 'package:adguard_home_manager/screens/logs/logs.dart'; +import 'package:adguard_home_manager/screens/settings/settings.dart'; + import 'package:adguard_home_manager/models/app_screen.dart'; List screensSelectServer = [ const AppScreen( name: "connect", icon: Icons.link_rounded, + child: Connect() ), const AppScreen( name: "settings", icon: Icons.settings_rounded, + child: Settings() ) ]; @@ -17,21 +26,26 @@ List screensServerConnected = [ const AppScreen( name: "home", icon: Icons.home_rounded, + child: Home() ), const AppScreen( name: "clients", icon: Icons.devices, + child: Clients() ), const AppScreen( name: "logs", icon: Icons.list_alt_rounded, + child: Logs() ), const AppScreen( name: "filters", icon: Icons.shield_rounded, + child: Filters() ), const AppScreen( name: "settings", icon: Icons.settings_rounded, + child: Settings() ) ]; \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 1548e4a..f34459f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,11 +16,12 @@ import 'package:window_size/window_size.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/layout.dart'; import 'package:adguard_home_manager/widgets/menu_bar.dart'; + import 'package:adguard_home_manager/functions/check_app_updates.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/widgets/update_modal.dart'; -import 'package:adguard_home_manager/routes/router.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; @@ -244,7 +245,7 @@ class _MainState extends State
with WidgetsBindingObserver { : Brightness.light, ), child: DynamicColorBuilder( - builder: (lightDynamic, darkDynamic) => MaterialApp.router( + builder: (lightDynamic, darkDynamic) => MaterialApp( title: 'AdGuard Home Manager', theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 ? appConfigProvider.useDynamicColor == true @@ -285,7 +286,7 @@ class _MainState extends State
with WidgetsBindingObserver { ), ); }, - routerConfig: goRouter, + home: Layout(), ), ), ); diff --git a/lib/models/app_screen.dart b/lib/models/app_screen.dart index 1e377eb..4412022 100644 --- a/lib/models/app_screen.dart +++ b/lib/models/app_screen.dart @@ -5,11 +5,13 @@ class AppScreen { final IconData icon; final PreferredSizeWidget? appBar; final Widget? fab; + final Widget child; const AppScreen({ required this.name, required this.icon, this.appBar, - this.fab + this.fab, + required this.child, }); } \ No newline at end of file diff --git a/lib/routes/router.dart b/lib/routes/router.dart deleted file mode 100644 index 9b1cfba..0000000 --- a/lib/routes/router.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:go_router/go_router.dart'; -import 'package:provider/provider.dart'; - -import 'package:adguard_home_manager/routes/router_globals.dart'; -import 'package:adguard_home_manager/routes/routes.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/constants/routes_names.dart'; - -final goRouter = GoRouter( - navigatorKey: rootNavigatorKey, - redirect: (context, state) { - final serversProvider = Provider.of(context, listen: false); - if (serversProvider.selectedServer == null) { - return RoutesNames.connect; - } - return null; - }, - initialLocation: RoutesNames.home, - routes: routes, -); \ No newline at end of file diff --git a/lib/routes/router_globals.dart b/lib/routes/router_globals.dart deleted file mode 100644 index f78c1a7..0000000 --- a/lib/routes/router_globals.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter/widgets.dart'; - -final GlobalKey rootNavigatorKey = GlobalKey(); -final GlobalKey connectNavigatorKey = GlobalKey(); -final GlobalKey homeNavigatorKey = GlobalKey(); -final GlobalKey clientsNavigatorKey = GlobalKey(); -final GlobalKey logsNavigatorKey = GlobalKey(); -final GlobalKey filtersNavigatorKey = GlobalKey(); -final GlobalKey settingsNavigatorKey = GlobalKey(); -final GlobalKey settingsListNavigatorKey = GlobalKey(); \ No newline at end of file diff --git a/lib/routes/routes.dart b/lib/routes/routes.dart deleted file mode 100644 index 351906a..0000000 --- a/lib/routes/routes.dart +++ /dev/null @@ -1,125 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - -import 'package:adguard_home_manager/screens/home/home.dart'; -import 'package:adguard_home_manager/screens/clients/clients.dart'; -import 'package:adguard_home_manager/screens/connect/connect.dart'; -import 'package:adguard_home_manager/screens/filters/filters.dart'; -import 'package:adguard_home_manager/screens/logs/logs.dart'; -import 'package:adguard_home_manager/screens/settings/settings.dart'; -import 'package:adguard_home_manager/widgets/layout.dart'; - -import 'package:adguard_home_manager/functions/desktop_mode.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; -import 'package:adguard_home_manager/constants/routes_names.dart'; - -Page routePage({ - required BuildContext context, - required Widget child -}) { - if (isDesktop(MediaQuery.of(context).size.width)) { - return NoTransitionPage(child: child); - } - else { - return CustomTransitionPage( - child: child, - transitionsBuilder: (context, anim1, anim2, child) { - return FadeTransition( - opacity: anim1, - child: child, - ); - }, - ); - } -} - -final List routes = [ - GoRoute( - path: "/", - redirect: (context, state) => RoutesNames.home, - ), - StatefulShellRoute.indexedStack( - builder: (context, state, navigationShell) => Layout( - navigationShell: navigationShell - ), - branches: [ - StatefulShellBranch( - navigatorKey: homeNavigatorKey, - routes: [ - GoRoute( - parentNavigatorKey: homeNavigatorKey, - path: RoutesNames.home, - pageBuilder: (context, state) => routePage( - context: context, - child: const Home() - ) - ), - ] - ), - StatefulShellBranch( - navigatorKey: clientsNavigatorKey, - routes: [ - GoRoute( - parentNavigatorKey: clientsNavigatorKey, - path: RoutesNames.clients, - pageBuilder: (context, state) => routePage( - context: context, - child: const Clients() - ) - ) - ] - ), - StatefulShellBranch( - navigatorKey: logsNavigatorKey, - routes: [ - GoRoute( - parentNavigatorKey: logsNavigatorKey, - path: RoutesNames.logs, - pageBuilder: (context, state) => routePage( - context: context, - child: const Logs() - ) - ) - ] - ), - StatefulShellBranch( - navigatorKey: filtersNavigatorKey, - routes: [ - GoRoute( - parentNavigatorKey: filtersNavigatorKey, - path: RoutesNames.filters, - pageBuilder: (context, state) => routePage( - context: context, - child: const Filters() - ) - ) - ] - ), - StatefulShellBranch( - navigatorKey: settingsNavigatorKey, - routes: [ - GoRoute( - parentNavigatorKey: settingsNavigatorKey, - path: RoutesNames.settings, - pageBuilder: (context, state) => routePage( - context: context, - child: const Settings() - ) - ) - ] - ), - StatefulShellBranch( - navigatorKey: connectNavigatorKey, - routes: [ - GoRoute( - path: RoutesNames.connect, - pageBuilder: (context, state) => routePage( - context: context, - child: const Connect() - ) - ) - ] - ), - ] - ) -]; \ No newline at end of file diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index fa95e60..9761e3f 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -8,7 +8,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -213,7 +212,7 @@ class _LogsListClientState extends State { ) } else { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => LogDetailsScreen( log: log, diff --git a/lib/screens/clients/clients_lists.dart b/lib/screens/clients/clients_lists.dart index 47e7d12..0e518ce 100644 --- a/lib/screens/clients/clients_lists.dart +++ b/lib/screens/clients/clients_lists.dart @@ -8,7 +8,6 @@ import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dar import 'package:adguard_home_manager/screens/clients/clients_list.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -72,7 +71,7 @@ class _ClientsListsState extends State with TickerProviderStateMix SplitView.of(context).push(w); } else { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => w, ) @@ -92,7 +91,7 @@ class _ClientsListsState extends State with TickerProviderStateMix SplitView.of(context).push(w); } else { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => w, ) diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 919f22c..5975cf6 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -14,7 +14,6 @@ import 'package:adguard_home_manager/screens/filters/remove_custom_rule_modal.da import 'package:adguard_home_manager/screens/filters/blocked_services_screen.dart'; import 'package:adguard_home_manager/screens/filters/update_interval_lists_modal.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -203,7 +202,7 @@ class _FiltersState extends State { ); } else { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => ListDetailsScreen( listId: filter.id, diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 2bccc66..365e606 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -5,7 +5,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/servers/servers.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; @@ -33,7 +32,7 @@ class HomeAppBar extends StatelessWidget { void navigateServers() { Future.delayed(const Duration(milliseconds: 0), (() { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute(builder: (context) => const Servers()) ); })); diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index dce0f52..06ef00e 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -11,7 +11,6 @@ import 'package:adguard_home_manager/widgets/domain_options.dart'; import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; @@ -218,7 +217,7 @@ class _TopItemsState extends State { ) } else { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => TopItemsScreen( type: widget.type, diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart index fa1aed2..b04fe74 100644 --- a/lib/screens/logs/logs_list.dart +++ b/lib/screens/logs/logs_list.dart @@ -12,7 +12,6 @@ import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart'; import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; @@ -464,7 +463,7 @@ class _LogsListWidgetState extends State { isLogSelected: widget.selectedLog != null && widget.selectedLog == logsProvider.logsData!.data[index], onLogTap: (log) { if (!widget.twoColumns) { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => LogDetailsScreen( log: log, diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index ccd50e7..c003ea2 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -12,7 +12,6 @@ import 'package:adguard_home_manager/widgets/confirm_action_modal.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_leases.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/select_interface_modal.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -706,7 +705,7 @@ class _DhcpScreenState extends State { color: Colors.transparent, child: InkWell( onTap: () { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => DhcpLeases( items: dhcpProvider.dhcp!.dhcpStatus.leases, @@ -741,7 +740,7 @@ class _DhcpScreenState extends State { color: Colors.transparent, child: InkWell( onTap: () { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => DhcpLeases( items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, @@ -786,7 +785,7 @@ class _DhcpScreenState extends State { ); } else { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => DhcpLeases( items: dhcpProvider.dhcp!.dhcpStatus.leases, @@ -815,7 +814,7 @@ class _DhcpScreenState extends State { ); } else { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => DhcpLeases( items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 063b9a3..1f74669 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -14,7 +14,6 @@ import 'package:adguard_home_manager/screens/settings/dns/upstream_dns.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/clear_dns_cache.dart'; @@ -54,7 +53,7 @@ class _DnsSettingsState extends State { SplitView.of(context).push(w); } else { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute( builder: (context) => w ) diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index e91156b..4625136 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -12,7 +12,6 @@ import 'package:adguard_home_manager/screens/settings/general_settings/reorderab import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; -import 'package:adguard_home_manager/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/check_app_updates.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -192,7 +191,7 @@ class _GeneralSettingsState extends State { icon: Icons.reorder_rounded, title: AppLocalizations.of(context)!.topItemsOrder, subtitle: AppLocalizations.of(context)!.topItemsOrderDescription, - onTap: () => rootNavigatorKey.currentState!.push( + onTap: () => Navigator.of(context).push( MaterialPageRoute( builder: (context) => const ReorderableTopItemsHome() ) diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index ce6ea5f..6a67d28 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -23,7 +23,6 @@ import 'package:adguard_home_manager/widgets/custom_settings_tile.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/routes/router_globals.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; @@ -71,7 +70,7 @@ class Settings extends StatelessWidget { ); } } -class SettingsWidget extends StatelessWidget { +class SettingsWidget extends StatefulWidget { final bool twoColumns; const SettingsWidget({ @@ -79,6 +78,17 @@ class SettingsWidget extends StatelessWidget { required this.twoColumns, }) : super(key: key); + @override + State createState() => _SettingsWidgetState(); +} + +class _SettingsWidgetState extends State { + @override + void initState() { + Provider.of(context, listen: false).setSelectedSettingsScreen(screen: null); + super.initState(); + } + @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); @@ -87,7 +97,7 @@ class SettingsWidget extends StatelessWidget { final width = MediaQuery.of(context).size.width; - if (!twoColumns && appConfigProvider.selectedSettingsScreen != null) { + if (!widget.twoColumns && appConfigProvider.selectedSettingsScreen != null) { appConfigProvider.setSelectedSettingsScreen(screen: null); } @@ -99,7 +109,7 @@ class SettingsWidget extends StatelessWidget { required Widget screenToNavigate, required int thisItem }) { - if (twoColumns) { + if (widget.twoColumns) { return CustomSettingsTile( title: title, subtitle: subtitle, @@ -120,7 +130,7 @@ class SettingsWidget extends StatelessWidget { icon: icon, trailing: trailing, onTap: () { - rootNavigatorKey.currentState!.push( + Navigator.of(context).push( MaterialPageRoute(builder: (context) => screenToNavigate) ); }, @@ -191,7 +201,7 @@ class SettingsWidget extends StatelessWidget { subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, thisItem: 3, screenToNavigate: DnsSettings( - splitView: twoColumns, + splitView: widget.twoColumns, ), ), settingsTile( diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index 6104b6f..a7da996 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -1,18 +1,16 @@ import 'package:flutter/material.dart'; +import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; -import 'package:go_router/go_router.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; import 'package:adguard_home_manager/config/sizes.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class Layout extends StatefulWidget { - final StatefulNavigationShell navigationShell; - const Layout({ Key? key, - required this.navigationShell, }) : super(key: key); @override @@ -23,10 +21,7 @@ class _LayoutState extends State { bool _drawerExpanded = true; void _goBranch(int index) { - widget.navigationShell.goBranch( - index, - initialLocation: index == widget.navigationShell.currentIndex, - ); + Provider.of(context, listen: false).setSelectedScreen(index); } @override @@ -34,6 +29,11 @@ class _LayoutState extends State { final width = MediaQuery.of(context).size.width; final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + final screens = serversProvider.selectedServer != null + ? screensServerConnected + : screensSelectServer; String translatedName(String key) { switch (key) { @@ -93,8 +93,7 @@ class _LayoutState extends State { (s) => DrawerTile( icon: s.value.icon, title: translatedName(s.value.name), - isSelected: - widget.navigationShell.currentIndex == s.key, + isSelected: appConfigProvider.selectedScreen == s.key, onSelect: () => _goBranch(s.key), withoutTitle: !_drawerExpanded, ), @@ -104,8 +103,7 @@ class _LayoutState extends State { (s) => DrawerTile( icon: s.value.icon, title: translatedName(s.value.name), - isSelected: - widget.navigationShell.currentIndex == s.key, + isSelected: appConfigProvider.selectedScreen == s.key, onSelect: () => _goBranch(s.key), withoutTitle: !_drawerExpanded, ), @@ -114,7 +112,17 @@ class _LayoutState extends State { ), ), Expanded( - child: widget.navigationShell + child: PageTransitionSwitcher( + duration: const Duration(milliseconds: 200), + transitionBuilder: ( + (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( + animation: primaryAnimation, + secondaryAnimation: secondaryAnimation, + child: child, + ) + ), + child: screens[appConfigProvider.selectedScreen].child, + ), ), ], ), @@ -126,18 +134,28 @@ class _LayoutState extends State { : screensSelectServer; return Scaffold( - body: widget.navigationShell, + body: PageTransitionSwitcher( + duration: const Duration(milliseconds: 200), + transitionBuilder: ( + (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( + animation: primaryAnimation, + secondaryAnimation: secondaryAnimation, + child: child, + ) + ), + child: screens[appConfigProvider.selectedScreen].child, + ), bottomNavigationBar: NavigationBar( - selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && widget.navigationShell.currentIndex > 1 + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 ? 0 - : widget.navigationShell.currentIndex, + : appConfigProvider.selectedScreen, onDestinationSelected: (s) => _goBranch(s), destinations: screens.asMap().entries.map((screen) => NavigationDestination( icon: Stack( children: [ Icon( screen.value.icon, - color: widget.navigationShell.currentIndex == screen.key + color: appConfigProvider.selectedScreen == screen.key ? Theme.of(context).colorScheme.onSecondaryContainer : Theme.of(context).colorScheme.onSurfaceVariant, ), diff --git a/pubspec.lock b/pubspec.lock index a194327..cb2cff6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -318,14 +318,6 @@ packages: description: flutter source: sdk version: "0.0.0" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: e156bc1b2088eb5ece9351bccd48c3e1719a4858eacbd44e59162e98a68205d1 - url: "https://pub.dev" - source: hosted - version: "12.0.1" html: dependency: "direct main" description: @@ -398,14 +390,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" - logging: - dependency: transitive - description: - name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.dev" - source: hosted - version: "1.2.0" markdown: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 06ae67d..778459c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -74,7 +74,6 @@ dependencies: flutter_dotenv: ^5.0.2 flutter_reorderable_list: ^1.3.1 pie_chart: ^5.3.2 - go_router: ^12.0.1 flutter_hooks: ^0.20.3 dev_dependencies: From 9b4cb09dc204e44970d11c4fdfce0fe2473f4ea7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 15:53:47 +0100 Subject: [PATCH 353/676] Changed segmented buttons --- lib/screens/filters/add_custom_rule.dart | 40 ++++++++++---------- lib/widgets/add_server/add_server_modal.dart | 35 +++++++++-------- pubspec.lock | 10 ++++- pubspec.yaml | 1 + 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/lib/screens/filters/add_custom_rule.dart b/lib/screens/filters/add_custom_rule.dart index 4b79fc4..c7e5bcd 100644 --- a/lib/screens/filters/add_custom_rule.dart +++ b/lib/screens/filters/add_custom_rule.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:segmented_button_slide/segmented_button_slide.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; @@ -124,25 +125,26 @@ class _AddCustomRuleState extends State { ), ), Container(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: SegmentedButton( - segments: [ - ButtonSegment( - value: BlockingPresets.block, - label: Text(AppLocalizations.of(context)!.block) - ), - ButtonSegment( - value: BlockingPresets.unblock, - label: Text(AppLocalizations.of(context)!.unblock) - ), - ButtonSegment( - value: BlockingPresets.custom, - label: Text(AppLocalizations.of(context)!.custom) - ), - ], - selected: {preset}, - onSelectionChanged: (value) => setState(() => preset = value.first), + SegmentedButtonSlide( + entries: [ + SegmentedButtonSlideEntry(label: AppLocalizations.of(context)!.block), + SegmentedButtonSlideEntry(label: AppLocalizations.of(context)!.unblock), + SegmentedButtonSlideEntry(label: AppLocalizations.of(context)!.custom), + ], + selectedEntry: preset.index, + onChange: (v) => setState(() => preset = BlockingPresets.values[v]), + colors: SegmentedButtonSlideColors( + barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), + backgroundSelectedColor: Theme.of(context).colorScheme.primary, + foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, + foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, + hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, + ), + textOverflow: TextOverflow.ellipsis, + fontSize: 14, + height: 40, + margin: const EdgeInsets.symmetric( + horizontal: 24, ), ), Container(height: 20), diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index c587c7e..511d367 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -2,6 +2,7 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; +import 'package:segmented_button_slide/segmented_button_slide.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -371,21 +372,25 @@ class _AddServerModalState extends State { label: AppLocalizations.of(context)!.connection, padding: const EdgeInsets.all(24), ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: SegmentedButton( - segments: const [ - ButtonSegment( - value: ConnectionType.http, - label: Text("HTTP") - ), - ButtonSegment( - value: ConnectionType.https, - label: Text("HTTPS") - ), - ], - selected: {connectionType}, - onSelectionChanged: (value) => setState(() => connectionType = value.first), + SegmentedButtonSlide( + entries: const [ + SegmentedButtonSlideEntry(label: "HTTP"), + SegmentedButtonSlideEntry(label: "HTTPS"), + ], + selectedEntry: connectionType.index, + onChange: (v) => setState(() => connectionType = ConnectionType.values[v]), + colors: SegmentedButtonSlideColors( + barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), + backgroundSelectedColor: Theme.of(context).colorScheme.primary, + foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, + foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, + hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, + ), + textOverflow: TextOverflow.ellipsis, + fontSize: 14, + height: 40, + margin: const EdgeInsets.symmetric( + horizontal: 24, ), ), const SizedBox(height: 30), diff --git a/pubspec.lock b/pubspec.lock index cb2cff6..0741c5f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -518,6 +518,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.5" + segmented_button_slide: + dependency: "direct main" + description: + name: segmented_button_slide + sha256: "96d67344fa65f6b98a317d930bfd4e81e47c4f9e3e2ab1ee8925b55f72cded13" + url: "https://pub.dev" + source: hosted + version: "1.0.4" sentry: dependency: transitive description: @@ -789,5 +797,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0 <4.0.0" + dart: ">=3.1.3 <4.0.0" flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 778459c..7fcccf0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -75,6 +75,7 @@ dependencies: flutter_reorderable_list: ^1.3.1 pie_chart: ^5.3.2 flutter_hooks: ^0.20.3 + segmented_button_slide: ^1.0.4 dev_dependencies: flutter_test: From d2c7866f0af813a38638b5a689daac83358a7cb5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 15:57:47 +0100 Subject: [PATCH 354/676] Fixed overlay style --- lib/main.dart | 100 +++++------ lib/widgets/layout.dart | 214 ++++++++++++----------- lib/widgets/system_ui_overlay_style.dart | 31 ++++ 3 files changed, 183 insertions(+), 162 deletions(-) create mode 100644 lib/widgets/system_ui_overlay_style.dart diff --git a/lib/main.dart b/lib/main.dart index f34459f..b2bb30d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:provider/provider.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; @@ -230,64 +229,49 @@ class _MainState extends State
with WidgetsBindingObserver { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - return AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarColor: Colors.transparent, - statusBarBrightness: Theme.of(context).brightness == Brightness.light - ? Brightness.light - : Brightness.dark, - statusBarIconBrightness: Theme.of(context).brightness == Brightness.light - ? Brightness.dark - : Brightness.light, - systemNavigationBarColor: Theme.of(context).scaffoldBackgroundColor, - systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light - ? Brightness.dark - : Brightness.light, - ), - child: DynamicColorBuilder( - builder: (lightDynamic, darkDynamic) => MaterialApp( - title: 'AdGuard Home Manager', - theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? lightTheme(lightDynamic) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]), - darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? darkTheme(darkDynamic) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]), - themeMode: appConfigProvider.selectedTheme, - debugShowCheckedModeBanner: false, - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - AppLocalizations.delegate, - ], - supportedLocales: const [ - Locale('en', ''), - Locale('es', ''), - Locale('zh', ''), - Locale('zh', 'CN'), - Locale('pl', ''), - Locale('tr', '') - ], - scaffoldMessengerKey: scaffoldMessengerKey, - builder: (context, child) { - return CustomMenuBar( - child: MediaQuery( - data: MediaQuery.of(context).copyWith( - textScaleFactor: !(Platform.isAndroid || Platform.isIOS) - ? 0.9 - : 1.0 - ), - child: child!, + return DynamicColorBuilder( + builder: (lightDynamic, darkDynamic) => MaterialApp( + title: 'AdGuard Home Manager', + theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 + ? appConfigProvider.useDynamicColor == true + ? lightTheme(lightDynamic) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]), + darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 + ? appConfigProvider.useDynamicColor == true + ? darkTheme(darkDynamic) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]), + themeMode: appConfigProvider.selectedTheme, + debugShowCheckedModeBanner: false, + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + AppLocalizations.delegate, + ], + supportedLocales: const [ + Locale('en', ''), + Locale('es', ''), + Locale('zh', ''), + Locale('zh', 'CN'), + Locale('pl', ''), + Locale('tr', '') + ], + scaffoldMessengerKey: scaffoldMessengerKey, + builder: (context, child) { + return CustomMenuBar( + child: MediaQuery( + data: MediaQuery.of(context).copyWith( + textScaleFactor: !(Platform.isAndroid || Platform.isIOS) + ? 0.9 + : 1.0 ), - ); - }, - home: Layout(), - ), + child: child!, + ), + ); + }, + home: const Layout(), ), ); } diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index a7da996..8edcd56 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -3,6 +3,8 @@ import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/system_ui_overlay_style.dart'; + import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; import 'package:adguard_home_manager/config/sizes.dart'; @@ -61,70 +63,72 @@ class _LayoutState extends State { } if (width > desktopBreakpoint) { - return Material( - child: Row( - children: [ - AnimatedContainer( - duration: const Duration(milliseconds: 250), - curve: Curves.ease, - width: _drawerExpanded ? 250 : 90, - child: ListView( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 16 + return OverlayStyle( + child: Material( + child: Row( + children: [ + AnimatedContainer( + duration: const Duration(milliseconds: 250), + curve: Curves.ease, + width: _drawerExpanded ? 250 : 90, + child: ListView( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 16 + ), + child: IconButton( + onPressed: () => setState(() => _drawerExpanded = !_drawerExpanded), + icon: const Icon(Icons.menu_open_rounded), + tooltip: _drawerExpanded == true + ? AppLocalizations.of(context)!.closeMenu + : AppLocalizations.of(context)!.openMenu, + ), ), - child: IconButton( - onPressed: () => setState(() => _drawerExpanded = !_drawerExpanded), - icon: const Icon(Icons.menu_open_rounded), - tooltip: _drawerExpanded == true - ? AppLocalizations.of(context)!.closeMenu - : AppLocalizations.of(context)!.openMenu, + ], + ), + if (serversProvider.selectedServer != null) + ...screensServerConnected.asMap().entries.map( + (s) => DrawerTile( + icon: s.value.icon, + title: translatedName(s.value.name), + isSelected: appConfigProvider.selectedScreen == s.key, + onSelect: () => _goBranch(s.key), + withoutTitle: !_drawerExpanded, ), ), - ], - ), - if (serversProvider.selectedServer != null) - ...screensServerConnected.asMap().entries.map( - (s) => DrawerTile( - icon: s.value.icon, - title: translatedName(s.value.name), - isSelected: appConfigProvider.selectedScreen == s.key, - onSelect: () => _goBranch(s.key), - withoutTitle: !_drawerExpanded, + if (serversProvider.selectedServer == null) + ...screensSelectServer.asMap().entries.map( + (s) => DrawerTile( + icon: s.value.icon, + title: translatedName(s.value.name), + isSelected: appConfigProvider.selectedScreen == s.key, + onSelect: () => _goBranch(s.key), + withoutTitle: !_drawerExpanded, + ), ), - ), - if (serversProvider.selectedServer == null) - ...screensSelectServer.asMap().entries.map( - (s) => DrawerTile( - icon: s.value.icon, - title: translatedName(s.value.name), - isSelected: appConfigProvider.selectedScreen == s.key, - onSelect: () => _goBranch(s.key), - withoutTitle: !_drawerExpanded, - ), - ), - ], - ), - ), - Expanded( - child: PageTransitionSwitcher( - duration: const Duration(milliseconds: 200), - transitionBuilder: ( - (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( - animation: primaryAnimation, - secondaryAnimation: secondaryAnimation, - child: child, - ) + ], ), - child: screens[appConfigProvider.selectedScreen].child, ), - ), - ], + Expanded( + child: PageTransitionSwitcher( + duration: const Duration(milliseconds: 200), + transitionBuilder: ( + (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( + animation: primaryAnimation, + secondaryAnimation: secondaryAnimation, + child: child, + ) + ), + child: screens[appConfigProvider.selectedScreen].child, + ), + ), + ], + ), ), ); } @@ -133,54 +137,56 @@ class _LayoutState extends State { ? screensServerConnected : screensSelectServer; - return Scaffold( - body: PageTransitionSwitcher( - duration: const Duration(milliseconds: 200), - transitionBuilder: ( - (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( - animation: primaryAnimation, - secondaryAnimation: secondaryAnimation, - child: child, - ) + return OverlayStyle( + child: Scaffold( + body: PageTransitionSwitcher( + duration: const Duration(milliseconds: 200), + transitionBuilder: ( + (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( + animation: primaryAnimation, + secondaryAnimation: secondaryAnimation, + child: child, + ) + ), + child: screens[appConfigProvider.selectedScreen].child, ), - child: screens[appConfigProvider.selectedScreen].child, - ), - bottomNavigationBar: NavigationBar( - selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 - ? 0 - : appConfigProvider.selectedScreen, - onDestinationSelected: (s) => _goBranch(s), - destinations: screens.asMap().entries.map((screen) => NavigationDestination( - icon: Stack( - children: [ - Icon( - screen.value.icon, - color: appConfigProvider.selectedScreen == screen.key - ? Theme.of(context).colorScheme.onSecondaryContainer - : Theme.of(context).colorScheme.onSurfaceVariant, - ), - if ( - screen.value.name == 'settings' && - serversProvider.updateAvailable.data != null && - serversProvider.updateAvailable.data!.canAutoupdate == true - ) Positioned( - bottom: 0, - right: -12, - child: Container( - width: 10, - height: 10, - margin: const EdgeInsets.only(right: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.red + bottomNavigationBar: NavigationBar( + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 + ? 0 + : appConfigProvider.selectedScreen, + onDestinationSelected: (s) => _goBranch(s), + destinations: screens.asMap().entries.map((screen) => NavigationDestination( + icon: Stack( + children: [ + Icon( + screen.value.icon, + color: appConfigProvider.selectedScreen == screen.key + ? Theme.of(context).colorScheme.onSecondaryContainer + : Theme.of(context).colorScheme.onSurfaceVariant, + ), + if ( + screen.value.name == 'settings' && + serversProvider.updateAvailable.data != null && + serversProvider.updateAvailable.data!.canAutoupdate == true + ) Positioned( + bottom: 0, + right: -12, + child: Container( + width: 10, + height: 10, + margin: const EdgeInsets.only(right: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.red + ), ), - ), - ) - ], - ), - label: translatedName(screen.value.name) - )).toList(), - ) + ) + ], + ), + label: translatedName(screen.value.name) + )).toList(), + ) + ), ); } } diff --git a/lib/widgets/system_ui_overlay_style.dart b/lib/widgets/system_ui_overlay_style.dart new file mode 100644 index 0000000..8ceaf4b --- /dev/null +++ b/lib/widgets/system_ui_overlay_style.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class OverlayStyle extends StatelessWidget { + final Widget child; + + const OverlayStyle({ + Key? key, + required this.child + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarBrightness: Theme.of(context).brightness == Brightness.light + ? Brightness.light + : Brightness.dark, + statusBarIconBrightness: Theme.of(context).brightness == Brightness.light + ? Brightness.dark + : Brightness.light, + systemNavigationBarColor: Theme.of(context).scaffoldBackgroundColor, + systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light + ? Brightness.dark + : Brightness.light, + ), + child: child, + ); + } +} \ No newline at end of file From 4d22d8a0a9ae230c122b82ab7afab09f97d526f7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 19:27:01 +0100 Subject: [PATCH 355/676] Added sign macos app actions --- .github/workflows/release-stable.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index cfebecd..42ff984 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -75,6 +75,20 @@ jobs: - run: flutter clean - run: flutter pub get - run: flutter build macos --release + - name: Install the Apple certificate and sign the application + env: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PWD: ${{ secrets.APPLE_CERTIFICATE_PWD }} + APPLE_KEYCHAIN_PWD: ${{ secrets.APPLE_KEYCHAIN_PWD }} + APPLE_IDENTITY_ID: ${{ secrets.APPLE_IDENTITY_ID }} + run: | + echo $APPLE_CERTIFICATE | base64 —decode > certificate.p12 + security create-keychain -p $APPLE_KEYCHAIN_PWD build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p $APPLE_KEYCHAIN_PWD build.keychain + security import certificate.p12 -k build.keychain -P $APPLE_CERTIFICATE_PWD -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $APPLE_KEYCHAIN_PWD build.keychain + /usr/bin/codesign --force -s "$APPLE_IDENTITY_ID" $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager.app -v - name: Create folder to build dmg run: mkdir $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager - name: Copy app into folder From eca69a79903b4abf694ecb90be3ce90ff59799a1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 19:36:33 +0100 Subject: [PATCH 356/676] Fix job --- .github/workflows/release-stable.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 42ff984..e61eb21 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -82,7 +82,7 @@ jobs: APPLE_KEYCHAIN_PWD: ${{ secrets.APPLE_KEYCHAIN_PWD }} APPLE_IDENTITY_ID: ${{ secrets.APPLE_IDENTITY_ID }} run: | - echo $APPLE_CERTIFICATE | base64 —decode > certificate.p12 + echo $APPLE_CERTIFICATE | base64 -—decode > certificate.p12 security create-keychain -p $APPLE_KEYCHAIN_PWD build.keychain security default-keychain -s build.keychain security unlock-keychain -p $APPLE_KEYCHAIN_PWD build.keychain From 557a9242e780fa7770d7e84e243a822123653d9d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 19:48:35 +0100 Subject: [PATCH 357/676] Fix job --- .github/workflows/release-stable.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index e61eb21..e8b6de0 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -82,7 +82,7 @@ jobs: APPLE_KEYCHAIN_PWD: ${{ secrets.APPLE_KEYCHAIN_PWD }} APPLE_IDENTITY_ID: ${{ secrets.APPLE_IDENTITY_ID }} run: | - echo $APPLE_CERTIFICATE | base64 -—decode > certificate.p12 + echo "$APPLE_CERTIFICATE" | base64 -—decode > certificate.p12 security create-keychain -p $APPLE_KEYCHAIN_PWD build.keychain security default-keychain -s build.keychain security unlock-keychain -p $APPLE_KEYCHAIN_PWD build.keychain From f7260e5ffbf73997d99e3eb141ed01dd453d6ff4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 29 Oct 2023 20:05:37 +0100 Subject: [PATCH 358/676] Fix job --- .github/workflows/release-stable.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index e8b6de0..b8d2b73 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -82,7 +82,7 @@ jobs: APPLE_KEYCHAIN_PWD: ${{ secrets.APPLE_KEYCHAIN_PWD }} APPLE_IDENTITY_ID: ${{ secrets.APPLE_IDENTITY_ID }} run: | - echo "$APPLE_CERTIFICATE" | base64 -—decode > certificate.p12 + echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12 security create-keychain -p $APPLE_KEYCHAIN_PWD build.keychain security default-keychain -s build.keychain security unlock-keychain -p $APPLE_KEYCHAIN_PWD build.keychain From 05e5255467960827d0c2bedf0cfb1f2e1a6ddfe5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 1 Nov 2023 15:43:19 +0100 Subject: [PATCH 359/676] 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( From 9bca87a4f24b3c7f9e70039eb43f9820b1949b42 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 1 Nov 2023 15:43:33 +0100 Subject: [PATCH 360/676] Updated iOS stuff --- ios/Podfile.lock | 52 +++++++++++++++++-- ios/Runner.xcodeproj/project.pbxproj | 3 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 9a238fd..ed1a57c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -11,11 +11,35 @@ PODS: - FMDB/standard (2.7.5) - package_info_plus (0.4.5): - Flutter - - sqflite (0.0.2): + - Sentry/HybridSDK (8.9.1): + - SentryPrivate (= 8.9.1) + - sentry_flutter (0.0.1): + - Flutter + - FlutterMacOS + - Sentry/HybridSDK (= 8.9.1) + - SentryPrivate (8.9.1) + - sqflite (0.0.3): - Flutter - FMDB (>= 2.7.5) + - sqlite3 (3.43.1): + - sqlite3/common (= 3.43.1) + - sqlite3/common (3.43.1) + - sqlite3/fts5 (3.43.1): + - sqlite3/common + - sqlite3/perf-threadsafe (3.43.1): + - sqlite3/common + - sqlite3/rtree (3.43.1): + - sqlite3/common + - sqlite3_flutter_libs (0.0.1): + - Flutter + - sqlite3 (~> 3.43.0) + - sqlite3/fts5 + - sqlite3/perf-threadsafe + - sqlite3/rtree - store_checker (0.0.1): - Flutter + - url_launcher_ios (0.0.1): + - Flutter DEPENDENCIES: - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) @@ -23,12 +47,18 @@ DEPENDENCIES: - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_web_browser (from `.symlinks/plugins/flutter_web_browser/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) + - sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`) - sqflite (from `.symlinks/plugins/sqflite/ios`) + - sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`) - store_checker (from `.symlinks/plugins/store_checker/ios`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) SPEC REPOS: trunk: - FMDB + - Sentry + - SentryPrivate + - sqlite3 EXTERNAL SOURCES: device_info_plus: @@ -41,21 +71,33 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_web_browser/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" + sentry_flutter: + :path: ".symlinks/plugins/sentry_flutter/ios" sqflite: :path: ".symlinks/plugins/sqflite/ios" + sqlite3_flutter_libs: + :path: ".symlinks/plugins/sqlite3_flutter_libs/ios" store_checker: :path: ".symlinks/plugins/store_checker/ios" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: - device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed + device_info_plus: 7545d84d8d1b896cb16a4ff98c19f07ec4b298ea Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef flutter_web_browser: 7bccaafbb0c5b8862afe7bcd158f15557109f61f FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e - sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 + package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 + Sentry: e3203780941722a1fcfee99e351de14244c7f806 + sentry_flutter: 8f0ffd53088e6a4d50c095852c5cad9e4405025c + SentryPrivate: 5e3683390f66611fc7c6215e27645873adb55d13 + sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a + sqlite3: e0a0623a33a20a47cb5921552aebc6e9e437dc91 + sqlite3_flutter_libs: 878ccbdcfd7b7cb41a774ec238223d876880c5ec store_checker: 359c5051d9ec30ff0a8fa39eb5ec9df021bb745d + url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.11.2 +COCOAPODS: 1.12.1 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 7d212ec..4f766b9 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -156,7 +156,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -222,6 +222,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a..a6b826d 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Date: Wed, 1 Nov 2023 18:52:30 +0100 Subject: [PATCH 361/676] Refactor code --- lib/screens/logs/clients_modal.dart | 315 ++++++++++-------- lib/screens/logs/logs.dart | 2 - lib/screens/logs/logs_filters_modal.dart | 403 +++++++++++------------ lib/screens/logs/logs_list.dart | 293 +--------------- lib/screens/logs/logs_list_appbar.dart | 317 ++++++++++++++++++ 5 files changed, 693 insertions(+), 637 deletions(-) create mode 100644 lib/screens/logs/logs_list_appbar.dart diff --git a/lib/screens/logs/clients_modal.dart b/lib/screens/logs/clients_modal.dart index fcd9d74..7bb0574 100644 --- a/lib/screens/logs/clients_modal.dart +++ b/lib/screens/logs/clients_modal.dart @@ -32,156 +32,18 @@ class _ClientsModalState extends State { @override Widget build(BuildContext context) { - final logsProvider = Provider.of(context); - final clientsProvider = Provider.of(context); - final height = MediaQuery.of(context).size.height; - void apply() async { - logsProvider.setSelectedClients( - selectedClients.isNotEmpty ? selectedClients : null - ); - - Navigator.pop(context); - } - - Widget listItem({ - required String label, - required void Function() onChanged - }) { - return Material( - color: Colors.transparent, - child: InkWell( - onTap: () => onChanged(), - child: Padding( - padding: const EdgeInsets.only( - left: 24, - top: 8, - right: 12, - bottom: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Text( - label, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - Checkbox( - value: selectedClients.contains(label), - onChanged: (_) => onChanged(), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5) - ), - ) - ], - ), - ), - ), - ); - } - - void selectAll() { - setState(() { - selectedClients = clientsProvider.clients!.autoClients.map((item) => item.ip).toList(); - }); - } - - void unselectAll() { - setState(() { - selectedClients = []; - }); - } - - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 24, - bottom: 16, - ), - child: Icon( - Icons.smartphone_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Text( - AppLocalizations.of(context)!.clients, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - ], - ), - Flexible( - child: ListView.builder( - itemCount: clientsProvider.clients!.autoClients.length, - itemBuilder: (context, index) => listItem( - label: clientsProvider.clients!.autoClients[index].ip, - onChanged: () { - if (selectedClients.contains(clientsProvider.clients!.autoClients[index].ip)) { - setState(() { - selectedClients = selectedClients.where( - (item) => item != clientsProvider.clients!.autoClients[index].ip - ).toList(); - }); - } - else { - setState(() { - selectedClients.add(clientsProvider.clients!.autoClients[index].ip); - }); - } - } - ) - ) - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: selectedClients.length == clientsProvider.clients!.autoClients.length - ? () => unselectAll() - : () => selectAll(), - child: Text( - selectedClients.length == clientsProvider.clients!.autoClients.length - ? AppLocalizations.of(context)!.unselectAll - : AppLocalizations.of(context)!.selectAll - ) - ), - TextButton( - onPressed: apply, - child: Text(AppLocalizations.of(context)!.apply) - ) - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ); - } - if (widget.dialog == true) { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( maxWidth: 500 ), - child: content() + child: _ModalContent( + selectedClients: selectedClients, + onClientsSelected: (v) => setState(() => selectedClients = v), + ) ), ); } @@ -198,9 +60,176 @@ class _ClientsModalState extends State { ), color: Theme.of(context).dialogBackgroundColor ), - child: content() + child: _ModalContent( + selectedClients: selectedClients, + onClientsSelected: (v) => setState(() => selectedClients = v), + ) ), ); } } +} + +class _ModalContent extends StatelessWidget { + final List selectedClients; + final void Function(List) onClientsSelected; + + const _ModalContent({ + Key? key, + required this.selectedClients, + required this.onClientsSelected, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final clientsProvider = Provider.of(context); + final logsProvider = Provider.of(context); + + void apply() async { + logsProvider.setSelectedClients( + selectedClients.isNotEmpty ? selectedClients : null + ); + + Navigator.pop(context); + } + + void selectAll() { + onClientsSelected( + clientsProvider.clients!.autoClients.map((item) => item.ip).toList() + ); + } + + void unselectAll() { + onClientsSelected([]); + } + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 24, + bottom: 16, + ), + child: Icon( + Icons.smartphone_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + Text( + AppLocalizations.of(context)!.clients, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + Flexible( + child: ListView.builder( + itemCount: clientsProvider.clients!.autoClients.length, + itemBuilder: (context, index) => _ListItem( + label: clientsProvider.clients!.autoClients[index].ip, + checkboxActive: selectedClients.contains(clientsProvider.clients!.autoClients[index].ip), + onChanged: (isSelected) { + if (isSelected == true) { + onClientsSelected([ + ...selectedClients, + clientsProvider.clients!.autoClients[index].ip + ]); + } + else { + onClientsSelected( + selectedClients.where( + (item) => item != clientsProvider.clients!.autoClients[index].ip + ).toList() + ); + } + } + ) + ) + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: selectedClients.length == clientsProvider.clients!.autoClients.length + ? () => unselectAll() + : () => selectAll(), + child: Text( + selectedClients.length == clientsProvider.clients!.autoClients.length + ? AppLocalizations.of(context)!.unselectAll + : AppLocalizations.of(context)!.selectAll + ) + ), + TextButton( + onPressed: apply, + child: Text(AppLocalizations.of(context)!.apply) + ) + ], + ), + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); + } +} + +class _ListItem extends StatelessWidget { + final String label; + final bool checkboxActive; + final void Function(bool) onChanged; + + const _ListItem({ + Key? key, + required this.label, + required this.checkboxActive, + required this.onChanged, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () => onChanged(!checkboxActive), + child: Padding( + padding: const EdgeInsets.only( + left: 24, + top: 8, + right: 12, + bottom: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + label, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ), + Checkbox( + value: checkboxActive, + onChanged: (v) => onChanged(!checkboxActive), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + ) + ], + ), + ), + ), + ); + } } \ No newline at end of file diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index b218ad7..863f93d 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -18,8 +18,6 @@ class _LogsState extends State { @override Widget build(BuildContext context) { - - return LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 1000) { diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/logs_filters_modal.dart index 8f1d7f0..e41efa5 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/logs_filters_modal.dart @@ -15,7 +15,7 @@ import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; -class LogsFiltersModal extends StatelessWidget { +class LogsFiltersModal extends StatefulWidget { final bool dialog; const LogsFiltersModal({ @@ -24,39 +24,67 @@ class LogsFiltersModal extends StatelessWidget { }) : super(key: key); @override - Widget build(BuildContext context) { - final logsProvider = Provider.of(context); - - return LogsFiltersModalWidget( - logsProvider: logsProvider, - dialog: dialog, - ); - } + State createState() => _LogsFiltersModalState(); } -class LogsFiltersModalWidget extends StatefulWidget { - final LogsProvider logsProvider; - final bool dialog; - - const LogsFiltersModalWidget({ - Key? key, - required this.logsProvider, - required this.dialog - }) : super(key: key); - - @override - State createState() => _LogsFiltersModalWidgetState(); -} - -class _LogsFiltersModalWidgetState extends State { +class _LogsFiltersModalState extends State { TextEditingController searchController = TextEditingController(); @override void initState() { - searchController.text = widget.logsProvider.searchText ?? ''; + searchController.text = Provider.of(context, listen: false).searchText ?? ''; super.initState(); } + @override + Widget build(BuildContext context) { + if (widget.dialog == true) { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: _FiltersList( + searchController: searchController, + onClearSearch: () => setState(() => searchController.text = "") + ) + ) + ), + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).dialogBackgroundColor, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ) + ), + child: _FiltersList( + searchController: searchController, + onClearSearch: () => setState(() => searchController.text = "") + ) + ), + ); + } + } +} + +class _FiltersList extends StatelessWidget { + final TextEditingController searchController; + final void Function() onClearSearch; + + const _FiltersList({ + Key? key, + required this.searchController, + required this.onClearSearch, + }) : super(key: key); + @override Widget build(BuildContext context) { final logsProvider = Provider.of(context); @@ -125,200 +153,167 @@ class _LogsFiltersModalWidgetState extends State { } } - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 24, - bottom: 16, - ), - child: Icon( - Icons.filter_list_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Text( - AppLocalizations.of(context)!.filters, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - height: 1.3, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - ], - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( children: [ - Expanded( - child: TextFormField( - controller: searchController, - onChanged: logsProvider.setSearchText, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.search_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.search, - suffixIcon: IconButton( - onPressed: () { - setState(() { - searchController.text = ''; - }); - logsProvider.setSearchText(null); - }, - icon: const Icon(Icons.clear) - ), - ), + Padding( + padding: const EdgeInsets.only( + top: 24, + bottom: 16, ), - ) + child: Icon( + Icons.filter_list_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + Text( + AppLocalizations.of(context)!.filters, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w400, + height: 1.3, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), ], ), - ), - Container(height: 16), - CustomListTile( - title: AppLocalizations.of(context)!.client, - subtitle: logsProvider.selectedClients != null - ? "${logsProvider.selectedClients!.length} ${AppLocalizations.of(context)!.clientsSelected}" - : AppLocalizations.of(context)!.all, - onTap: clientsProvider.loadStatus == LoadStatus.loaded - ? openSelectClients - : null, - disabled: clientsProvider.loadStatus != LoadStatus.loaded, - icon: Icons.smartphone_rounded, - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - trailing: clientsProvider.loadStatus == LoadStatus.loading - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Row( + children: [ + Expanded( + child: TextFormField( + controller: searchController, + onChanged: logsProvider.setSearchText, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.search_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.search, + suffixIcon: IconButton( + onPressed: () { + onClearSearch(); + logsProvider.setSearchText(null); + }, + icon: const Icon(Icons.clear) + ), + ), ), ) - : clientsProvider.loadStatus == LoadStatus.error - ? const Icon( - Icons.error_rounded, - color: Colors.red, - ) - : null, - ), - SectionLabel( - label: AppLocalizations.of(context)!.quickFilters, - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 16 - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - FilterChip( - selected: logsProvider.selectedResultStatus == "all", - label: Text(AppLocalizations.of(context)!.all), - onSelected: (_) => logsProvider.setSelectedResultStatus("all") - ), - FilterChip( - selected: logsProvider.selectedResultStatus == "processed" || - logsProvider.selectedResultStatus == "whitelisted", - label: Text(AppLocalizations.of(context)!.allowed), - onSelected: (_) => logsProvider.setSelectedResultStatus("processed") - ), - FilterChip( - selected: logsProvider.selectedResultStatus == "blocked" || - logsProvider.selectedResultStatus == "blocked_safebrowsing" || - logsProvider.selectedResultStatus == "blocked_parental" || - logsProvider.selectedResultStatus == "safe_search", - label: Text(AppLocalizations.of(context)!.blocked), - onSelected: (_) => logsProvider.setSelectedResultStatus("blocked") - ), ], ), - const Padding(padding: EdgeInsets.all(8)), - CustomListTile( - title: AppLocalizations.of(context)!.responseStatus, - subtitle: "${translatedString[logsProvider.selectedResultStatus]}", - onTap: openSelectFilterStatus, - icon: Icons.shield_rounded, - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: () { - searchController.text = ""; - logsProvider.requestResetFilters(); - }, - child: Text(AppLocalizations.of(context)!.resetFilters) ), - TextButton( - onPressed: () { - Navigator.pop(context); - logsProvider.filterLogs(); - }, - child: Text(AppLocalizations.of(context)!.apply) + Container(height: 16), + CustomListTile( + title: AppLocalizations.of(context)!.client, + subtitle: logsProvider.selectedClients != null + ? "${logsProvider.selectedClients!.length} ${AppLocalizations.of(context)!.clientsSelected}" + : AppLocalizations.of(context)!.all, + onTap: clientsProvider.loadStatus == LoadStatus.loaded + ? openSelectClients + : null, + disabled: clientsProvider.loadStatus != LoadStatus.loaded, + icon: Icons.smartphone_rounded, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + trailing: clientsProvider.loadStatus == LoadStatus.loading + ? const SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + ), + ) + : clientsProvider.loadStatus == LoadStatus.error + ? const Icon( + Icons.error_rounded, + color: Colors.red, + ) + : null, + ), + SectionLabel( + label: AppLocalizations.of(context)!.quickFilters, + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 16 + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + FilterChip( + selected: logsProvider.selectedResultStatus == "all", + label: Text(AppLocalizations.of(context)!.all), + onSelected: (_) => logsProvider.setSelectedResultStatus("all") + ), + FilterChip( + selected: logsProvider.selectedResultStatus == "processed" || + logsProvider.selectedResultStatus == "whitelisted", + label: Text(AppLocalizations.of(context)!.allowed), + onSelected: (_) => logsProvider.setSelectedResultStatus("processed") + ), + FilterChip( + selected: logsProvider.selectedResultStatus == "blocked" || + logsProvider.selectedResultStatus == "blocked_safebrowsing" || + logsProvider.selectedResultStatus == "blocked_parental" || + logsProvider.selectedResultStatus == "safe_search", + label: Text(AppLocalizations.of(context)!.blocked), + onSelected: (_) => logsProvider.setSelectedResultStatus("blocked") + ), + ], + ), + const Padding(padding: EdgeInsets.all(8)), + CustomListTile( + title: AppLocalizations.of(context)!.responseStatus, + subtitle: "${translatedString[logsProvider.selectedResultStatus]}", + onTap: openSelectFilterStatus, + icon: Icons.shield_rounded, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), ), ], ), ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ); - } - - if (widget.dialog == true) { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: content() - ) ), - ); - } - else { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ) + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () { + searchController.text = ""; + logsProvider.requestResetFilters(); + }, + child: Text(AppLocalizations.of(context)!.resetFilters) + ), + TextButton( + onPressed: () { + Navigator.pop(context); + logsProvider.filterLogs(); + }, + child: Text(AppLocalizations.of(context)!.apply) + ), + ], ), - child: content() ), - ); - } + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); } } \ No newline at end of file diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart index b04fe74..72978ce 100644 --- a/lib/screens/logs/logs_list.dart +++ b/lib/screens/logs/logs_list.dart @@ -1,27 +1,19 @@ // ignore_for_file: use_build_context_synchronously -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/logs/log_details_screen.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; -import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart'; -import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart'; +import 'package:adguard_home_manager/screens/logs/logs_list_appbar.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; -import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; class LogsListWidget extends StatefulWidget { @@ -99,292 +91,17 @@ class _LogsListWidgetState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); - - final width = MediaQuery.of(context).size.width; - - void updateConfig(Map data) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.updatingSettings); - - final result = serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? await serversProvider.apiClient!.updateQueryLogParameters(data: data) - : await serversProvider.apiClient!.updateQueryLogParametersLegacy(data: data); - - processModal.close(); - - if (result['result'] == 'success') { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsConfigUpdated, - color: Colors.green - ); - } - else { - appConfigProvider.addLog(result['log']); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsConfigNotUpdated, - color: Colors.red - ); - } - } - - void clearQueries() async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.updatingSettings); - - final result = await serversProvider.apiClient!.clearLogs(); - - processModal.close(); - - if (result['result'] == 'success') { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsCleared, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsNotCleared, - color: Colors.red - ); - } - } - - - void openFilersModal() { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => const LogsFiltersModal( - dialog: true, - ), - barrierDismissible: false - ); - } - else { - showModalBottomSheet( - context: context, - useRootNavigator: true, - builder: (context) => const LogsFiltersModal( - dialog: false, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ); - } - } - - final Map translatedString = { - "all": AppLocalizations.of(context)!.all, - "filtered": AppLocalizations.of(context)!.filtered, - "processed": AppLocalizations.of(context)!.processedRow, - "whitelisted": AppLocalizations.of(context)!.processedWhitelistRow, - "blocked": AppLocalizations.of(context)!.blocked, - "blocked_safebrowsing": AppLocalizations.of(context)!.blockedSafeBrowsingRow, - "blocked_parental": AppLocalizations.of(context)!.blockedParentalRow, - "safe_search": AppLocalizations.of(context)!.safeSearch, - }; return Scaffold( body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - surfaceTintColor: isDesktop(width) ? Colors.transparent : null, - title: Text(AppLocalizations.of(context)!.logs), - expandedHeight: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null - ? 170 : null, - actions: [ - if (!(Platform.isAndroid || Platform.isIOS)) IconButton( - onPressed: () => logsProvider.fetchLogs(inOffset: 0), - icon: const Icon(Icons.refresh_rounded), - tooltip: AppLocalizations.of(context)!.refresh, - ), - logsProvider.loadStatus == LoadStatus.loaded - ? IconButton( - onPressed: openFilersModal, - icon: const Icon(Icons.filter_list_rounded), - tooltip: AppLocalizations.of(context)!.filters, - ) - : const SizedBox(), - if (statusProvider.serverStatus != null) IconButton( - tooltip: AppLocalizations.of(context)!.settings, - onPressed: () => { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => LogsConfigModal( - onConfirm: updateConfig, - onClear: clearQueries, - dialog: true, - serverVersion: statusProvider.serverStatus!.serverVersion, - ), - barrierDismissible: false - ) - } - else { - showModalBottomSheet( - context: context, - useRootNavigator: true, - builder: (context) => LogsConfigModal( - onConfirm: updateConfig, - onClear: clearQueries, - dialog: false, - serverVersion: statusProvider.serverStatus!.serverVersion, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ) - } - }, - icon: const Icon(Icons.settings) - ), - const SizedBox(width: 5), - ], - bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null - ? PreferredSize( - preferredSize: const Size(double.maxFinite, 70), - child: Container( - height: 50, - width: double.maxFinite, - padding: const EdgeInsets.only(bottom: 10), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: showDivider == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.1) - : Colors.transparent, - ) - ) - ), - child: ListView( - scrollDirection: Axis.horizontal, - children: [ - if (logsProvider.appliedFilters.searchText != null) ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.search_rounded, - ), - label: Row( - children: [ - Text( - logsProvider.appliedFilters.searchText!, - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: null, - clients: logsProvider.appliedFilters.clients - ) - ); - logsProvider.setSearchText(null); - logsProvider.fetchLogs( - inOffset: 0, - searchText: '' - ); - }, - ), - ], - if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.shield_rounded, - ), - label: Row( - children: [ - Text( - translatedString[logsProvider.appliedFilters.selectedResultStatus]!, - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: logsProvider.appliedFilters.searchText, - clients: logsProvider.appliedFilters.clients - ) - ); - logsProvider.setSelectedResultStatus('all'); - logsProvider.fetchLogs( - inOffset: 0, - responseStatus: 'all' - ); - }, - ), - ], - if (logsProvider.appliedFilters.clients != null) ...[ - const SizedBox(width: 15), - Chip( - avatar: const Icon( - Icons.smartphone_rounded, - ), - label: Row( - children: [ - Text( - logsProvider.appliedFilters.clients!.length == 1 - ? logsProvider.appliedFilters.clients![0] - : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", - ), - ], - ), - deleteIcon: const Icon( - Icons.clear, - size: 18, - ), - onDeleted: () { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: logsProvider.appliedFilters.searchText, - clients: null - ) - ); - logsProvider.setSelectedClients(null); - logsProvider.fetchLogs( - inOffset: 0, - responseStatus: logsProvider.appliedFilters.selectedResultStatus - ); - }, - ), - ], - const SizedBox(width: 15), - ], - ), - ) - ) - : null, - ), + sliver: LogsListAppBar( + innerBoxIsScrolled: innerBoxIsScrolled, + showDivider: showDivider, + ) ) ], body: Builder( diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart new file mode 100644 index 0000000..39b4548 --- /dev/null +++ b/lib/screens/logs/logs_list_appbar.dart @@ -0,0 +1,317 @@ +// ignore_for_file: use_build_context_synchronously + +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/logs/logs_config_modal.dart'; +import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/providers/logs_provider.dart'; + +class LogsListAppBar extends StatelessWidget { + final bool innerBoxIsScrolled; + final bool showDivider; + + const LogsListAppBar({ + Key? key, + required this.innerBoxIsScrolled, + required this.showDivider, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final logsProvider = Provider.of(context); + final statusProvider = Provider.of(context); + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; + + void updateConfig(Map data) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.updatingSettings); + + final result = serverVersionIsAhead( + currentVersion: statusProvider.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? await serversProvider.apiClient!.updateQueryLogParameters(data: data) + : await serversProvider.apiClient!.updateQueryLogParametersLegacy(data: data); + + processModal.close(); + + if (result['result'] == 'success') { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsConfigUpdated, + color: Colors.green + ); + } + else { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsConfigNotUpdated, + color: Colors.red + ); + } + } + + void clearQueries() async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.updatingSettings); + + final result = await serversProvider.apiClient!.clearLogs(); + + processModal.close(); + + if (result['result'] == 'success') { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsCleared, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsNotCleared, + color: Colors.red + ); + } + } + + + void openFilersModal() { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => const LogsFiltersModal( + dialog: true, + ), + barrierDismissible: false + ); + } + else { + showModalBottomSheet( + context: context, + useRootNavigator: true, + builder: (context) => const LogsFiltersModal( + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ); + } + } + + final Map translatedString = { + "all": AppLocalizations.of(context)!.all, + "filtered": AppLocalizations.of(context)!.filtered, + "processed": AppLocalizations.of(context)!.processedRow, + "whitelisted": AppLocalizations.of(context)!.processedWhitelistRow, + "blocked": AppLocalizations.of(context)!.blocked, + "blocked_safebrowsing": AppLocalizations.of(context)!.blockedSafeBrowsingRow, + "blocked_parental": AppLocalizations.of(context)!.blockedParentalRow, + "safe_search": AppLocalizations.of(context)!.safeSearch, + }; + + return SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, + title: Text(AppLocalizations.of(context)!.logs), + expandedHeight: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + ? 170 : null, + actions: [ + if (!(Platform.isAndroid || Platform.isIOS)) IconButton( + onPressed: () => logsProvider.fetchLogs(inOffset: 0), + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ), + logsProvider.loadStatus == LoadStatus.loaded + ? IconButton( + onPressed: openFilersModal, + icon: const Icon(Icons.filter_list_rounded), + tooltip: AppLocalizations.of(context)!.filters, + ) + : const SizedBox(), + if (statusProvider.serverStatus != null) IconButton( + tooltip: AppLocalizations.of(context)!.settings, + onPressed: () => { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => LogsConfigModal( + onConfirm: updateConfig, + onClear: clearQueries, + dialog: true, + serverVersion: statusProvider.serverStatus!.serverVersion, + ), + barrierDismissible: false + ) + } + else { + showModalBottomSheet( + context: context, + useRootNavigator: true, + builder: (context) => LogsConfigModal( + onConfirm: updateConfig, + onClear: clearQueries, + dialog: false, + serverVersion: statusProvider.serverStatus!.serverVersion, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ) + } + }, + icon: const Icon(Icons.settings) + ), + const SizedBox(width: 5), + ], + bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + ? PreferredSize( + preferredSize: const Size(double.maxFinite, 70), + child: Container( + height: 50, + width: double.maxFinite, + padding: const EdgeInsets.only(bottom: 10), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: showDivider == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.1) + : Colors.transparent, + ) + ) + ), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + if (logsProvider.appliedFilters.searchText != null) ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.search_rounded, + ), + label: Row( + children: [ + Text( + logsProvider.appliedFilters.searchText!, + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: null, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.setSearchText(null); + logsProvider.fetchLogs( + inOffset: 0, + searchText: '' + ); + }, + ), + ], + if (logsProvider.appliedFilters.selectedResultStatus != 'all') ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.shield_rounded, + ), + label: Row( + children: [ + Text( + translatedString[logsProvider.appliedFilters.selectedResultStatus]!, + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: logsProvider.appliedFilters.searchText, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.setSelectedResultStatus('all'); + logsProvider.fetchLogs( + inOffset: 0, + responseStatus: 'all' + ); + }, + ), + ], + if (logsProvider.appliedFilters.clients != null) ...[ + const SizedBox(width: 15), + Chip( + avatar: const Icon( + Icons.smartphone_rounded, + ), + label: Row( + children: [ + Text( + logsProvider.appliedFilters.clients!.length == 1 + ? logsProvider.appliedFilters.clients![0] + : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", + ), + ], + ), + deleteIcon: const Icon( + Icons.clear, + size: 18, + ), + onDeleted: () { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: logsProvider.appliedFilters.searchText, + clients: null + ) + ); + logsProvider.setSelectedClients(null); + logsProvider.fetchLogs( + inOffset: 0, + responseStatus: logsProvider.appliedFilters.selectedResultStatus + ); + }, + ), + ], + const SizedBox(width: 15), + ], + ), + ) + ) + : null, + ); + } +} \ No newline at end of file From ad7267bc5cfae8a5b3f21a2329f2db4b2d668657 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 1 Nov 2023 20:46:03 +0100 Subject: [PATCH 362/676] Refactor logs --- .../logs/configuration/config_widgets.dart | 266 +++++++++++ .../logs/configuration/logs_config_modal.dart | 254 +++++++++++ .../{ => details}/log_details_screen.dart | 2 +- .../logs/{ => details}/log_list_tile.dart | 0 .../logs/{ => filters}/clients_modal.dart | 0 .../{ => filters}/filter_status_modal.dart | 0 .../{ => filters}/logs_filters_modal.dart | 4 +- lib/screens/logs/logs.dart | 2 +- lib/screens/logs/logs_config_modal.dart | 413 ------------------ lib/screens/logs/logs_list.dart | 2 +- lib/screens/logs/logs_list_appbar.dart | 4 +- .../settings/dhcp/select_interface_modal.dart | 7 +- 12 files changed, 529 insertions(+), 425 deletions(-) create mode 100644 lib/screens/logs/configuration/config_widgets.dart create mode 100644 lib/screens/logs/configuration/logs_config_modal.dart rename lib/screens/logs/{ => details}/log_details_screen.dart (99%) rename lib/screens/logs/{ => details}/log_list_tile.dart (100%) rename lib/screens/logs/{ => filters}/clients_modal.dart (100%) rename lib/screens/logs/{ => filters}/filter_status_modal.dart (100%) rename lib/screens/logs/{ => filters}/logs_filters_modal.dart (98%) delete mode 100644 lib/screens/logs/logs_config_modal.dart diff --git a/lib/screens/logs/configuration/config_widgets.dart b/lib/screens/logs/configuration/config_widgets.dart new file mode 100644 index 0000000..44523f3 --- /dev/null +++ b/lib/screens/logs/configuration/config_widgets.dart @@ -0,0 +1,266 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/logs/configuration/logs_config_modal.dart'; + +class LogsConfigOptions extends StatelessWidget { + final bool generalSwitch; + final void Function(bool) updateGeneralSwitch; + final bool anonymizeClientIp; + final void Function(bool) updateAnonymizeClientIp; + final List retentionItems; + final String? retentionTime; + final void Function(String?) updateRetentionTime; + final void Function() onClear; + final void Function() onConfirm; + + const LogsConfigOptions({ + Key? key, + required this.generalSwitch, + required this.updateGeneralSwitch, + required this.anonymizeClientIp, + required this.updateAnonymizeClientIp, + required this.retentionItems, + required this.retentionTime, + required this.updateRetentionTime, + required this.onClear, + required this.onConfirm + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.settings, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.logsSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], + ), + 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: () => updateGeneralSwitch(!generalSwitch), + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.enableLog, + style: const TextStyle( + fontSize: 18, + ), + ), + Switch( + value: generalSwitch, + onChanged: updateGeneralSwitch, + ) + ], + ), + ), + ), + ), + ), + Container(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 14), + child: Column( + children: [ + Material( + color: Colors.transparent, + child: InkWell( + onTap: () => updateAnonymizeClientIp(!anonymizeClientIp), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.anonymizeClientIp, + style: const TextStyle( + fontSize: 16 + ), + ), + Switch( + value: anonymizeClientIp, + onChanged: updateAnonymizeClientIp, + ) + ], + ), + ), + ), + ), + Container(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: DropdownButtonFormField( + items: retentionItems.map>((item) { + return DropdownMenuItem( + value: item.value.toString(), + child: Text(item.label), + ); + }).toList(), + value: retentionTime, + onChanged: (value) => updateRetentionTime(value), + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + label: Text(AppLocalizations.of(context)!.retentionTime) + ), + borderRadius: BorderRadius.circular(20), + ), + ), + ], + ), + ) + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () { + Navigator.pop(context); + onClear(); + }, + child: Text(AppLocalizations.of(context)!.clearLogs) + ), + Row( + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + const SizedBox(width: 20), + TextButton( + onPressed: retentionTime != '' + ? () { + Navigator.pop(context); + onConfirm(); + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, + style: TextStyle( + color: retentionTime != '' + ? Theme.of(context).colorScheme.primary + : Colors.grey + ), + ) + ), + ], + ) + ], + ), + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); + } +} + +class ConfigLogsLoading extends StatelessWidget { + const ConfigLogsLoading({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.loadingLogsSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), + ); + } +} + +class ConfigLogsError extends StatelessWidget { + const ConfigLogsError({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.logSettingsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/logs/configuration/logs_config_modal.dart b/lib/screens/logs/configuration/logs_config_modal.dart new file mode 100644 index 0000000..698348c --- /dev/null +++ b/lib/screens/logs/configuration/logs_config_modal.dart @@ -0,0 +1,254 @@ +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/logs/configuration/config_widgets.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class RetentionItem { + final String label; + final double value; + + const RetentionItem({ + required this.label, + required this.value, + }); +} + +class LogsConfigModal extends StatelessWidget { + final void Function(Map) onConfirm; + final void Function() onClear; + final bool dialog; + final String serverVersion; + + const LogsConfigModal({ + Key? key, + required this.onConfirm, + required this.onClear, + required this.dialog, + required this.serverVersion + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + return LogsConfigModalWidget( + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + context: context, + onConfirm: onConfirm, + onClear: onClear, + dialog: dialog, + serverVersion: serverVersion, + ); + } +} + +class LogsConfigModalWidget extends StatefulWidget { + final ServersProvider serversProvider; + final AppConfigProvider appConfigProvider; + final BuildContext context; + final void Function(Map) onConfirm; + final void Function() onClear; + final bool dialog; + final String serverVersion; + + const LogsConfigModalWidget({ + Key? key, + required this.serversProvider, + required this.appConfigProvider, + required this.context, + required this.onConfirm, + required this.onClear, + required this.dialog, + required this.serverVersion + }) : super(key: key); + + @override + State createState() => _LogsConfigModalWidgetState(); +} + +class _LogsConfigModalWidgetState extends State { + bool generalSwitch = false; + bool anonymizeClientIp = false; + String? retentionTime = ""; + + List retentionItems = []; + + LoadStatus loadStatus = LoadStatus.loading; + + void loadData() async { + final serversProvider = Provider.of(context, listen: false); + + final result = serverVersionIsAhead( + currentVersion: widget.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? await serversProvider.apiClient!.getQueryLogInfo() + : await serversProvider.apiClient!.getQueryLogInfoLegacy(); + + if (mounted) { + if (result['result'] == 'success') { + setState(() { + generalSwitch = result['data']['enabled']; + anonymizeClientIp = result['data']['anonymize_client_ip']; + retentionTime = result['data']['interval'].toString(); + loadStatus = LoadStatus.loading; + }); + } + else { + setState(() => loadStatus = LoadStatus.error); + } + } + } + + @override + void initState() { + retentionItems = serverVersionIsAhead( + currentVersion: widget.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true ? [ + RetentionItem( + label: AppLocalizations.of(widget.context)!.hours6, + value: 21600000 + ), + RetentionItem( + label: AppLocalizations.of(widget.context)!.hours24, + value: 86400000 + ), + RetentionItem( + label: AppLocalizations.of(widget.context)!.days7, + value: 604800000 + ), + RetentionItem( + label: AppLocalizations.of(widget.context)!.days30, + value: 2592000000 + ), + RetentionItem( + label: AppLocalizations.of(widget.context)!.days90, + value: 7776000000 + ), + ] : [ + RetentionItem( + label: AppLocalizations.of(widget.context)!.hours6, + value: 0.25 + ), + RetentionItem( + label: AppLocalizations.of(widget.context)!.hours24, + value: 1 + ), + RetentionItem( + label: AppLocalizations.of(widget.context)!.days7, + value: 7 + ), + RetentionItem( + label: AppLocalizations.of(widget.context)!.days30, + value: 30 + ), + RetentionItem( + label: AppLocalizations.of(widget.context)!.days90, + value: 90 + ), + ]; + + loadData(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Builder( + builder: (context) { + switch (loadStatus) { + case LoadStatus.loading: + return const ConfigLogsLoading(); + + case LoadStatus.loaded: + return LogsConfigOptions( + generalSwitch: generalSwitch, + updateGeneralSwitch: (v) => setState(() => generalSwitch = v), + anonymizeClientIp: anonymizeClientIp, + updateAnonymizeClientIp: (v) => setState(() => anonymizeClientIp = v), + retentionItems: retentionItems, + retentionTime: retentionTime, + updateRetentionTime: (v) => setState(() => retentionTime = v), + onClear: () => widget.onClear(), + onConfirm: () => widget.onConfirm({ + "enabled": generalSwitch, + "interval": double.parse(retentionTime!), + "anonymize_client_ip": anonymizeClientIp + }) + ); + + case LoadStatus.error: + return const ConfigLogsError(); + + default: + return const SizedBox(); + } + }, + ) + ), + ); + } + else { + return Container( + height: Platform.isIOS ? 436 : 420, + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: Builder( + builder: (context) { + switch (loadStatus) { + case LoadStatus.loading: + return const ConfigLogsLoading(); + + case LoadStatus.loaded: + return LogsConfigOptions( + generalSwitch: generalSwitch, + updateGeneralSwitch: (v) => setState(() => generalSwitch = v), + anonymizeClientIp: anonymizeClientIp, + updateAnonymizeClientIp: (v) => setState(() => anonymizeClientIp = v), + retentionItems: retentionItems, + retentionTime: retentionTime, + updateRetentionTime: (v) => setState(() => retentionTime = v), + onClear: () => widget.onClear(), + onConfirm: () => widget.onConfirm({ + "enabled": generalSwitch, + "interval": double.parse(retentionTime!), + "anonymize_client_ip": anonymizeClientIp + }) + ); + + case LoadStatus.error: + return const ConfigLogsError(); + + default: + return const SizedBox(); + } + }, + ) + ); + } + } +} \ No newline at end of file diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/details/log_details_screen.dart similarity index 99% rename from lib/screens/logs/log_details_screen.dart rename to lib/screens/logs/details/log_details_screen.dart index 161e9fa..510c2e2 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/details/log_details_screen.dart @@ -6,7 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; -import 'package:adguard_home_manager/screens/logs/log_list_tile.dart'; +import 'package:adguard_home_manager/screens/logs/details/log_list_tile.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; diff --git a/lib/screens/logs/log_list_tile.dart b/lib/screens/logs/details/log_list_tile.dart similarity index 100% rename from lib/screens/logs/log_list_tile.dart rename to lib/screens/logs/details/log_list_tile.dart diff --git a/lib/screens/logs/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart similarity index 100% rename from lib/screens/logs/clients_modal.dart rename to lib/screens/logs/filters/clients_modal.dart diff --git a/lib/screens/logs/filter_status_modal.dart b/lib/screens/logs/filters/filter_status_modal.dart similarity index 100% rename from lib/screens/logs/filter_status_modal.dart rename to lib/screens/logs/filters/filter_status_modal.dart diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/filters/logs_filters_modal.dart similarity index 98% rename from lib/screens/logs/logs_filters_modal.dart rename to lib/screens/logs/filters/logs_filters_modal.dart index e41efa5..8e1cdbe 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/filters/logs_filters_modal.dart @@ -6,8 +6,8 @@ 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/logs/clients_modal.dart'; -import 'package:adguard_home_manager/screens/logs/filter_status_modal.dart'; +import 'package:adguard_home_manager/screens/logs/filters/clients_modal.dart'; +import 'package:adguard_home_manager/screens/logs/filters/filter_status_modal.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 863f93d..c1510c3 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -4,7 +4,7 @@ import 'package:adguard_home_manager/models/logs.dart'; import 'package:flutter/material.dart'; import 'package:adguard_home_manager/screens/logs/logs_list.dart'; -import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; +import 'package:adguard_home_manager/screens/logs/details/log_details_screen.dart'; class Logs extends StatefulWidget { const Logs({Key? key}) : super(key: key); diff --git a/lib/screens/logs/logs_config_modal.dart b/lib/screens/logs/logs_config_modal.dart deleted file mode 100644 index 2f16721..0000000 --- a/lib/screens/logs/logs_config_modal.dart +++ /dev/null @@ -1,413 +0,0 @@ -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/functions/compare_versions.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; - -class LogsConfigModal extends StatelessWidget { - final void Function(Map) onConfirm; - final void Function() onClear; - final bool dialog; - final String serverVersion; - - const LogsConfigModal({ - Key? key, - required this.onConfirm, - required this.onClear, - required this.dialog, - required this.serverVersion - }) : super(key: key); - - @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return LogsConfigModalWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - context: context, - onConfirm: onConfirm, - onClear: onClear, - dialog: dialog, - serverVersion: serverVersion, - ); - } -} - -class LogsConfigModalWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - final BuildContext context; - final void Function(Map) onConfirm; - final void Function() onClear; - final bool dialog; - final String serverVersion; - - const LogsConfigModalWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - required this.context, - required this.onConfirm, - required this.onClear, - required this.dialog, - required this.serverVersion - }) : super(key: key); - - @override - State createState() => _LogsConfigModalWidgetState(); -} - -class _LogsConfigModalWidgetState extends State { - bool generalSwitch = false; - bool anonymizeClientIp = false; - String? retentionTime = ""; - - List> retentionItems = []; - - int loadStatus = 0; - - void loadData() async { - final serversProvider = Provider.of(context, listen: false); - - final result = serverVersionIsAhead( - currentVersion: widget.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? await serversProvider.apiClient!.getQueryLogInfo() - : await serversProvider.apiClient!.getQueryLogInfoLegacy(); - - if (mounted) { - if (result['result'] == 'success') { - setState(() { - generalSwitch = result['data']['enabled']; - anonymizeClientIp = result['data']['anonymize_client_ip']; - retentionTime = result['data']['interval'].toString(); - loadStatus = 1; - }); - } - else { - setState(() => loadStatus = 2); - } - } - } - - @override - void initState() { - retentionItems = serverVersionIsAhead( - currentVersion: widget.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true ? [ - { - 'label': AppLocalizations.of(widget.context)!.hours6, - 'value': 21600000 - }, - { - 'label': AppLocalizations.of(widget.context)!.hours24, - 'value': 86400000 - }, - { - 'label': AppLocalizations.of(widget.context)!.days7, - 'value': 604800000 - }, - { - 'label': AppLocalizations.of(widget.context)!.days30, - 'value': 2592000000 - }, - { - 'label': AppLocalizations.of(widget.context)!.days90, - 'value': 7776000000 - }, - ] : [ - { - 'label': AppLocalizations.of(widget.context)!.hours6, - 'value': 0.25 - }, - { - 'label': AppLocalizations.of(widget.context)!.hours24, - 'value': 1 - }, - { - 'label': AppLocalizations.of(widget.context)!.days7, - 'value': 7 - }, - { - 'label': AppLocalizations.of(widget.context)!.days30, - 'value': 30 - }, - { - 'label': AppLocalizations.of(widget.context)!.days90, - 'value': 90 - }, - ]; - - loadData(); - super.initState(); - } - - @override - Widget build(BuildContext context) { - Widget generateBody() { - switch (loadStatus) { - case 0: - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.loadingLogsSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ) - ], - ), - ); - - case 1: - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.settings, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.logsSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - ], - ), - ], - ), - 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: () => setState(() => generalSwitch = !generalSwitch), - borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.enableLog, - style: const TextStyle( - fontSize: 18, - ), - ), - Switch( - value: generalSwitch, - onChanged: (value) => setState(() => generalSwitch = value), - ) - ], - ), - ), - ), - ), - ), - Container(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 14), - child: Column( - children: [ - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => setState(() => anonymizeClientIp = !anonymizeClientIp), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 30), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.anonymizeClientIp, - style: const TextStyle( - fontSize: 16 - ), - ), - Switch( - value: anonymizeClientIp, - onChanged: (value) => setState(() => anonymizeClientIp = value), - ) - ], - ), - ), - ), - ), - Container(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: DropdownButtonFormField( - items: retentionItems.map>((Map item) { - return DropdownMenuItem( - value: item['value'].toString(), - child: Text(item['label']), - ); - }).toList(), - value: retentionTime, - onChanged: (value) => setState(() => retentionTime = value), - decoration: InputDecoration( - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - label: Text(AppLocalizations.of(context)!.retentionTime) - ), - borderRadius: BorderRadius.circular(20), - ), - ), - ], - ), - ) - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: () { - Navigator.pop(context); - widget.onClear(); - }, - child: Text(AppLocalizations.of(context)!.clearLogs) - ), - Row( - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ), - const SizedBox(width: 20), - TextButton( - onPressed: retentionTime != '' - ? () { - Navigator.pop(context); - widget.onConfirm({ - "enabled": generalSwitch, - "interval": double.parse(retentionTime!), - "anonymize_client_ip": anonymizeClientIp - }); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: retentionTime != '' - ? Theme.of(context).colorScheme.primary - : Colors.grey - ), - ) - ), - ], - ) - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ); - - case 2: - return Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.logSettingsNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ) - ], - ); - - default: - return const SizedBox(); - } - } - - if (widget.dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: generateBody() - ), - ); - } - else { - return Container( - height: Platform.isIOS ? 436 : 420, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor - ), - child: generateBody() - ); - } - } -} \ No newline at end of file diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart index 72978ce..ac0596a 100644 --- a/lib/screens/logs/logs_list.dart +++ b/lib/screens/logs/logs_list.dart @@ -4,7 +4,7 @@ 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/logs/log_details_screen.dart'; +import 'package:adguard_home_manager/screens/logs/details/log_details_screen.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; import 'package:adguard_home_manager/screens/logs/logs_list_appbar.dart'; diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 39b4548..8e02aed 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -6,8 +6,8 @@ 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/logs/logs_config_modal.dart'; -import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart'; +import 'package:adguard_home_manager/screens/logs/filters/logs_filters_modal.dart'; +import 'package:adguard_home_manager/screens/logs/configuration/logs_config_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; diff --git a/lib/screens/settings/dhcp/select_interface_modal.dart b/lib/screens/settings/dhcp/select_interface_modal.dart index 668548d..0a740fd 100644 --- a/lib/screens/settings/dhcp/select_interface_modal.dart +++ b/lib/screens/settings/dhcp/select_interface_modal.dart @@ -90,9 +90,7 @@ class SelectInterfaceModal extends StatelessWidget { } else { return GestureDetector( - onTap: () => Navigator.of(context).pop(), - child: Container( - color: Colors.transparent, + onTap: () => Navigator.of(context).pop(), child: DraggableScrollableSheet( initialChildSize: 0.6, minChildSize: 0.3, @@ -154,8 +152,7 @@ class SelectInterfaceModal extends StatelessWidget { ); }, ), - ), - ); + ); } } } \ No newline at end of file From 2837f8543504c10059f67abc45acfa52ae6f3d23 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 1 Nov 2023 20:47:37 +0100 Subject: [PATCH 363/676] Added animation top items --- .../clients/client/logs_list_client.dart | 2 +- lib/screens/home/home.dart | 2 +- lib/screens/home/top_items.dart | 447 ------------------ lib/screens/home/top_items/row_item.dart | 260 ++++++++++ lib/screens/home/top_items/top_items.dart | 299 ++++++++++++ lib/widgets/custom_pie_chart.dart | 4 +- 6 files changed, 564 insertions(+), 450 deletions(-) delete mode 100644 lib/screens/home/top_items.dart create mode 100644 lib/screens/home/top_items/row_item.dart create mode 100644 lib/screens/home/top_items/top_items.dart diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index 9761e3f..8d975a9 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -6,7 +6,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; -import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; +import 'package:adguard_home_manager/screens/logs/details/log_details_screen.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/logs.dart'; diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 293eef3..343d065 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -11,7 +11,7 @@ import 'package:adguard_home_manager/screens/home/server_status.dart'; import 'package:adguard_home_manager/screens/home/combined_chart.dart'; import 'package:adguard_home_manager/screens/home/appbar.dart'; import 'package:adguard_home_manager/screens/home/fab.dart'; -import 'package:adguard_home_manager/screens/home/top_items.dart'; +import 'package:adguard_home_manager/screens/home/top_items/top_items.dart'; import 'package:adguard_home_manager/screens/home/chart.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart deleted file mode 100644 index ebf4e94..0000000 --- a/lib/screens/home/top_items.dart +++ /dev/null @@ -1,447 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -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/widgets/custom_pie_chart.dart'; -import 'package:adguard_home_manager/widgets/domain_options.dart'; -import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; -import 'package:adguard_home_manager/screens/top_items/top_items.dart'; - -import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/providers/logs_provider.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; - -class TopItems extends StatefulWidget { - final String type; - final String label; - final List> data; - final bool? clients; - - const TopItems({ - Key? key, - required this.type, - required this.label, - required this.data, - this.clients - }) : super(key: key); - - @override - State createState() => _TopItemsState(); -} - -class _TopItemsState extends State { - bool _showChart = true; - - final colors = [ - Colors.red, - Colors.green, - Colors.blue, - Colors.orange, - Colors.teal, - Colors.grey - ]; - - @override - void initState() { - _showChart = Provider.of(context, listen: false).showTopItemsChart; - super.initState(); - } - - @override - Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - - final width = MediaQuery.of(context).size.width; - - List> generateData() { - switch (widget.type) { - case 'topQueriedDomains': - return statusProvider.serverStatus!.stats.topQueriedDomains; - - case 'topBlockedDomains': - return statusProvider.serverStatus!.stats.topBlockedDomains; - - case 'topClients': - return statusProvider.serverStatus!.stats.topClients; - - default: - return []; - } - } - - Map chartData() { - Map values = {}; - widget.data.sublist(0, widget.data.length > 5 ? 5 : widget.data.length).forEach((element) { - values = { - ...values, - element.keys.first: element.values.first.toDouble() - }; - }); - if (widget.data.length > 5) { - final int rest = List.from( - widget.data.sublist(5, widget.data.length).map((e) => e.values.first.toInt()) - ).reduce((a, b) => a + b); - values = { - ...values, - AppLocalizations.of(context)!.others: rest.toDouble() - }; - } - return values; - } - - final List itemsList = widget.data.sublist( - 0, - widget.data.length > 5 ? 5 : widget.data.length - ).asMap().entries.map((e) => RowItem( - clients: widget.clients ?? false, - domain: e.value.keys.toList()[0], - number: e.value.values.toList()[0].toString(), - type: widget.type, - chartColor: _showChart ? colors[e.key] : null, - )).toList(); - - final Widget noItems = Padding( - padding: const EdgeInsets.only( - bottom: 20, - top: 10 - ), - child: Text( - AppLocalizations.of(context)!.noItems, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ); - - final Widget chart = CustomPieChart( - data: chartData(), - colors: colors - ); - - return SizedBox( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisAlignment: width <= 700 - ? MainAxisAlignment.spaceBetween - : MainAxisAlignment.center, - children: [ - Text( - widget.label, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - if (width <= 700) TextButton( - onPressed: () => setState(() => _showChart = !_showChart), - child: Text( - _showChart - ? AppLocalizations.of(context)!.hideChart - : AppLocalizations.of(context)!.showChart - ) - ) - ], - ), - ), - - const SizedBox(height: 24), - - if (widget.data.isEmpty) noItems, - if (widget.data.isNotEmpty && width > 700) Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - flex: 1, - child: ConstrainedBox( - constraints: const BoxConstraints( - maxHeight: 250 - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: chart, - ), - ) - ), - Expanded( - flex: 2, - child: Column( - children: [ - ...itemsList, - OthersRowItem(items: widget.data) - ] - ), - ) - ], - ), - if (widget.data.isNotEmpty && width <= 700) ...[ - if (_showChart) ...[ - SizedBox( - height: 150, - child: chart - ), - const SizedBox(height: 16), - ], - ...itemsList, - if (_showChart) OthersRowItem(items: widget.data), - const SizedBox(height: 16), - ], - - if (widget.data.length > 5) ...[ - Padding( - padding: const EdgeInsets.only(right: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => TopItemsModal( - type: widget.type, - title: widget.label, - isClient: widget.clients, - data: generateData(), - ) - ) - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => TopItemsScreen( - type: widget.type, - title: widget.label, - isClient: widget.clients, - data: generateData(), - ) - ) - ) - } - }, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text(AppLocalizations.of(context)!.viewMore), - const SizedBox(width: 10), - const Icon( - Icons.arrow_forward, - size: 20, - ) - ], - ) - ), - ], - ), - ), - const SizedBox(height: 10), - ] - ], - ), - ); - } -} - -class RowItem extends StatelessWidget { - final String type; - final Color? chartColor; - final String domain; - final String number; - final bool clients; - - const RowItem({ - Key? key, - required this.type, - this.chartColor, - required this.domain, - required this.number, - required this.clients - }) : super(key: key); - - @override - Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); - - String? name; - if (clients == true) { - try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(domain)).name; - } catch (e) { - // ---- // - } - } - - return Material( - color: Colors.transparent, - child: DomainOptions( - item: domain, - isClient: type == 'topClients', - isBlocked: type == 'topBlockedDomains', - onTap: () { - if (type == 'topQueriedDomains' || type == 'topBlockedDomains') { - logsProvider.setSearchText(domain); - logsProvider.setSelectedClients(null); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: domain, - clients: null - ) - ); - appConfigProvider.setSelectedScreen(2); - } - else if (type == 'topClients') { - logsProvider.setSearchText(null); - logsProvider.setSelectedClients([domain]); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: null, - clients: [domain] - ) - ); - } - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Row( - children: [ - if (chartColor != null) Container( - margin: const EdgeInsets.only(right: 16), - width: 12, - height: 12, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - color: chartColor - ), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - domain, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - if (name != null) ...[ - const SizedBox(height: 5), - Text( - name, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ] - ], - ), - ), - ], - ), - ), - const SizedBox(width: 16), - Text( - number, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - ), - ), - ); - } -} - -class OthersRowItem extends StatelessWidget { - final List> items; - - const OthersRowItem({ - Key? key, - required this.items - }) : super(key: key); - - @override - Widget build(BuildContext context) { - - if (items.length <= 5) { - return const SizedBox(); - } - - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Row( - children: [ - Container( - margin: const EdgeInsets.only(right: 16), - width: 12, - height: 12, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - color: Colors.grey - ), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.others, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ), - ], - ), - ), - const SizedBox(width: 16), - Text( - List.from( - items.sublist(5, items.length).map((e) => e.values.first.toInt()) - ).reduce((a, b) => a + b).toString(), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/home/top_items/row_item.dart b/lib/screens/home/top_items/row_item.dart new file mode 100644 index 0000000..8985fd6 --- /dev/null +++ b/lib/screens/home/top_items/row_item.dart @@ -0,0 +1,260 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/domain_options.dart'; + +import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/logs_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; + +class RowItem extends StatelessWidget { + final String type; + final Color chartColor; + final String domain; + final String number; + final bool clients; + final bool showColor; + + const RowItem({ + Key? key, + required this.type, + required this.chartColor, + required this.domain, + required this.number, + required this.clients, + required this.showColor, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + final logsProvider = Provider.of(context); + + String? name; + if (clients == true) { + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(domain)).name; + } catch (e) { + // ---- // + } + } + + return Material( + color: Colors.transparent, + child: DomainOptions( + item: domain, + isClient: type == 'topClients', + isBlocked: type == 'topBlockedDomains', + onTap: () { + if (type == 'topQueriedDomains' || type == 'topBlockedDomains') { + logsProvider.setSearchText(domain); + logsProvider.setSelectedClients(null); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: domain, + clients: null + ) + ); + appConfigProvider.setSelectedScreen(2); + } + else if (type == 'topClients') { + logsProvider.setSearchText(null); + logsProvider.setSelectedClients([domain]); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: null, + clients: [domain] + ) + ); + } + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + children: [ + AnimatedContainer( + duration: const Duration(milliseconds: 200), + curve: Curves.ease, + margin: EdgeInsets.only(right: showColor ? 16 : 0), + width: showColor ? 12 : 0, + height: showColor ? 12 : 0, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: chartColor + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + domain, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + if (name != null) ...[ + const SizedBox(height: 5), + Text( + name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ] + ], + ), + ), + ], + ), + ), + const SizedBox(width: 16), + Text( + number, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + ), + ), + ); + } +} + +class OthersRowItem extends StatefulWidget { + final List> items; + final bool showColor; + + const OthersRowItem({ + Key? key, + required this.items, + required this.showColor, + }) : super(key: key); + + @override + State createState() => _OthersRowItemState(); +} + +class _OthersRowItemState extends State with SingleTickerProviderStateMixin { + late AnimationController expandController; + late Animation animation; + + @override + void initState() { + super.initState(); + prepareAnimations(); + _runExpandCheck(); + } + + void prepareAnimations() { + expandController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 200) + ); + animation = CurvedAnimation( + parent: expandController, + curve: Curves.ease, + ); + } + + void _runExpandCheck() { + if (widget.showColor) { + expandController.forward(); + } + else { + expandController.reverse(); + } + } + + @override + void didUpdateWidget(oldWidget) { + super.didUpdateWidget(oldWidget); + _runExpandCheck(); + } + + @override + void dispose() { + expandController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (widget.items.length <= 5) { + return const SizedBox(); + } + + return SizeTransition( + axisAlignment: 1.0, + sizeFactor: animation, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 16), + width: 12, + height: 12, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Colors.grey + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.others, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ), + ], + ), + ), + const SizedBox(width: 16), + Text( + List.from( + widget.items.sublist(5, widget.items.length).map((e) => e.values.first.toInt()) + ).reduce((a, b) => a + b).toString(), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/home/top_items/top_items.dart b/lib/screens/home/top_items/top_items.dart new file mode 100644 index 0000000..97b61e0 --- /dev/null +++ b/lib/screens/home/top_items/top_items.dart @@ -0,0 +1,299 @@ +// ignore_for_file: use_build_context_synchronously + +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/home/top_items/row_item.dart'; +import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; +import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; +import 'package:adguard_home_manager/screens/top_items/top_items.dart'; + +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; + +class TopItems extends StatefulWidget { + final String type; + final String label; + final List> data; + final bool? clients; + + const TopItems({ + Key? key, + required this.type, + required this.label, + required this.data, + this.clients + }) : super(key: key); + + @override + State createState() => _TopItemsState(); +} + +class _TopItemsState extends State { + bool _showChart = true; + + final colors = [ + Colors.red, + Colors.green, + Colors.blue, + Colors.orange, + Colors.teal, + Colors.grey + ]; + + @override + void initState() { + _showChart = Provider.of(context, listen: false).showTopItemsChart; + super.initState(); + } + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; + + List> generateData() { + switch (widget.type) { + case 'topQueriedDomains': + return statusProvider.serverStatus!.stats.topQueriedDomains; + + case 'topBlockedDomains': + return statusProvider.serverStatus!.stats.topBlockedDomains; + + case 'topClients': + return statusProvider.serverStatus!.stats.topClients; + + default: + return []; + } + } + + Map chartData() { + Map values = {}; + widget.data.sublist(0, widget.data.length > 5 ? 5 : widget.data.length).forEach((element) { + values = { + ...values, + element.keys.first: element.values.first.toDouble() + }; + }); + if (widget.data.length > 5) { + final int rest = List.from( + widget.data.sublist(5, widget.data.length).map((e) => e.values.first.toInt()) + ).reduce((a, b) => a + b); + values = { + ...values, + AppLocalizations.of(context)!.others: rest.toDouble() + }; + } + return values; + } + + final Widget noItems = Padding( + padding: const EdgeInsets.only( + bottom: 20, + top: 10 + ), + child: Text( + AppLocalizations.of(context)!.noItems, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ); + + return SizedBox( + child: Column( + children: [ + if (widget.data.isEmpty) noItems, + if (widget.data.isNotEmpty && width > 700) Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: ConstrainedBox( + constraints: const BoxConstraints( + maxHeight: 250 + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: CustomPieChart( + data: chartData(), + colors: colors + ) + ), + ) + ), + Expanded( + flex: 2, + child: Column( + children: [ + ItemsList( + colors: colors, + data: widget.data, + clients: widget.clients, + type: widget.type, + showChart: _showChart + ), + OthersRowItem( + items: widget.data, + showColor: true, + ) + ] + ), + ) + ], + ), + if (widget.data.isNotEmpty && width <= 700) ...[ + ExpansionPanelList( + expandedHeaderPadding: const EdgeInsets.all(0), + elevation: 0, + expansionCallback: (_, isExpanded) => setState(() => _showChart = isExpanded), + children: [ + ExpansionPanel( + headerBuilder: (context, isExpanded) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: width <= 700 + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.center, + children: [ + Text( + widget.label, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Column( + children: [ + SizedBox( + height: 150, + child: CustomPieChart( + data: chartData(), + colors: colors + ) + ), + const SizedBox(height: 16), + ], + ), + ), + isExpanded: _showChart + ), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 8), + child: ItemsList( + colors: colors, + data: widget.data, + clients: widget.clients, + type: widget.type, + showChart: _showChart + ), + ), + OthersRowItem( + items: widget.data, + showColor: _showChart, + ), + const SizedBox(height: 16), + ], + + if (widget.data.length > 5) ...[ + Padding( + padding: const EdgeInsets.only(right: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => TopItemsModal( + type: widget.type, + title: widget.label, + isClient: widget.clients, + data: generateData(), + ) + ) + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => TopItemsScreen( + type: widget.type, + title: widget.label, + isClient: widget.clients, + data: generateData(), + ) + ) + ) + } + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(AppLocalizations.of(context)!.viewMore), + const SizedBox(width: 10), + const Icon( + Icons.arrow_forward, + size: 20, + ) + ], + ) + ), + ], + ), + ), + const SizedBox(height: 10), + ] + ], + ), + ); + } +} + +class ItemsList extends StatelessWidget { + final List colors; + final List> data; + final bool? clients; + final String type; + final bool showChart; + + const ItemsList({ + Key? key, + required this.colors, + required this.data, + required this.clients, + required this.type, + required this.showChart, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: data.sublist( + 0, data.length > 5 ? 5 : data.length + ).asMap().entries.map((e) => RowItem( + clients: clients ?? false, + domain: e.value.keys.toList()[0], + number: e.value.values.toList()[0].toString(), + type: type, + chartColor: colors[e.key], + showColor: showChart, + )).toList() + ); + } +} \ No newline at end of file diff --git a/lib/widgets/custom_pie_chart.dart b/lib/widgets/custom_pie_chart.dart index 6af7e11..0c8f9f6 100644 --- a/lib/widgets/custom_pie_chart.dart +++ b/lib/widgets/custom_pie_chart.dart @@ -4,18 +4,20 @@ import 'package:pie_chart/pie_chart.dart'; class CustomPieChart extends StatelessWidget { final Map data; final List colors; + final Duration? animationDuration; const CustomPieChart({ Key? key, required this.data, required this.colors, + this.animationDuration = const Duration(milliseconds: 800), }) : super(key: key); @override Widget build(BuildContext context) { return PieChart( dataMap: data, - animationDuration: const Duration(milliseconds: 800), + animationDuration: animationDuration, colorList: colors, initialAngleInDegree: 270, chartType: ChartType.ring, From 1eb0df9063a9f864dff037db4df8d73d1c31503b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 1 Nov 2023 20:49:38 +0100 Subject: [PATCH 364/676] Fix filter clients from top items --- lib/screens/home/top_items/row_item.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/screens/home/top_items/row_item.dart b/lib/screens/home/top_items/row_item.dart index 8985fd6..b22b33b 100644 --- a/lib/screens/home/top_items/row_item.dart +++ b/lib/screens/home/top_items/row_item.dart @@ -71,6 +71,7 @@ class RowItem extends StatelessWidget { clients: [domain] ) ); + appConfigProvider.setSelectedScreen(2); } }, child: Padding( From 4a2f7b8bdb8928e4d4edcf30d5599f26674cd39b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 1 Nov 2023 21:14:45 +0100 Subject: [PATCH 365/676] Improved animation --- lib/screens/home/top_items/row_item.dart | 98 +++++++++++++++++------ lib/screens/home/top_items/top_items.dart | 1 + 2 files changed, 75 insertions(+), 24 deletions(-) diff --git a/lib/screens/home/top_items/row_item.dart b/lib/screens/home/top_items/row_item.dart index b22b33b..dbbd6d4 100644 --- a/lib/screens/home/top_items/row_item.dart +++ b/lib/screens/home/top_items/row_item.dart @@ -9,7 +9,7 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -class RowItem extends StatelessWidget { +class RowItem extends StatefulWidget { final String type; final Color chartColor; final String domain; @@ -27,6 +27,53 @@ class RowItem extends StatelessWidget { required this.showColor, }) : super(key: key); + @override + State createState() => _RowItemState(); +} + +class _RowItemState extends State with TickerProviderStateMixin { + late AnimationController expandController; + late Animation animation; + + @override + void initState() { + super.initState(); + prepareAnimations(); + _runExpandCheck(); + } + + void prepareAnimations() { + expandController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 250) + ); + animation = CurvedAnimation( + parent: expandController, + curve: Curves.ease, + ); + } + + void _runExpandCheck() { + if (widget.showColor) { + expandController.forward(); + } + else { + expandController.reverse(); + } + } + + @override + void didUpdateWidget(oldWidget) { + super.didUpdateWidget(oldWidget); + _runExpandCheck(); + } + + @override + void dispose() { + expandController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final statusProvider = Provider.of(context); @@ -34,9 +81,9 @@ class RowItem extends StatelessWidget { final logsProvider = Provider.of(context); String? name; - if (clients == true) { + if (widget.clients == true) { try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(domain)).name; + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(widget.domain)).name; } catch (e) { // ---- // } @@ -45,30 +92,30 @@ class RowItem extends StatelessWidget { return Material( color: Colors.transparent, child: DomainOptions( - item: domain, - isClient: type == 'topClients', - isBlocked: type == 'topBlockedDomains', + item: widget.domain, + isClient: widget.type == 'topClients', + isBlocked: widget.type == 'topBlockedDomains', onTap: () { - if (type == 'topQueriedDomains' || type == 'topBlockedDomains') { - logsProvider.setSearchText(domain); + if (widget.type == 'topQueriedDomains' || widget.type == 'topBlockedDomains') { + logsProvider.setSearchText(widget.domain); logsProvider.setSelectedClients(null); logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: 'all', - searchText: domain, + searchText: widget.domain, clients: null ) ); appConfigProvider.setSelectedScreen(2); } - else if (type == 'topClients') { + else if (widget.type == 'topClients') { logsProvider.setSearchText(null); - logsProvider.setSelectedClients([domain]); + logsProvider.setSelectedClients([widget.domain]); logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: 'all', searchText: null, - clients: [domain] + clients: [widget.domain] ) ); appConfigProvider.setSelectedScreen(2); @@ -85,15 +132,18 @@ class RowItem extends StatelessWidget { Flexible( child: Row( children: [ - AnimatedContainer( - duration: const Duration(milliseconds: 200), - curve: Curves.ease, - margin: EdgeInsets.only(right: showColor ? 16 : 0), - width: showColor ? 12 : 0, - height: showColor ? 12 : 0, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - color: chartColor + SizeTransition( + axisAlignment: 1.0, + sizeFactor: animation, + axis: Axis.horizontal, + child: Container( + margin: const EdgeInsets.only(right: 16), + width: 12, + height: 12, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: widget.chartColor + ), ), ), Expanded( @@ -101,7 +151,7 @@ class RowItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - domain, + widget.domain, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 16, @@ -127,7 +177,7 @@ class RowItem extends StatelessWidget { ), const SizedBox(width: 16), Text( - number, + widget.number, style: TextStyle( color: Theme.of(context).colorScheme.onSurface ), @@ -168,7 +218,7 @@ class _OthersRowItemState extends State with SingleTickerProvider void prepareAnimations() { expandController = AnimationController( vsync: this, - duration: const Duration(milliseconds: 200) + duration: const Duration(milliseconds: 250) ); animation = CurvedAnimation( parent: expandController, diff --git a/lib/screens/home/top_items/top_items.dart b/lib/screens/home/top_items/top_items.dart index 97b61e0..5fd6435 100644 --- a/lib/screens/home/top_items/top_items.dart +++ b/lib/screens/home/top_items/top_items.dart @@ -153,6 +153,7 @@ class _TopItemsState extends State { expandedHeaderPadding: const EdgeInsets.all(0), elevation: 0, expansionCallback: (_, isExpanded) => setState(() => _showChart = isExpanded), + animationDuration: const Duration(milliseconds: 250), children: [ ExpansionPanel( headerBuilder: (context, isExpanded) => Padding( From 1ec4be5bc71c93317b6711893d8a612b51c3ee57 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 1 Nov 2023 21:31:19 +0100 Subject: [PATCH 366/676] Updated turkish translation --- lib/l10n/app_tr.arb | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index ef6edd7..27b066c 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -65,7 +65,7 @@ "theme": "Tema", "light": "Aydınlık", "dark": "Karanlık", - "systemDefined": "Sistem temasına uy", + "systemDefined": "Sistemle uyumlu olsun", "close": "Kapat", "connectedTo": "Bağlandı:", "selectedServer": "Seçili sunucu:", @@ -170,9 +170,9 @@ "search": "Ara", "dnsQueries": "DNS sorguları", "average": "Ortalama", - "blockedFilters": "Engellenen (Alan adları)", - "malwarePhishingBlocked": "Engellenen (Zararlı içerik)", - "blockedAdultWebsites": "Engellenen (Yetişkin içerik)", + "blockedFilters": "Engellenen alan adları", + "malwarePhishingBlocked": "Engellenen zararlı içerikler", + "blockedAdultWebsites": "Engellenen yetişkin içerikler", "generalSettings": "Genel ayarlar", "generalSettingsDescription": "Çeşitli farklı ayarlar", "hideZeroValues": "Sıfır değerlerini gizle", @@ -397,12 +397,12 @@ "loadingRewriteRules": "Yeniden yazma kuralları yükleniyor...", "rewriteRulesNotLoaded": "DNS yeniden yazma kuralları yüklenemedi.", "noRewriteRules": "DNS yeniden yazım kuralları yok", - "answer": "Cevap", - "deleteDnsRewrite": "DNS yeniden yazmayı sil", + "answer": "Yanıt", + "deleteDnsRewrite": "DNS yeniden yazımı sil", "deleteDnsRewriteMessage": "Bu DNS yeniden yazmasını silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.", "dnsRewriteRuleDeleted": "DNS yeniden yazma kuralı başarıyla silindi", "dnsRewriteRuleNotDeleted": "DNS yeniden yazma kuralı silinemedi", - "addDnsRewrite": "DNS yeniden yazmayı ekle", + "addDnsRewrite": "DNS yeniden yazımı ekle", "addingRewrite": "Yeniden yazma ekleniyor...", "dnsRewriteRuleAdded": "DNS yeniden yazma kuralı başarıyla eklendi", "dnsRewriteRuleNotAdded": "DNS yeniden yazma kuralı eklenemedi", @@ -453,14 +453,14 @@ "limitRequestsSecond": "Saniye başına hız limiti", "valueNotNumber": "Değer bir sayı değil", "enableEdns": "EDNS istemci alt ağını etkinleştir", - "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı Seçeneği (ECS) ekleyin ve istemciler tarafından gönderilen değerleri sorgu günlüğüne kaydedin.", - "enableDnssec": "DNSSEC'i Etkinleştir", - "enableDnssecDescription": "Giden DNS sorguları için DNSSEC özelliğini etkinleştir ve sonucu kontrol et (DNSSEC etkinleştirilmiş bir çözümleyici gerekli).", + "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı Seçeneği (ECS) ekleyin ve istemciler tarafından gönderilen değerleri sorgu günlüğüne kaydedin", + "enableDnssec": "DNSSEC'i etkinleştir", + "enableDnssecDescription": "Giden DNS sorguları için DNSSEC özelliğini etkinleştir ve sonucu kontrol edin (DNSSEC etkinleştirilmiş bir çözümleyici gerekli)", "disableResolvingIpv6": "IPv6 adreslerinin çözümlenmesini devre dışı bırak", - "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını bırakın (AAAA yazın) ve HTTPS yanıtlarından IPv6 ipuçlarını kaldırın.", + "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını bırakın (AAAA yazın) ve HTTPS yanıtlarından IPv6 ipuçlarını kaldırın", "blockingMode": "Engelleme modu", "defaultMode": "Varsayılan", - "defaultDescription": "Reklam engelleme tarzı bir kural tarafından engellendiğinde sıfır IP adresi ile yanıt verin (A için 0.0.0.0; :: AAAA için) /etc/hosts tarzı bir kural tarafından engellendiğinde kuralda belirtilen IP adresi ile yanıt verin.", + "defaultDescription": "Reklam engelleme tarzı bir kural tarafından engellendiğinde sıfır IP adresi ile yanıt verin (A için 0.0.0.0; :: AAAA için) /etc/hosts tarzı bir kural tarafından engellendiğinde kuralda belirtilen IP adresi ile yanıt verin", "refusedDescription": "REFUSED kodu ile yanıt verin", "nxdomainDescription": "NXDOMAIN kodu ile yanıt verin", "nullIp": "Boş IP", @@ -501,7 +501,7 @@ "encryptionSettingsNotLoaded": "Şifreleme ayarları yüklenemedi.", "enableEncryption": "Şifrelemeyi etkinleştir", "enableEncryptionTypes": "HTTPS, DNS-over-HTTPS ve DNS-over-TLS", - "enableEncryptionDescription": "Eğer şifreleme etkinleştirilmişse, AdGuard Home yönetici arayüzü HTTPS üzerinden çalışacaktır ve DNS sunucusu DNS üzerinden HTTPS ve TLS ile gelen isteklere cevap verecektir.", + "enableEncryptionDescription": "Eğer şifreleme etkinleştirilmişse, AdGuard Home yönetici arayüzü HTTPS üzerinden çalışacaktır ve DNS sunucusu DNS üzerinden HTTPS ve TLS ile gelen isteklere yanıt verecektir.", "serverConfiguration": "Sunucu yapılandırması", "domainName": "Alan adı", "domainNameDescription": "Eğer ayarlanırsa, AdGuard Home istemci kimliklerini tespit eder, DDR sorgularına yanıt verir ve ek bağlantı doğrulamalarını gerçekleştirir. Ayarlanmazsa, bu özellikler devre dışı bırakılır. Sertifikadaki DNS adlarından biriyle eşleşmelidir.", @@ -511,7 +511,7 @@ "dnsOverQuicPort": "DNS-over-QUIC bağlantı noktası", "certificates": "Sertifikalar", "certificatesDescription": "Şifreleme kullanmak için, alan adınız için geçerli bir SSL sertifikası zinciri sağlamanız gereklidir. letsencrypt.org'dan ücretsiz bir sertifika alabilir veya güvenilir sertifika yetkililerinden satın alabilirsiniz.", - "certificateFilePath": "Sertifika dosyası yolunu ayarla", + "certificateFilePath": "Sertifika dosyası belirle", "pasteCertificateContent": "Sertifika içeriğini yapıştır", "certificatePath": "Sertifika dosya yolu", "certificateContent": "Sertifika içeriği", @@ -560,7 +560,7 @@ "validPrivateKey": "Geçerli özel anahtar", "expirationDate": "Son kullanma tarihi", "keysNotMatch": "Geçersiz bir sertifika veya anahtar: tls: özel anahtar genel anahtarla eşleşmiyor.", - "timeLogs": "Günlüklerdeki zaman", + "timeLogs": "Günlüklerdeki işlem süresi", "timeLogsDescription": "Günlükler listesinde zaman yerine işlem süresini göster", "hostNames": "Ana bilgisayar adları", "keyType": "Anahtar türü", @@ -575,7 +575,7 @@ "completed": "Tamamlandı", "permissionNotGranted": "İzin verilmedi", "inputSearchTerm": "Bir arama terimi girin.", - "answers": "Cevaplar", + "answers": "Yanıtlar", "copyClipboard": "Panoya kopyala", "domainCopiedClipboard": "Alan adı panoya kopyalandı", "clearDnsCache": "DNS önbelleğini temizle", @@ -629,7 +629,7 @@ "ipLogsDescription": "Günlüklerde istemci adı yerine her zaman IP adresini göster", "application": "Uygulama", "combinedChart": "Birleştirilmiş grafik", - "combinedChartDescription": "Tüm grafikleri bir araya getirin", + "combinedChartDescription": "Tüm grafikleri bir araya getir", "statistics": "İstatistikler", "errorLoadFilters": "Filtreler yüklenirken hata oluştu.", "clientRemovedSuccessfully": "İstemci başarıyla kaldırıldı.", @@ -667,5 +667,7 @@ "showChart": "Göster", "hideChart": "Gizle", "showTopItemsChart": "Öne çıkan öğeler grafiği", - "showTopItemsChartDescription": "Varsayılan olarak öne çıkan öğeler bölümünde halka grafiğini gösterir. Sadece mobil görünümü etkiler." + "showTopItemsChartDescription": "Varsayılan olarak öne çıkan öğeler bölümünde halka grafiğini gösterir. Sadece mobil görünümü etkiler.", + "openMenu": "Menüyü genişlet", + "closeMenu": "Menüyü daralt" } From f02406cf9d138331937ac776ff05984cc3ab51a7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 2 Nov 2023 01:37:59 +0100 Subject: [PATCH 367/676] Theme changes --- lib/config/theme.dart | 94 ++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 59 deletions(-) diff --git a/lib/config/theme.dart b/lib/config/theme.dart index 7391677..a78a14a 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -1,64 +1,7 @@ import 'package:flutter/material.dart'; -ThemeData lightTheme(ColorScheme? dynamicColorScheme) => ThemeData( +final baseTheme = ThemeData( useMaterial3: true, - colorScheme: dynamicColorScheme, - snackBarTheme: SnackBarThemeData( - behavior: SnackBarBehavior.floating, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5) - ), - elevation: 4, - ), - brightness: Brightness.light, listTileTheme: ListTileThemeData( - tileColor: Colors.transparent, - textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), - iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), - ), - androidOverscrollIndicator: AndroidOverscrollIndicator.stretch, -); - -ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( - useMaterial3: true, - colorScheme: dynamicColorScheme, - snackBarTheme: SnackBarThemeData( - behavior: SnackBarBehavior.floating, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5) - ), - elevation: 4, - ), - brightness: Brightness.dark, - listTileTheme: ListTileThemeData( - tileColor: Colors.transparent, - textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), - iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), - ), - androidOverscrollIndicator: AndroidOverscrollIndicator.stretch, -); - -ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( - useMaterial3: true, - colorSchemeSeed: primaryColor, - snackBarTheme: SnackBarThemeData( - behavior: SnackBarBehavior.floating, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5) - ), - elevation: 4, - ), - listTileTheme: const ListTileThemeData( - tileColor: Colors.transparent, - textColor: Color.fromRGBO(117, 117, 117, 1), - iconColor: Color.fromRGBO(117, 117, 117, 1), - ), - brightness: Brightness.light, - androidOverscrollIndicator: AndroidOverscrollIndicator.stretch -); - -ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( - useMaterial3: true, - colorSchemeSeed: primaryColor, snackBarTheme: SnackBarThemeData( contentTextStyle: const TextStyle( color: Colors.white @@ -69,11 +12,44 @@ ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( ), elevation: 4, ), +); + +ThemeData lightTheme(ColorScheme? dynamicColorScheme) => baseTheme.copyWith( + colorScheme: dynamicColorScheme, + brightness: Brightness.light, + listTileTheme: ListTileThemeData( + tileColor: Colors.transparent, + textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), + iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), + ), +); + +ThemeData darkTheme(ColorScheme? dynamicColorScheme) => baseTheme.copyWith( + colorScheme: dynamicColorScheme, + brightness: Brightness.dark, + listTileTheme: ListTileThemeData( + tileColor: Colors.transparent, + textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), + iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), + ), +); + +ThemeData lightThemeOldVersions(MaterialColor primaryColor) => baseTheme.copyWith( + colorScheme: ColorScheme.fromSeed(seedColor: primaryColor), + listTileTheme: const ListTileThemeData( + tileColor: Colors.transparent, + textColor: Color.fromRGBO(117, 117, 117, 1), + iconColor: Color.fromRGBO(117, 117, 117, 1), + ), + brightness: Brightness.light, +); + +ThemeData darkThemeOldVersions(MaterialColor primaryColor) => baseTheme.copyWith( + colorScheme: ColorScheme.fromSeed(seedColor: primaryColor), listTileTheme: const ListTileThemeData( tileColor: Colors.transparent, textColor: Color.fromRGBO(187, 187, 187, 1), iconColor: Color.fromRGBO(187, 187, 187, 1), ), brightness: Brightness.dark, - androidOverscrollIndicator: AndroidOverscrollIndicator.stretch ); \ No newline at end of file From 0e6cde57f00790ad8533243ca50115c549d8a917 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 2 Nov 2023 18:26:50 +0100 Subject: [PATCH 368/676] Revert theme changes --- lib/config/theme.dart | 94 +++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/lib/config/theme.dart b/lib/config/theme.dart index a78a14a..7391677 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -1,7 +1,64 @@ import 'package:flutter/material.dart'; -final baseTheme = ThemeData( +ThemeData lightTheme(ColorScheme? dynamicColorScheme) => ThemeData( useMaterial3: true, + colorScheme: dynamicColorScheme, + snackBarTheme: SnackBarThemeData( + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + elevation: 4, + ), + brightness: Brightness.light, listTileTheme: ListTileThemeData( + tileColor: Colors.transparent, + textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), + iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), + ), + androidOverscrollIndicator: AndroidOverscrollIndicator.stretch, +); + +ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( + useMaterial3: true, + colorScheme: dynamicColorScheme, + snackBarTheme: SnackBarThemeData( + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + elevation: 4, + ), + brightness: Brightness.dark, + listTileTheme: ListTileThemeData( + tileColor: Colors.transparent, + textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), + iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), + ), + androidOverscrollIndicator: AndroidOverscrollIndicator.stretch, +); + +ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( + useMaterial3: true, + colorSchemeSeed: primaryColor, + snackBarTheme: SnackBarThemeData( + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + elevation: 4, + ), + listTileTheme: const ListTileThemeData( + tileColor: Colors.transparent, + textColor: Color.fromRGBO(117, 117, 117, 1), + iconColor: Color.fromRGBO(117, 117, 117, 1), + ), + brightness: Brightness.light, + androidOverscrollIndicator: AndroidOverscrollIndicator.stretch +); + +ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( + useMaterial3: true, + colorSchemeSeed: primaryColor, snackBarTheme: SnackBarThemeData( contentTextStyle: const TextStyle( color: Colors.white @@ -12,44 +69,11 @@ final baseTheme = ThemeData( ), elevation: 4, ), -); - -ThemeData lightTheme(ColorScheme? dynamicColorScheme) => baseTheme.copyWith( - colorScheme: dynamicColorScheme, - brightness: Brightness.light, - listTileTheme: ListTileThemeData( - tileColor: Colors.transparent, - textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), - iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), - ), -); - -ThemeData darkTheme(ColorScheme? dynamicColorScheme) => baseTheme.copyWith( - colorScheme: dynamicColorScheme, - brightness: Brightness.dark, - listTileTheme: ListTileThemeData( - tileColor: Colors.transparent, - textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), - iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), - ), -); - -ThemeData lightThemeOldVersions(MaterialColor primaryColor) => baseTheme.copyWith( - colorScheme: ColorScheme.fromSeed(seedColor: primaryColor), - listTileTheme: const ListTileThemeData( - tileColor: Colors.transparent, - textColor: Color.fromRGBO(117, 117, 117, 1), - iconColor: Color.fromRGBO(117, 117, 117, 1), - ), - brightness: Brightness.light, -); - -ThemeData darkThemeOldVersions(MaterialColor primaryColor) => baseTheme.copyWith( - colorScheme: ColorScheme.fromSeed(seedColor: primaryColor), listTileTheme: const ListTileThemeData( tileColor: Colors.transparent, textColor: Color.fromRGBO(187, 187, 187, 1), iconColor: Color.fromRGBO(187, 187, 187, 1), ), brightness: Brightness.dark, + androidOverscrollIndicator: AndroidOverscrollIndicator.stretch ); \ No newline at end of file From e5a971f3a3afadac3b199ccbe03845d663ad5568 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 2 Nov 2023 18:26:58 +0100 Subject: [PATCH 369/676] Bug fixes --- lib/main.dart | 2 +- lib/screens/clients/added_list.dart | 1 - .../clients/client/added_client_tile.dart | 8 +- .../filters/filters_triple_column.dart | 508 +++++++++--------- .../logs/configuration/config_widgets.dart | 16 +- .../logs/configuration/logs_config_modal.dart | 12 +- 6 files changed, 273 insertions(+), 274 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b2bb30d..8696561 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -214,7 +214,7 @@ class _MainState extends State
with WidgetsBindingObserver { isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), ); if (result != null && appConfigProvider.doNotRememberVersion != result.tagName && mounted) { - await showDialog( + showDialog( context: context, builder: (context) => UpdateModal( gitHubRelease: result, diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index eea9dd6..2c93a04 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -188,7 +188,6 @@ class _AddedListState extends State { : null, onDelete: openDeleteModal, splitView: widget.splitView, - serverVersion: statusProvider.serverStatus!.serverVersion, ), noData: SizedBox( width: double.maxFinite, diff --git a/lib/screens/clients/client/added_client_tile.dart b/lib/screens/clients/client/added_client_tile.dart index 9db4edb..aa3c31e 100644 --- a/lib/screens/clients/client/added_client_tile.dart +++ b/lib/screens/clients/client/added_client_tile.dart @@ -5,6 +5,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/clients.dart'; @@ -18,7 +19,6 @@ class AddedClientTile extends StatelessWidget { final void Function(Client) onDelete; final Client? selectedClient; final bool? splitView; - final String serverVersion; const AddedClientTile({ Key? key, @@ -29,11 +29,11 @@ class AddedClientTile extends StatelessWidget { required this.onDelete, this.selectedClient, required this.splitView, - required this.serverVersion }) : super(key: key); @override Widget build(BuildContext context) { + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); if (splitView == true) { @@ -147,7 +147,7 @@ class AddedClientTile extends StatelessWidget { Icons.search_rounded, size: 19, color: serverVersionIsAhead( - currentVersion: serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true @@ -261,7 +261,7 @@ class AddedClientTile extends StatelessWidget { Icons.search_rounded, size: 19, color: serverVersionIsAhead( - currentVersion: serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 3a8bfa2..6ecdd8f 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -73,258 +73,7 @@ class FiltersTripleColumn extends StatelessWidget { else { return null; } - } - - Widget content() { - switch (filteringProvider.loadStatus) { - case LoadStatus.loading: - return Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingFilters, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ], - ); - - case LoadStatus.loaded: - return Row( - children: [ - Expanded( - flex: 1, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.whitelists, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500 - ), - ), - AddFiltersButton( - type: 'whitelist', - widget: (fn) => IconButton( - onPressed: fn, - icon: const Icon(Icons.add_rounded), - tooltip: AppLocalizations.of(context)!.addWhitelist, - ), - ) - ], - ), - ), - Expanded( - child: ListView.builder( - itemCount: filteringProvider.filtering!.whitelistFilters.length, - itemBuilder: (context, index) => ListOptionsMenu( - list: filteringProvider.filtering!.whitelistFilters[index], - listType: 'whitelist', - child: CustomListTile( - title: filteringProvider.filtering!.whitelistFilters[index].name, - subtitle: "${intFormat(filteringProvider.filtering!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", - trailing: Icon( - filteringProvider.filtering!.whitelistFilters[index].enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - color: filteringProvider.filtering!.whitelistFilters[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ), - onTap: () => onOpenDetailsModal(filteringProvider.filtering!.whitelistFilters[index], 'whitelist'), - ), - ), - ), - ) - ], - ), - ), - Expanded( - flex: 1, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.blacklists, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500 - ), - ), - AddFiltersButton( - type: 'blacklist', - widget: (fn) => IconButton( - onPressed: fn, - icon: const Icon(Icons.add_rounded), - tooltip: AppLocalizations.of(context)!.addBlacklist, - ) - ) - ], - ), - ), - Expanded( - child: ListView.builder( - itemCount: filteringProvider.filtering!.filters.length, - itemBuilder: (context, index) => ListOptionsMenu( - list: filteringProvider.filtering!.filters[index], - listType: 'blacklist', - child: CustomListTile( - title: filteringProvider.filtering!.filters[index].name, - subtitle: "${intFormat(filteringProvider.filtering!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", - trailing: Icon( - filteringProvider.filtering!.filters[index].enabled == true - ? Icons.check_circle_rounded - : Icons.cancel, - color: filteringProvider.filtering!.filters[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ), - onTap: () => onOpenDetailsModal(filteringProvider.filtering!.filters[index], 'blacklist'), - ), - ), - ), - ) - ], - ), - ), - Expanded( - flex: 1, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.customRules, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500 - ), - ), - AddFiltersButton( - type: '', - widget: (fn) => IconButton( - onPressed: fn, - icon: const Icon(Icons.add_rounded), - tooltip: AppLocalizations.of(context)!.addCustomRule, - ) - ) - ], - ), - ), - Expanded( - child: ListView.builder( - itemCount: filteringProvider.filtering!.userRules.length, - itemBuilder: (context, index) => ContextMenuArea( - builder: (context) => [ - CustomListTile( - title: AppLocalizations.of(context)!.copyClipboard, - icon: Icons.copy_rounded, - onTap: () { - copyToClipboard( - value: filteringProvider.filtering!.userRules[index], - successMessage: AppLocalizations.of(context)!.copiedClipboard, - ); - Navigator.pop(context); - } - ), - ], - child: CustomListTile( - onLongPress: () => showDialog( - context: context, - builder: (context) => OptionsModal( - options: [ - MenuOption( - title: AppLocalizations.of(context)!.copyClipboard, - icon: Icons.copy_rounded, - action: () => copyToClipboard( - value: filteringProvider.filtering!.userRules[index], - successMessage: AppLocalizations.of(context)!.copiedClipboard, - ) - ) - ] - ) - ), - title: filteringProvider.filtering!.userRules[index], - subtitleWidget: generateSubtitle(filteringProvider.filtering!.userRules[index]), - trailing: IconButton( - onPressed: () => onRemoveCustomRule(filteringProvider.filtering!.userRules[index]), - icon: const Icon(Icons.delete), - tooltip: AppLocalizations.of(context)!.delete, - ), - ), - ), - ), - ) - ], - ), - ), - ], - ); - - case LoadStatus.error: - return SizedBox.expand( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.filtersNotLoaded, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ], - ), - ); - - default: - return const SizedBox(); - } - } + } return Scaffold( appBar: AppBar( @@ -334,7 +83,7 @@ class FiltersTripleColumn extends StatelessWidget { IconButton( onPressed: () async { final result = await filteringProvider.fetchFilters(); - if (result == false) { + if (result == false && context.mounted) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, @@ -348,7 +97,258 @@ class FiltersTripleColumn extends StatelessWidget { ...actions ], ), - body: content(), + body: Builder( + builder: (context) { + switch (filteringProvider.loadStatus) { + case LoadStatus.loading: + return Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingFilters, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ], + ); + + case LoadStatus.loaded: + return Row( + children: [ + Expanded( + flex: 1, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.whitelists, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500 + ), + ), + AddFiltersButton( + type: 'whitelist', + widget: (fn) => IconButton( + onPressed: fn, + icon: const Icon(Icons.add_rounded), + tooltip: AppLocalizations.of(context)!.addWhitelist, + ), + ) + ], + ), + ), + Expanded( + child: ListView.builder( + itemCount: filteringProvider.filtering!.whitelistFilters.length, + itemBuilder: (context, index) => ListOptionsMenu( + list: filteringProvider.filtering!.whitelistFilters[index], + listType: 'whitelist', + child: CustomListTile( + title: filteringProvider.filtering!.whitelistFilters[index].name, + subtitle: "${intFormat(filteringProvider.filtering!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + filteringProvider.filtering!.whitelistFilters[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: filteringProvider.filtering!.whitelistFilters[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => onOpenDetailsModal(filteringProvider.filtering!.whitelistFilters[index], 'whitelist'), + ), + ), + ), + ) + ], + ), + ), + Expanded( + flex: 1, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.blacklists, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500 + ), + ), + AddFiltersButton( + type: 'blacklist', + widget: (fn) => IconButton( + onPressed: fn, + icon: const Icon(Icons.add_rounded), + tooltip: AppLocalizations.of(context)!.addBlacklist, + ) + ) + ], + ), + ), + Expanded( + child: ListView.builder( + itemCount: filteringProvider.filtering!.filters.length, + itemBuilder: (context, index) => ListOptionsMenu( + list: filteringProvider.filtering!.filters[index], + listType: 'blacklist', + child: CustomListTile( + title: filteringProvider.filtering!.filters[index].name, + subtitle: "${intFormat(filteringProvider.filtering!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + trailing: Icon( + filteringProvider.filtering!.filters[index].enabled == true + ? Icons.check_circle_rounded + : Icons.cancel, + color: filteringProvider.filtering!.filters[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + onTap: () => onOpenDetailsModal(filteringProvider.filtering!.filters[index], 'blacklist'), + ), + ), + ), + ) + ], + ), + ), + Expanded( + flex: 1, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.customRules, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500 + ), + ), + AddFiltersButton( + type: '', + widget: (fn) => IconButton( + onPressed: fn, + icon: const Icon(Icons.add_rounded), + tooltip: AppLocalizations.of(context)!.addCustomRule, + ) + ) + ], + ), + ), + Expanded( + child: ListView.builder( + itemCount: filteringProvider.filtering!.userRules.length, + itemBuilder: (context, index) => ContextMenuArea( + builder: (context) => [ + CustomListTile( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + onTap: () { + copyToClipboard( + value: filteringProvider.filtering!.userRules[index], + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ); + Navigator.pop(context); + } + ), + ], + child: CustomListTile( + onLongPress: () => showDialog( + context: context, + builder: (context) => OptionsModal( + options: [ + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: () => copyToClipboard( + value: filteringProvider.filtering!.userRules[index], + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ) + ) + ] + ) + ), + title: filteringProvider.filtering!.userRules[index], + subtitleWidget: generateSubtitle(filteringProvider.filtering!.userRules[index]), + trailing: IconButton( + onPressed: () => onRemoveCustomRule(filteringProvider.filtering!.userRules[index]), + icon: const Icon(Icons.delete), + tooltip: AppLocalizations.of(context)!.delete, + ), + ), + ), + ), + ) + ], + ), + ), + ], + ); + + case LoadStatus.error: + return SizedBox.expand( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.filtersNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ) ); } } \ No newline at end of file diff --git a/lib/screens/logs/configuration/config_widgets.dart b/lib/screens/logs/configuration/config_widgets.dart index 44523f3..2d70285 100644 --- a/lib/screens/logs/configuration/config_widgets.dart +++ b/lib/screens/logs/configuration/config_widgets.dart @@ -11,8 +11,8 @@ class LogsConfigOptions extends StatelessWidget { final bool anonymizeClientIp; final void Function(bool) updateAnonymizeClientIp; final List retentionItems; - final String? retentionTime; - final void Function(String?) updateRetentionTime; + final double? retentionTime; + final void Function(double?) updateRetentionTime; final void Function() onClear; final void Function() onConfirm; @@ -130,14 +130,12 @@ class LogsConfigOptions extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: DropdownButtonFormField( - items: retentionItems.map>((item) { - return DropdownMenuItem( - value: item.value.toString(), - child: Text(item.label), - ); - }).toList(), + items: retentionItems.map((item) => DropdownMenuItem( + value: item.value, + child: Text(item.label), + )).toList(), value: retentionTime, - onChanged: (value) => updateRetentionTime(value), + onChanged: (value) => updateRetentionTime(value as double), decoration: InputDecoration( border: const OutlineInputBorder( borderRadius: BorderRadius.all( diff --git a/lib/screens/logs/configuration/logs_config_modal.dart b/lib/screens/logs/configuration/logs_config_modal.dart index 698348c..8db61ba 100644 --- a/lib/screens/logs/configuration/logs_config_modal.dart +++ b/lib/screens/logs/configuration/logs_config_modal.dart @@ -79,7 +79,7 @@ class LogsConfigModalWidget extends StatefulWidget { class _LogsConfigModalWidgetState extends State { bool generalSwitch = false; bool anonymizeClientIp = false; - String? retentionTime = ""; + double? retentionTime; List retentionItems = []; @@ -101,8 +101,10 @@ class _LogsConfigModalWidgetState extends State { setState(() { generalSwitch = result['data']['enabled']; anonymizeClientIp = result['data']['anonymize_client_ip']; - retentionTime = result['data']['interval'].toString(); - loadStatus = LoadStatus.loading; + retentionTime = result['data']['interval'] != null + ? double.parse(result['data']['interval'].toString()) + : null; + loadStatus = LoadStatus.loaded; }); } else { @@ -191,7 +193,7 @@ class _LogsConfigModalWidgetState extends State { onClear: () => widget.onClear(), onConfirm: () => widget.onConfirm({ "enabled": generalSwitch, - "interval": double.parse(retentionTime!), + "interval": retentionTime, "anonymize_client_ip": anonymizeClientIp }) ); @@ -235,7 +237,7 @@ class _LogsConfigModalWidgetState extends State { onClear: () => widget.onClear(), onConfirm: () => widget.onConfirm({ "enabled": generalSwitch, - "interval": double.parse(retentionTime!), + "interval": retentionTime, "anonymize_client_ip": anonymizeClientIp }) ); From c1950fdc2bba5fcc286dc1c4492bc107aca47687 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 12 Nov 2023 18:51:41 +0100 Subject: [PATCH 370/676] Fixed update notification --- lib/main.dart | 26 +------------------------- lib/widgets/layout.dart | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8696561..b025caa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,9 +18,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/layout.dart'; import 'package:adguard_home_manager/widgets/menu_bar.dart'; -import 'package:adguard_home_manager/functions/check_app_updates.dart'; -import 'package:adguard_home_manager/functions/open_url.dart'; -import 'package:adguard_home_manager/widgets/update_modal.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; @@ -180,7 +177,7 @@ class Main extends StatefulWidget { State
createState() => _MainState(); } -class _MainState extends State
with WidgetsBindingObserver { +class _MainState extends State
{ List modes = []; DisplayMode? active; DisplayMode? preferred; @@ -201,28 +198,7 @@ class _MainState extends State
with WidgetsBindingObserver { void initState() { displayMode(); - WidgetsBinding.instance.addObserver(this); - super.initState(); - - WidgetsBinding.instance.addPostFrameCallback((_) async { - final appConfigProvider = Provider.of(context, listen: false); - final result = await checkAppUpdates( - currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, - installationSource: appConfigProvider.installationSource, - setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, - isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), - ); - if (result != null && appConfigProvider.doNotRememberVersion != result.tagName && mounted) { - showDialog( - context: context, - builder: (context) => UpdateModal( - gitHubRelease: result, - onDownload: (link, version) => openUrl(link), - ), - ); - } - }); } @override diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index 8edcd56..8465a18 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -3,8 +3,11 @@ import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/update_modal.dart'; import 'package:adguard_home_manager/widgets/system_ui_overlay_style.dart'; +import 'package:adguard_home_manager/functions/check_app_updates.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; import 'package:adguard_home_manager/config/sizes.dart'; @@ -19,13 +22,39 @@ class Layout extends StatefulWidget { State createState() => _LayoutState(); } -class _LayoutState extends State { +class _LayoutState extends State with WidgetsBindingObserver { bool _drawerExpanded = true; void _goBranch(int index) { Provider.of(context, listen: false).setSelectedScreen(index); } + @override + void initState() { + WidgetsBinding.instance.addObserver(this); + + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback((_) async { + final appConfigProvider = Provider.of(context, listen: false); + final result = await checkAppUpdates( + currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, + installationSource: appConfigProvider.installationSource, + setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, + isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), + ); + if (result != null && appConfigProvider.doNotRememberVersion != result.tagName && mounted) { + await showDialog( + context: context, + builder: (context) => UpdateModal( + gitHubRelease: result, + onDownload: (link, version) => openUrl(link), + ), + ); + } + }); + } + @override Widget build(BuildContext context) { final width = MediaQuery.of(context).size.width; From 1ea71265e22522a2b673bbce6db1050bae1abb7c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 15 Nov 2023 18:16:43 +0100 Subject: [PATCH 371/676] Bugs fixed --- lib/models/dhcp.dart | 2 +- lib/screens/filters/filters_list.dart | 2 +- .../access_settings/clients_list.dart | 2 +- lib/screens/settings/advanced_setings.dart | 1 + lib/services/http_requests.dart | 75 +++++++++++-------- lib/widgets/layout.dart | 8 +- 6 files changed, 54 insertions(+), 36 deletions(-) diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index c04ecc9..21b460b 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -76,7 +76,7 @@ class DhcpStatus { v6: json["v6"] != null ? IpVersion.fromJson(json["v6"]) : null, leases: List.from(json["leases"].map((x) => Lease.fromJson(x))), staticLeases: List.from(json["static_leases"].map((x) => Lease.fromJson(x))), - enabled: json["enabled"], + enabled: json["enabled"] ?? false, ); Map toJson() => { diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index 3fdf3d5..5c93fb0 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -132,7 +132,7 @@ class _FiltersListState extends State { TextButton.icon( onPressed: () async { final result = await filteringProvider.fetchFilters(); - if (result == false) { + if (result == false && mounted) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 6f87c7c..fcffbef 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -70,7 +70,7 @@ class _ClientsListState extends State { Future refetchClients() async { final result = await clientsProvider.fetchClients(); - if (result == false) { + if (result == false && mounted) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientsNotLoaded, diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 75572c1..39a93e3 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -24,6 +24,7 @@ class AdvancedSettings extends StatelessWidget { required Future Function(bool) function }) async { final result = await function(newStatus); + if (!context.mounted) return; if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 7fe18e0..a2eb5ec 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1330,55 +1330,68 @@ class ApiClient { } Future getDhcpData() async { - final result = await Future.wait([ - apiRequest( - urlPath: '/dhcp/interfaces', - method: 'get', - server: server, - type: 'get_dhcp_data' - ), - apiRequest( - urlPath: '/dhcp/status', - method: 'get', - server: server, - type: 'get_dhcp_data' - ), - ]); + try { + final result = await Future.wait([ + apiRequest( + urlPath: '/dhcp/interfaces', + method: 'get', + server: server, + type: 'get_dhcp_data' + ), + apiRequest( + urlPath: '/dhcp/status', + method: 'get', + server: server, + type: 'get_dhcp_data' + ), + ]); - if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - List interfaces = List.from(jsonDecode(result[0]['body']).entries.map((entry) => NetworkInterface.fromJson(entry.value))); + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { + List interfaces = List.from(jsonDecode(result[0]['body']).entries.map((entry) => NetworkInterface.fromJson(entry.value))); - return { - 'result': 'success', - 'data': DhcpModel( - networkInterfaces: interfaces, - dhcpStatus: DhcpStatus.fromJson(jsonDecode(result[1]['body'])) - ) - }; + return { + 'result': 'success', + 'data': DhcpModel( + networkInterfaces: interfaces, + dhcpStatus: DhcpStatus.fromJson(jsonDecode(result[1]['body'])) + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_dhcp_data', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { 'result': 'error', 'log': AppLog( - type: 'get_dhcp_data', + type: 'get_dhpc_data', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: [result[0]['log'].message, result[1]['log'].message].toString(), statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } - } - else { + } catch (e) { + Sentry.captureException(e); return { 'result': 'error', 'log': AppLog( type: 'get_dhpc_data', dateTime: DateTime.now(), - message: [result[0]['log'].message, result[1]['log'].message].toString(), - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), + message: 'error_code_not_expected', + resBody: e.toString(), ) }; } diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index 8465a18..fe3aa1c 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -153,7 +153,9 @@ class _LayoutState extends State with WidgetsBindingObserver { child: child, ) ), - child: screens[appConfigProvider.selectedScreen].child, + child: appConfigProvider.selectedScreen < screens.length + ? screens[appConfigProvider.selectedScreen].child + : screens[0].child, ), ), ], @@ -177,7 +179,9 @@ class _LayoutState extends State with WidgetsBindingObserver { child: child, ) ), - child: screens[appConfigProvider.selectedScreen].child, + child: appConfigProvider.selectedScreen < screens.length + ? screens[appConfigProvider.selectedScreen].child + : screens[0].child, ), bottomNavigationBar: NavigationBar( selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 From ad42438ce3737f9b5a5460be1f7069253ae5adac Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 15 Nov 2023 18:28:10 +0100 Subject: [PATCH 372/676] Changed list details modal opening --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/screens/filters/filters.dart | 47 ++++++------ lib/screens/filters/list_details_screen.dart | 79 +++++++++++--------- lib/screens/filters/list_options_menu.dart | 19 ++++- 5 files changed, 87 insertions(+), 64 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index d4962e3..ab0908a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -669,5 +669,6 @@ "showTopItemsChart": "Show top items chart", "showTopItemsChartDescription": "Shows by default the ring chart on the top items sections. Only affects to the mobile view.", "openMenu": "Open menu", - "closeMenu": "Close menu" + "closeMenu": "Close menu", + "openListUrl": "Open list URL" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 2f202a8..9836280 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -669,5 +669,6 @@ "showTopItemsChart": "Mostrar gráfico en top de items", "showTopItemsChartDescription": "Muestra por defecto el gráfico de anillo en las secciones de top de items. Sólo afecta a la vista móvil.", "openMenu": "Abrir menú", - "closeMenu": "Cerrar menú" + "closeMenu": "Cerrar menú", + "openListUrl": "Abrir URL de lista" } \ No newline at end of file diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 5975cf6..cb5cbdb 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -190,28 +190,31 @@ class _FiltersState extends State { } void openListDetails(Filter filter, String type) { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => ListDetailsScreen( - listId: filter.id, - type: type, - dialog: true, - ), - barrierDismissible: false - ); - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ListDetailsScreen( - listId: filter.id, - type: type, - dialog: false, - ) - ) - ); - } + showGeneralDialog( + context: context, + barrierColor: !(width > 900 || !(Platform.isAndroid | Platform.isIOS)) + ?Colors.transparent + : Colors.black54, + transitionBuilder: (context, anim1, anim2, child) { + return SlideTransition( + position: Tween( + begin: const Offset(0, 1), + end: const Offset(0, 0) + ).animate( + CurvedAnimation( + parent: anim1, + curve: Curves.easeInOutCubicEmphasized + ) + ), + child: child, + ); + }, + pageBuilder: (context, animation, secondaryAnimation) => ListDetailsScreen( + listId: filter.id, + type: type, + dialog: width > 900 || !(Platform.isAndroid | Platform.isIOS), + ), + ); } List actions() { diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 236ee75..c0c9e2b 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -352,47 +352,52 @@ class _ListDetailsScreenState extends State { ); } else { - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.listDetails), - actions: list != null ? actions() : null, - ), - body: Stack( - children: [ - if (list != null) ListView( - children: content(), + return Dialog.fullscreen( + child: Scaffold( + appBar: AppBar( + leading: CloseButton( + onPressed: () => Navigator.pop(context), ), - if (list == null) Center( - child: Text( - AppLocalizations.of(context)!.listNotAvailable, - style: const TextStyle( - fontSize: 24, + title: Text(AppLocalizations.of(context)!.listDetails), + actions: list != null ? actions() : null, + ), + body: Stack( + children: [ + if (list != null) ListView( + children: content(), + ), + if (list == null) Center( + child: Text( + AppLocalizations.of(context)!.listNotAvailable, + style: const TextStyle( + fontSize: 24, + ), ), ), - ), - if (list != null) AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: fabVisible ? - appConfigProvider.showingSnackbar - ? 70 : (Platform.isIOS ? 40 : 20) - : -70, - right: 20, - child: FloatingActionButton( - onPressed: () => updateList( - action: list!.enabled == true - ? FilteringListActions.disable - : FilteringListActions.enable, - filterList: list + if (list != null) AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: fabVisible ? + appConfigProvider.showingSnackbar + ? 70 : (Platform.isIOS ? 40 : 20) + : -70, + right: 20, + child: FloatingActionButton( + onPressed: () => updateList( + action: list!.enabled == true + ? FilteringListActions.disable + : FilteringListActions.enable, + filterList: list + ), + child: Icon( + list.enabled == true + ? Icons.gpp_bad_rounded + : Icons.verified_user_rounded, + ), ), - child: Icon( - list.enabled == true - ? Icons.gpp_bad_rounded - : Icons.verified_user_rounded, - ), - ), - ) - ], + ) + ], + ), ), ); } diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 1d644a0..91ca07f 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -1,6 +1,7 @@ // ignore_for_file: use_build_context_synchronously -import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:contextmenu/contextmenu.dart'; import 'package:provider/provider.dart'; @@ -9,6 +10,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; @@ -92,11 +95,16 @@ class ListOptionsMenu extends StatelessWidget { ); } ), + CustomListTile( + title: AppLocalizations.of(context)!.openListUrl, + icon: Icons.open_in_browser_rounded, + onTap: () => openUrl(list.url) + ), ], child: Material( color: Colors.transparent, child: InkWell( - onLongPress: () => showDialog( + onLongPress: Platform.isAndroid || Platform.isIOS ? () => showDialog( context: context, builder: (context) => OptionsModal( options: [ @@ -117,9 +125,14 @@ class ListOptionsMenu extends StatelessWidget { successMessage: AppLocalizations.of(context)!.listUrlCopied ) ), + MenuOption( + title: AppLocalizations.of(context)!.openListUrl, + icon: Icons.open_in_browser_rounded, + action: () => openUrl(list.url) + ), ] ) - ), + ) : null, child: child ), ), From 5768eac1b25b4f0368678db8e3c3ee9e8424c42a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 15 Nov 2023 18:31:31 +0100 Subject: [PATCH 373/676] Open list url from modal --- lib/screens/filters/list_details_screen.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index c0c9e2b..90fb5c7 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -11,6 +11,7 @@ import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -158,6 +159,11 @@ class _ListDetailsScreenState extends State { vertical: 8 ) : null, + trailing: IconButton( + onPressed: () => openUrl(list!.url), + icon: const Icon(Icons.open_in_browser_rounded), + tooltip: AppLocalizations.of(context)!.openListUrl, + ), ), CustomListTile( icon: Icons.list_rounded, From 9d3391aa0d76b0297e897618b0aa03e1a31f3b2a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 15 Nov 2023 19:42:04 +0100 Subject: [PATCH 374/676] Added selection mode --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/screens/filters/list_options_menu.dart | 39 +++ lib/screens/filters/selection_screen.dart | 365 +++++++++++++++++++++ lib/widgets/custom_list_tile.dart | 4 +- 5 files changed, 411 insertions(+), 3 deletions(-) create mode 100644 lib/screens/filters/selection_screen.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ab0908a..9f955e9 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -670,5 +670,6 @@ "showTopItemsChartDescription": "Shows by default the ring chart on the top items sections. Only affects to the mobile view.", "openMenu": "Open menu", "closeMenu": "Close menu", - "openListUrl": "Open list URL" + "openListUrl": "Open list URL", + "selectionMode": "Selection mode" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 9836280..ab46506 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -670,5 +670,6 @@ "showTopItemsChartDescription": "Muestra por defecto el gráfico de anillo en las secciones de top de items. Sólo afecta a la vista móvil.", "openMenu": "Abrir menú", "closeMenu": "Cerrar menú", - "openListUrl": "Abrir URL de lista" + "openListUrl": "Abrir URL de lista", + "selectionMode": "Modo de selección" } \ No newline at end of file diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 91ca07f..698d803 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -9,6 +9,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; +import 'package:adguard_home_manager/screens/filters/selection_screen.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -36,6 +37,8 @@ class ListOptionsMenu extends StatelessWidget { final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final width = MediaQuery.of(context).size.width; + void enableDisable() async { ProcessModal processModal = ProcessModal(context: context); processModal.open( @@ -70,6 +73,32 @@ class ListOptionsMenu extends StatelessWidget { } } + void openSelectionMode() { + showGeneralDialog( + context: context, + barrierColor: !(width > 900 || !(Platform.isAndroid | Platform.isIOS)) + ?Colors.transparent + : Colors.black54, + transitionBuilder: (context, anim1, anim2, child) { + return SlideTransition( + position: Tween( + begin: const Offset(0, 1), + end: const Offset(0, 0) + ).animate( + CurvedAnimation( + parent: anim1, + curve: Curves.easeInOutCubicEmphasized + ) + ), + child: child, + ); + }, + pageBuilder: (context, animation, secondaryAnimation) => SelectionScreen( + isModal: width > 900 || !(Platform.isAndroid | Platform.isIOS) + ) + ); + } + return ContextMenuArea( builder: (context) => [ CustomListTile( @@ -100,6 +129,11 @@ class ListOptionsMenu extends StatelessWidget { icon: Icons.open_in_browser_rounded, onTap: () => openUrl(list.url) ), + CustomListTile( + title: AppLocalizations.of(context)!.selectionMode, + icon: Icons.check_rounded, + onTap: openSelectionMode + ), ], child: Material( color: Colors.transparent, @@ -130,6 +164,11 @@ class ListOptionsMenu extends StatelessWidget { icon: Icons.open_in_browser_rounded, action: () => openUrl(list.url) ), + MenuOption( + title: AppLocalizations.of(context)!.selectionMode, + icon: Icons.check_rounded, + action: openSelectionMode + ), ] ) ) : null, diff --git a/lib/screens/filters/selection_screen.dart b/lib/screens/filters/selection_screen.dart new file mode 100644 index 0000000..6ef3e77 --- /dev/null +++ b/lib/screens/filters/selection_screen.dart @@ -0,0 +1,365 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; + +class SelectionScreen extends StatefulWidget { + final bool isModal; + + const SelectionScreen({ + Key? key, + required this.isModal + }) : super(key: key); + + @override + State createState() => _SelectionScreenState(); +} + +class _SelectionScreenState extends State with TickerProviderStateMixin { + late TabController _tabController; + + List _selectedLists = []; + + @override + void initState() { + super.initState(); + _tabController = TabController( + initialIndex: 0, + length: 2, + vsync: this, + ); + } + + void handleSelect(Filter list) { + final isContained = _selectedLists.contains(list); + if (isContained) { + setState(() => _selectedLists = _selectedLists.where((l) => l != list).toList()); + } + else { + setState(() => _selectedLists.add(list)); + } + } + + @override + Widget build(BuildContext context) { + final filteringProvider = Provider.of(context); + + if (widget.isModal == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, + ), + const SizedBox(width: 8), + Text( + AppLocalizations.of(context)!.selectionMode, + style: const TextStyle( + fontSize: 22 + ), + ) + ], + ), + + ], + ), + ), + Expanded( + child: DefaultTabController( + length: 2, + child: Column( + children: [ + TabBar( + controller: _tabController, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.verified_user_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.whitelists,) + ], + ), + ), + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.gpp_bad_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.blacklists) + ], + ), + ), + ] + ), + Expanded( + child: TabBarView( + controller: _tabController, + children: [ + _List( + lists: filteringProvider.filtering!.whitelistFilters, + selectedLists: _selectedLists, + onSelect: handleSelect, + ), + _List( + lists: filteringProvider.filtering!.filters, + selectedLists: _selectedLists, + onSelect: handleSelect, + ), + ] + ), + ) + ], + ) + ), + ) + ], + ), + ), + ); + } + else { + return Dialog.fullscreen( + child: DefaultTabController( + length: 2, + child: NestedScrollView( + + headerSliverBuilder: ((context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + leading: CloseButton( + onPressed: () => Navigator.pop(context), + ), + title: Text(AppLocalizations.of(context)!.selectionMode), + pinned: true, + floating: true, + forceElevated: innerBoxIsScrolled, + centerTitle: false, + bottom: TabBar( + controller: _tabController, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.verified_user_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.whitelists,) + ], + ), + ), + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.gpp_bad_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.blacklists) + ], + ), + ), + ] + ) + ), + ) + ]; + }), + body: TabBarView( + controller: _tabController, + children: [ + _SliverList( + lists: filteringProvider.filtering!.whitelistFilters, + selectedLists: _selectedLists, + onSelect: handleSelect, + ), + _SliverList( + lists: filteringProvider.filtering!.filters, + selectedLists: _selectedLists, + onSelect: handleSelect, + ), + ] + ) + ) + ), + ); + } + } +} + +class _SliverList extends StatelessWidget { + final List lists; + final List selectedLists; + final void Function(Filter) onSelect; + + const _SliverList({ + Key? key, + required this.lists, + required this.selectedLists, + required this.onSelect, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (BuildContext context) { + return CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (lists.isNotEmpty) SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) => CustomListTile( + title: lists[index].name, + subtitle: lists[index].url, + color: selectedLists.contains(lists[index]) + ? Theme.of(context).colorScheme.primaryContainer + : null, + trailing: Column( + children: [ + Icon( + lists[index].enabled == true + ? Icons.check_rounded + : Icons.close_rounded, + size: 12, + color: lists[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + const SizedBox(height: 4), + Text( + lists[index].enabled == true + ? AppLocalizations.of(context)!.enabled + : AppLocalizations.of(context)!.disabled, + style: TextStyle( + fontSize: 10, + color: lists[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + ) + ], + ), + onTap: () => onSelect(lists[index]), + ), + childCount: lists.length + ), + ), + if (lists.isEmpty) SliverFillRemaining( + child: Center( + child: Text( + AppLocalizations.of(context)!.noItems, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ) + ) + ], + ); + }, + ), + ); + } +} + +class _List extends StatelessWidget { + final List lists; + final List selectedLists; + final void Function(Filter) onSelect; + + const _List({ + Key? key, + required this.lists, + required this.selectedLists, + required this.onSelect, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + + return ListView.builder( + itemCount: lists.length, + itemBuilder: (context, index) => CustomListTile( + title: lists[index].name, + subtitle: lists[index].url, + color: selectedLists.contains(lists[index]) + ? Theme.of(context).colorScheme.primaryContainer + : null, + trailing: Column( + children: [ + Icon( + lists[index].enabled == true + ? Icons.check_rounded + : Icons.close_rounded, + size: 12, + color: lists[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + const SizedBox(height: 4), + Text( + lists[index].enabled == true + ? AppLocalizations.of(context)!.enabled + : AppLocalizations.of(context)!.disabled, + style: TextStyle( + fontSize: 10, + color: lists[index].enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + ) + ], + ), + onTap: () => onSelect(lists[index]), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/custom_list_tile.dart b/lib/widgets/custom_list_tile.dart index 6f27129..0523468 100644 --- a/lib/widgets/custom_list_tile.dart +++ b/lib/widgets/custom_list_tile.dart @@ -11,6 +11,7 @@ class CustomListTile extends StatelessWidget { final void Function()? onLongPress; final bool? disabled; final void Function(bool)? onHover; + final Color? color; const CustomListTile({ Key? key, @@ -24,12 +25,13 @@ class CustomListTile extends StatelessWidget { this.onLongPress, this.disabled, this.onHover, + this.color, }) : super(key: key); @override Widget build(BuildContext context) { return Material( - color: Colors.transparent, + color: color ?? Colors.transparent, child: InkWell( onTap: onTap, onHover: onHover, From b6bf2d80c74c1fa95d439fbae43cee3b9c2b9a43 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 17 Nov 2023 01:30:48 +0100 Subject: [PATCH 375/676] Select items, select all and fabs --- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/screens/filters/list_options_menu.dart | 2 +- .../filters/selection/selection_lists.dart | 215 +++++++++++ .../filters/selection/selection_screen.dart | 312 +++++++++++++++ lib/screens/filters/selection_screen.dart | 365 ------------------ 6 files changed, 534 insertions(+), 368 deletions(-) create mode 100644 lib/screens/filters/selection/selection_lists.dart create mode 100644 lib/screens/filters/selection/selection_screen.dart delete mode 100644 lib/screens/filters/selection_screen.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 9f955e9..0d247be 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -671,5 +671,7 @@ "openMenu": "Open menu", "closeMenu": "Close menu", "openListUrl": "Open list URL", - "selectionMode": "Selection mode" + "selectionMode": "Selection mode", + "enableDisableSelected": "Enable or disable selected items", + "deleteSelected": "Delete selected items" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index ab46506..26be7c5 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -671,5 +671,7 @@ "openMenu": "Abrir menú", "closeMenu": "Cerrar menú", "openListUrl": "Abrir URL de lista", - "selectionMode": "Modo de selección" + "selectionMode": "Modo de selección", + "enableDisableSelected": "Activar o desactivar elementos seleccionados", + "deleteSelected": "Eliminar elementos seleccionados" } \ No newline at end of file diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 698d803..0dbf2ab 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -9,7 +9,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; -import 'package:adguard_home_manager/screens/filters/selection_screen.dart'; +import 'package:adguard_home_manager/screens/filters/selection/selection_screen.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; diff --git a/lib/screens/filters/selection/selection_lists.dart b/lib/screens/filters/selection/selection_lists.dart new file mode 100644 index 0000000..7bb2a2c --- /dev/null +++ b/lib/screens/filters/selection/selection_lists.dart @@ -0,0 +1,215 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; + +class SelectionList extends StatelessWidget { + final List lists; + final List selectedLists; + final void Function(Filter) onSelect; + final void Function() selectAll; + final void Function() unselectAll; + + const SelectionList({ + Key? key, + required this.lists, + required this.selectedLists, + required this.onSelect, + required this.selectAll, + required this.unselectAll, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ListView.builder( + itemCount: lists.length+1, + itemBuilder: (context, index) { + if (index == 0) { + return CheckboxListTile( + title: Text(AppLocalizations.of(context)!.selectAll), + value: lists.length == selectedLists.length, + onChanged: (value) { + if (value == true) { + selectAll(); + } + else { + unselectAll(); + } + }, + ); + } + return _Tile( + list: lists[index-1], + onSelect: onSelect, + isSelected: selectedLists.contains(lists[index-1]), + ); + } + ); + } +} + +class SelectionSliverList extends StatelessWidget { + final List lists; + final List selectedLists; + final void Function(Filter) onSelect; + final void Function() selectAll; + final void Function() unselectAll; + + const SelectionSliverList({ + Key? key, + required this.lists, + required this.selectedLists, + required this.onSelect, + required this.selectAll, + required this.unselectAll, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (BuildContext context) { + return CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (lists.isNotEmpty) SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + if (index == 0) { + return Card( + margin: const EdgeInsets.all(16), + child: CheckboxListTile( + title: Text(AppLocalizations.of(context)!.selectAll), + value: lists.length == selectedLists.length, + onChanged: (value) { + if (value == true) { + selectAll(); + } + else { + unselectAll(); + } + }, + checkboxShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4) + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12) + ), + ), + ); + } + return _Tile( + list: lists[index-1], + onSelect: onSelect, + isSelected: selectedLists.contains(lists[index-1]), + ); + }, + childCount: lists.length+1 + ), + ), + if (lists.isEmpty) SliverFillRemaining( + child: Center( + child: Text( + AppLocalizations.of(context)!.noItems, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ) + ) + ], + ); + }, + ), + ); + } +} + +class _Tile extends StatelessWidget { + final Filter list; + final void Function(Filter) onSelect; + final bool isSelected; + + const _Tile({ + Key? key, + required this.list, + required this.onSelect, + required this.isSelected, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + + return ListTile( + title: Text( + list.name, + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + list.url, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 8), + Row( + children: [ + Icon( + list.enabled == true + ? Icons.check_rounded + : Icons.close_rounded, + size: 16, + color: list.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + const SizedBox(width: 4), + Text( + list.enabled == true + ? AppLocalizations.of(context)!.enabled + : AppLocalizations.of(context)!.disabled, + style: TextStyle( + fontSize: 12, + color: list.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + ) + ], + ) + ], + ), + isThreeLine: true, + tileColor: isSelected == true + ? Theme.of(context).colorScheme.primaryContainer + : null, + contentPadding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 16 + ), + selected: isSelected, + selectedTileColor: Theme.of(context).colorScheme.primaryContainer, + selectedColor: Theme.of(context).colorScheme.onSurface, + onTap: () => onSelect(list), + ); + } +} + diff --git a/lib/screens/filters/selection/selection_screen.dart b/lib/screens/filters/selection/selection_screen.dart new file mode 100644 index 0000000..375ae67 --- /dev/null +++ b/lib/screens/filters/selection/selection_screen.dart @@ -0,0 +1,312 @@ +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/filters/selection/selection_lists.dart'; + +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; + +enum ListType { blacklist, whitelist } + +class SelectionScreen extends StatefulWidget { + final bool isModal; + + const SelectionScreen({ + Key? key, + required this.isModal + }) : super(key: key); + + @override + State createState() => _SelectionScreenState(); +} + +class _SelectionScreenState extends State with TickerProviderStateMixin { + late TabController _tabController; + late ScrollController _scrollController; + + bool _isScrolled = false; + + List _selectedWhitelists = []; + List _selectedBlacklists = []; + + @override + void initState() { + super.initState(); + _tabController = TabController( + initialIndex: 0, + length: 2, + vsync: this, + ); + _scrollController = ScrollController()..addListener(() { + setState(() => _isScrolled = _scrollController.offset > 0); + }); + } + + void handleSelect(Filter list, ListType type) { + if (type == ListType.blacklist) { + final isContained = _selectedBlacklists.contains(list); + if (isContained) { + setState(() => _selectedBlacklists = _selectedBlacklists.where((l) => l != list).toList()); + } + else { + setState(() => _selectedBlacklists.add(list)); + } + } + else if (type == ListType.whitelist) { + final isContained = _selectedWhitelists.contains(list); + if (isContained) { + setState(() => _selectedWhitelists = _selectedWhitelists.where((l) => l != list).toList()); + } + else { + setState(() => _selectedWhitelists.add(list)); + } + } + } + + @override + Widget build(BuildContext context) { + final filteringProvider = Provider.of(context); + + final somethingSelected = _selectedBlacklists.isNotEmpty || _selectedWhitelists.isNotEmpty; + + void enableDisableSelected() { + + } + + void deleteSelected() { + + } + + if (widget.isModal == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, + ), + const SizedBox(width: 8), + Text( + AppLocalizations.of(context)!.selectionMode, + style: const TextStyle( + fontSize: 22 + ), + ) + ], + ), + + ], + ), + ), + Expanded( + child: DefaultTabController( + length: 2, + child: Column( + children: [ + TabBar( + controller: _tabController, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + _Tab( + icon: Icons.verified_user_rounded, + text: AppLocalizations.of(context)!.whitelists, + quantity: _selectedWhitelists.length + ), + _Tab( + icon: Icons.gpp_bad_rounded, + text: AppLocalizations.of(context)!.blacklist, + quantity: _selectedBlacklists.length + ), + ] + ), + Expanded( + child: TabBarView( + controller: _tabController, + children: [ + SelectionList( + lists: filteringProvider.filtering!.whitelistFilters, + selectedLists: _selectedWhitelists, + onSelect: (list) => handleSelect(list, ListType.whitelist), + selectAll: () => setState(() => _selectedWhitelists = filteringProvider.filtering!.whitelistFilters), + unselectAll: () => setState(() => []) + ), + SelectionList( + lists: filteringProvider.filtering!.filters, + selectedLists: _selectedBlacklists, + onSelect: (list) => handleSelect(list, ListType.blacklist), + selectAll: () => setState(() => _selectedBlacklists = filteringProvider.filtering!.filters), + unselectAll: () => setState(() => _selectedBlacklists = []) + ), + ] + ), + ) + ], + ) + ), + ) + ], + ), + ), + ); + } + else { + return Dialog.fullscreen( + child: Stack( + children: [ + DefaultTabController( + length: 2, + child: NestedScrollView( + controller: _scrollController, + headerSliverBuilder: ((context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + leading: CloseButton( + onPressed: () => Navigator.pop(context), + ), + title: Text(AppLocalizations.of(context)!.selectionMode), + pinned: true, + floating: true, + forceElevated: innerBoxIsScrolled, + centerTitle: false, + bottom: TabBar( + controller: _tabController, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + _Tab( + icon: Icons.verified_user_rounded, + text: AppLocalizations.of(context)!.whitelists, + quantity: _selectedWhitelists.length + ), + _Tab( + icon: Icons.gpp_bad_rounded, + text: AppLocalizations.of(context)!.blacklist, + quantity: _selectedBlacklists.length + ), + ] + ) + ), + ) + ]; + }), + body: TabBarView( + controller: _tabController, + children: [ + SelectionSliverList( + lists: filteringProvider.filtering!.whitelistFilters, + selectedLists: _selectedWhitelists, + onSelect: (list) => handleSelect(list, ListType.whitelist), + selectAll: () => setState(() => _selectedWhitelists = filteringProvider.filtering!.whitelistFilters), + unselectAll: () => setState(() => _selectedWhitelists = []), + ), + SelectionSliverList( + lists: filteringProvider.filtering!.filters, + selectedLists: _selectedBlacklists, + onSelect: (list) => handleSelect(list, ListType.blacklist), + selectAll: () => setState(() => _selectedBlacklists = filteringProvider.filtering!.filters), + unselectAll: () => setState(() => _selectedBlacklists = []), + ), + ] + ) + ) + ), + AnimatedPositioned( + duration: const Duration(milliseconds: 200), + curve: Curves.ease, + right: 16, + bottom: _isScrolled ? -150 : 16, + child: Column( + children: [ + FloatingActionButton.small( + onPressed: somethingSelected == true + ? () => enableDisableSelected() + : null, + tooltip: AppLocalizations.of(context)!.enableDisableSelected, + child: Icon( + Icons.shield_rounded, + color: somethingSelected == true + ? Theme.of(context).colorScheme.onPrimaryContainer + : Theme.of(context).colorScheme.secondary, + ), + ), + const SizedBox(height: 16), + FloatingActionButton.small( + onPressed: somethingSelected == true + ? () => deleteSelected() + : null, + tooltip: AppLocalizations.of(context)!.deleteSelected, + child: Icon( + Icons.delete_rounded, + color: somethingSelected == true + ? Theme.of(context).colorScheme.onPrimaryContainer + : Theme.of(context).colorScheme.secondary, + ), + ), + ], + ), + ) + ], + ), + ); + } + } +} + +class _Tab extends StatelessWidget { + final IconData icon; + final String text; + final int quantity; + + const _Tab({ + Key? key, + required this.icon, + required this.text, + required this.quantity + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon), + const SizedBox(width: 8), + Text(text), + const SizedBox(width: 8), + Container( + width: 18, + height: 18, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Theme.of(context).colorScheme.primaryContainer + ), + child: Text( + quantity.toString(), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + color: Theme.of(context).colorScheme.onPrimaryContainer + ), + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/filters/selection_screen.dart b/lib/screens/filters/selection_screen.dart deleted file mode 100644 index 6ef3e77..0000000 --- a/lib/screens/filters/selection_screen.dart +++ /dev/null @@ -1,365 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; - -import 'package:adguard_home_manager/models/filtering.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/filtering_provider.dart'; - -class SelectionScreen extends StatefulWidget { - final bool isModal; - - const SelectionScreen({ - Key? key, - required this.isModal - }) : super(key: key); - - @override - State createState() => _SelectionScreenState(); -} - -class _SelectionScreenState extends State with TickerProviderStateMixin { - late TabController _tabController; - - List _selectedLists = []; - - @override - void initState() { - super.initState(); - _tabController = TabController( - initialIndex: 0, - length: 2, - vsync: this, - ); - } - - void handleSelect(Filter list) { - final isContained = _selectedLists.contains(list); - if (isContained) { - setState(() => _selectedLists = _selectedLists.where((l) => l != list).toList()); - } - else { - setState(() => _selectedLists.add(list)); - } - } - - @override - Widget build(BuildContext context) { - final filteringProvider = Provider.of(context); - - if (widget.isModal == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.clear_rounded), - tooltip: AppLocalizations.of(context)!.close, - ), - const SizedBox(width: 8), - Text( - AppLocalizations.of(context)!.selectionMode, - style: const TextStyle( - fontSize: 22 - ), - ) - ], - ), - - ], - ), - ), - Expanded( - child: DefaultTabController( - length: 2, - child: Column( - children: [ - TabBar( - controller: _tabController, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.verified_user_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.whitelists,) - ], - ), - ), - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.gpp_bad_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.blacklists) - ], - ), - ), - ] - ), - Expanded( - child: TabBarView( - controller: _tabController, - children: [ - _List( - lists: filteringProvider.filtering!.whitelistFilters, - selectedLists: _selectedLists, - onSelect: handleSelect, - ), - _List( - lists: filteringProvider.filtering!.filters, - selectedLists: _selectedLists, - onSelect: handleSelect, - ), - ] - ), - ) - ], - ) - ), - ) - ], - ), - ), - ); - } - else { - return Dialog.fullscreen( - child: DefaultTabController( - length: 2, - child: NestedScrollView( - - headerSliverBuilder: ((context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar( - leading: CloseButton( - onPressed: () => Navigator.pop(context), - ), - title: Text(AppLocalizations.of(context)!.selectionMode), - pinned: true, - floating: true, - forceElevated: innerBoxIsScrolled, - centerTitle: false, - bottom: TabBar( - controller: _tabController, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.verified_user_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.whitelists,) - ], - ), - ), - Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.gpp_bad_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.blacklists) - ], - ), - ), - ] - ) - ), - ) - ]; - }), - body: TabBarView( - controller: _tabController, - children: [ - _SliverList( - lists: filteringProvider.filtering!.whitelistFilters, - selectedLists: _selectedLists, - onSelect: handleSelect, - ), - _SliverList( - lists: filteringProvider.filtering!.filters, - selectedLists: _selectedLists, - onSelect: handleSelect, - ), - ] - ) - ) - ), - ); - } - } -} - -class _SliverList extends StatelessWidget { - final List lists; - final List selectedLists; - final void Function(Filter) onSelect; - - const _SliverList({ - Key? key, - required this.lists, - required this.selectedLists, - required this.onSelect, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - final appConfigProvider = Provider.of(context); - - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (BuildContext context) { - return CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (lists.isNotEmpty) SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) => CustomListTile( - title: lists[index].name, - subtitle: lists[index].url, - color: selectedLists.contains(lists[index]) - ? Theme.of(context).colorScheme.primaryContainer - : null, - trailing: Column( - children: [ - Icon( - lists[index].enabled == true - ? Icons.check_rounded - : Icons.close_rounded, - size: 12, - color: lists[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ), - const SizedBox(height: 4), - Text( - lists[index].enabled == true - ? AppLocalizations.of(context)!.enabled - : AppLocalizations.of(context)!.disabled, - style: TextStyle( - fontSize: 10, - color: lists[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ), - ) - ], - ), - onTap: () => onSelect(lists[index]), - ), - childCount: lists.length - ), - ), - if (lists.isEmpty) SliverFillRemaining( - child: Center( - child: Text( - AppLocalizations.of(context)!.noItems, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ) - ) - ) - ], - ); - }, - ), - ); - } -} - -class _List extends StatelessWidget { - final List lists; - final List selectedLists; - final void Function(Filter) onSelect; - - const _List({ - Key? key, - required this.lists, - required this.selectedLists, - required this.onSelect, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - final appConfigProvider = Provider.of(context); - - return ListView.builder( - itemCount: lists.length, - itemBuilder: (context, index) => CustomListTile( - title: lists[index].name, - subtitle: lists[index].url, - color: selectedLists.contains(lists[index]) - ? Theme.of(context).colorScheme.primaryContainer - : null, - trailing: Column( - children: [ - Icon( - lists[index].enabled == true - ? Icons.check_rounded - : Icons.close_rounded, - size: 12, - color: lists[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ), - const SizedBox(height: 4), - Text( - lists[index].enabled == true - ? AppLocalizations.of(context)!.enabled - : AppLocalizations.of(context)!.disabled, - style: TextStyle( - fontSize: 10, - color: lists[index].enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ), - ) - ], - ), - onTap: () => onSelect(lists[index]), - ), - ); - } -} \ No newline at end of file From b8b34f7f47dcfb172f637528c0e2b215da2966aa Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 18 Nov 2023 22:58:27 +0100 Subject: [PATCH 376/676] Added enable disable lists and delete lists --- lib/l10n/app_en.arb | 10 +- lib/l10n/app_es.arb | 10 +- lib/models/filtering.dart | 16 +- lib/providers/filtering_provider.dart | 71 +++++++ .../selection/delete_selection_modal.dart | 150 ++++++++++++++ .../enable_disable_selection_modal.dart | 193 ++++++++++++++++++ .../filters/selection/selection_lists.dart | 125 ++++++++++-- .../selection/selection_result_modal.dart | 102 +++++++++ .../filters/selection/selection_screen.dart | 86 +++++++- lib/widgets/system_ui_overlay_style.dart | 2 +- 10 files changed, 739 insertions(+), 26 deletions(-) create mode 100644 lib/screens/filters/selection/delete_selection_modal.dart create mode 100644 lib/screens/filters/selection/enable_disable_selection_modal.dart create mode 100644 lib/screens/filters/selection/selection_result_modal.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 0d247be..2fc732c 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -673,5 +673,13 @@ "openListUrl": "Open list URL", "selectionMode": "Selection mode", "enableDisableSelected": "Enable or disable selected items", - "deleteSelected": "Delete selected items" + "deleteSelected": "Delete selected items", + "deleteSelectedLists": "Delete selected lists", + "allSelectedListsDeletedSuccessfully": "All selected lists have been deleted successfully.", + "deletionResult": "Deletion result", + "deletingLists": "Deleting lists...", + "failedElements": "Failed elements", + "processingLists": "Processing lists...", + "enableDisableResult": "Enable or disable result", + "selectedListsEnabledDisabledSuccessfully": "All selected lists have been enabled or disabled successfully" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 26be7c5..6f2d8d6 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -673,5 +673,13 @@ "openListUrl": "Abrir URL de lista", "selectionMode": "Modo de selección", "enableDisableSelected": "Activar o desactivar elementos seleccionados", - "deleteSelected": "Eliminar elementos seleccionados" + "deleteSelected": "Eliminar elementos seleccionados", + "deleteSelectedLists": "Eliminar listas seleccionadas", + "allSelectedListsDeletedSuccessfully": "Todas las listas seleccionadas han sido eliminadas correctamente.", + "deletionResult": "Resultado de eliminación", + "deletingLists": "Eliminando listas...", + "failedElements": "Elementos fallidos", + "processingLists": "Procesando listas...", + "enableDisableResult": "Resultado de activar o desactivar", + "selectedListsEnabledDisabledSuccessfully": "Todas las listas seleccionadas se han activado o desactivado correctamente." } \ No newline at end of file diff --git a/lib/models/filtering.dart b/lib/models/filtering.dart index 9b1d6ce..7b521d2 100644 --- a/lib/models/filtering.dart +++ b/lib/models/filtering.dart @@ -1,6 +1,6 @@ class Filtering { - final List filters; - final List whitelistFilters; + List filters; + List whitelistFilters; List userRules; List blockedServices; int interval; @@ -40,7 +40,7 @@ class Filter { final DateTime? lastUpdated; final int id; final int rulesCount; - final bool enabled; + bool enabled; Filter({ required this.url, @@ -69,3 +69,13 @@ class Filter { "enabled": enabled, }; } + +class ProcessedList { + final Filter list; + final bool successful; + + const ProcessedList({ + required this.list, + required this.successful + }); +} \ No newline at end of file diff --git a/lib/providers/filtering_provider.dart b/lib/providers/filtering_provider.dart index d416455..75cfbed 100644 --- a/lib/providers/filtering_provider.dart +++ b/lib/providers/filtering_provider.dart @@ -384,4 +384,75 @@ class FilteringProvider with ChangeNotifier { return false; } } + + Future> deleteMultipleLists({ + required List blacklists, + required List whitelists + }) async { + Future deleteList({ + required Filter list, + required bool isWhitelist, + }) async { + final result = await _serversProvider!.apiClient!.deleteFilterList( + data: { + "url": list.url, + "whitelist": isWhitelist + } + ); + if (result['result'] == 'success') { + return ProcessedList(list: list, successful: true); + } + else { + return ProcessedList(list: list, successful: false); + } + } + + final resultWhitelists = await Future.wait(whitelists.map((e) => deleteList(list: e, isWhitelist: true))); + final resultBlacklists = await Future.wait(blacklists.map((e) => deleteList(list: e, isWhitelist: false))); + + await fetchFilters(); + + return [ + ...resultWhitelists, + ...resultBlacklists, + ]; + } + + Future> enableDisableMultipleLists({ + required List blacklists, + required List whitelists + }) async { + Future enableDisableList({ + required Filter list, + required bool isWhitelist, + }) async { + final result = await _serversProvider!.apiClient!.updateFilterList( + data: { + "data": { + "enabled": !list.enabled, + "name": list.name, + "url": list.url + }, + "url": list.url, + "whitelist": isWhitelist + } + ); + if (result['result'] == 'success') { + return ProcessedList(list: list, successful: true); + } + else { + return ProcessedList(list: list, successful: false); + } + } + + final resultWhitelists = await Future.wait(whitelists.map((e) => enableDisableList(list: e, isWhitelist: true))); + final resultBlacklists = await Future.wait(blacklists.map((e) => enableDisableList(list: e, isWhitelist: false))); + + await fetchFilters(); + + return [ + ...resultWhitelists, + ...resultBlacklists, + ]; + } } \ No newline at end of file diff --git a/lib/screens/filters/selection/delete_selection_modal.dart b/lib/screens/filters/selection/delete_selection_modal.dart new file mode 100644 index 0000000..944d515 --- /dev/null +++ b/lib/screens/filters/selection/delete_selection_modal.dart @@ -0,0 +1,150 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/models/filtering.dart'; + +class DeleteSelectionModal extends StatefulWidget { + final List selectedWhitelists; + final List selectedBlacklists; + final void Function() onDelete; + + const DeleteSelectionModal({ + Key? key, + required this.selectedBlacklists, + required this.selectedWhitelists, + required this.onDelete, + }) : super(key: key); + + @override + State createState() => _DeleteSelectionModalState(); +} + +class _DeleteSelectionModalState extends State { + bool _whitelistExpanded = true; + bool _blacklistExpanded = true; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Column( + children: [ + Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.deleteSelectedLists, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: SizedBox( + width: double.maxFinite, + child: SingleChildScrollView( + child: Wrap( + children: [ + if (widget.selectedWhitelists.isNotEmpty) ExpansionPanelList( + expandedHeaderPadding: const EdgeInsets.all(0), + elevation: 0, + expansionCallback: (_, isExpanded) => setState(() => _whitelistExpanded = isExpanded), + animationDuration: const Duration(milliseconds: 250), + children: [ + ExpansionPanel( + backgroundColor: Colors.transparent, + headerBuilder: (context, isExpanded) => Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.whitelists, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + body: ListView.builder( + primary: false, + shrinkWrap: true, + itemCount: widget.selectedWhitelists.length, + itemBuilder: (context, index) => Padding( + padding: const EdgeInsets.all(4), + child: Text("• ${widget.selectedWhitelists[index].name}"), + ), + ), + isExpanded: _whitelistExpanded + ), + ], + ), + if (widget.selectedWhitelists.isNotEmpty && widget.selectedBlacklists.isNotEmpty) const Padding(padding: EdgeInsets.all(8)), + if (widget.selectedBlacklists.isNotEmpty) ExpansionPanelList( + expandedHeaderPadding: const EdgeInsets.all(0), + elevation: 0, + expansionCallback: (_, isExpanded) => setState(() => _blacklistExpanded = isExpanded), + animationDuration: const Duration(milliseconds: 250), + children: [ + ExpansionPanel( + backgroundColor: Colors.transparent, + headerBuilder: (context, isExpanded) => Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.blacklists, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + body: ListView.builder( + primary: false, + shrinkWrap: true, + itemCount: widget.selectedBlacklists.length, + itemBuilder: (context, index) => Padding( + padding: const EdgeInsets.all(4), + child: Text("• ${widget.selectedBlacklists[index].name}"), + ), + ), + isExpanded: _blacklistExpanded + ), + ], + ) + ], + ), + ), + ), + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + const SizedBox(width: 8), + TextButton( + onPressed: widget.onDelete, + child: Text(AppLocalizations.of(context)!.confirm) + ), + ], + ) + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/filters/selection/enable_disable_selection_modal.dart b/lib/screens/filters/selection/enable_disable_selection_modal.dart new file mode 100644 index 0000000..08a9b3d --- /dev/null +++ b/lib/screens/filters/selection/enable_disable_selection_modal.dart @@ -0,0 +1,193 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/models/filtering.dart'; + +class EnableDisableSelectionModal extends StatefulWidget { + final List selectedWhitelists; + final List selectedBlacklists; + final void Function() onDelete; + + const EnableDisableSelectionModal({ + Key? key, + required this.selectedBlacklists, + required this.selectedWhitelists, + required this.onDelete, + }) : super(key: key); + + @override + State createState() => _EnableDisableSelectionModalState(); +} + +class _EnableDisableSelectionModalState extends State { + bool _whitelistExpanded = true; + bool _blacklistExpanded = true; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Column( + children: [ + Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.enableDisableSelected, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: SizedBox( + width: double.maxFinite, + child: SingleChildScrollView( + child: Wrap( + children: [ + if (widget.selectedWhitelists.isNotEmpty) ExpansionPanelList( + expandedHeaderPadding: const EdgeInsets.all(0), + elevation: 0, + expansionCallback: (_, isExpanded) => setState(() => _whitelistExpanded = isExpanded), + animationDuration: const Duration(milliseconds: 250), + children: [ + ExpansionPanel( + backgroundColor: Colors.transparent, + headerBuilder: (context, isExpanded) => Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.whitelists, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + body: ListView.builder( + primary: false, + shrinkWrap: true, + itemCount: widget.selectedWhitelists.length, + itemBuilder: (context, index) => Padding( + padding: const EdgeInsets.all(4), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + "• ${widget.selectedWhitelists[index].name}", + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox(width: 8), + Text( + widget.selectedWhitelists[index].enabled == true + ? AppLocalizations.of(context)!.disable + : AppLocalizations.of(context)!.enable, + style: TextStyle( + color: widget.selectedWhitelists[index].enabled == true + ? Colors.red + : Colors.green, + fontWeight: FontWeight.w500 + ), + ) + ], + ), + ), + ), + isExpanded: _whitelistExpanded + ), + ], + ), + if (widget.selectedWhitelists.isNotEmpty && widget.selectedBlacklists.isNotEmpty) const Padding(padding: EdgeInsets.all(8)), + if (widget.selectedBlacklists.isNotEmpty) ExpansionPanelList( + expandedHeaderPadding: const EdgeInsets.all(0), + elevation: 0, + expansionCallback: (_, isExpanded) => setState(() => _blacklistExpanded = isExpanded), + animationDuration: const Duration(milliseconds: 250), + children: [ + ExpansionPanel( + backgroundColor: Colors.transparent, + headerBuilder: (context, isExpanded) => Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.blacklists, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + body: ListView.builder( + primary: false, + shrinkWrap: true, + itemCount: widget.selectedBlacklists.length, + itemBuilder: (context, index) => Padding( + padding: const EdgeInsets.all(4), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + "• ${widget.selectedBlacklists[index].name}", + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox(width: 8), + Text( + widget.selectedBlacklists[index].enabled == true + ? AppLocalizations.of(context)!.disable + : AppLocalizations.of(context)!.enable, + style: TextStyle( + color: widget.selectedBlacklists[index].enabled == true + ? Colors.red + : Colors.green, + fontWeight: FontWeight.w500 + ), + ) + ], + ), + ), + ), + isExpanded: _blacklistExpanded + ), + ], + ) + ], + ), + ), + ), + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + const SizedBox(width: 8), + TextButton( + onPressed: widget.onDelete, + child: Text(AppLocalizations.of(context)!.confirm) + ), + ], + ) + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/filters/selection/selection_lists.dart b/lib/screens/filters/selection/selection_lists.dart index 7bb2a2c..1525e24 100644 --- a/lib/screens/filters/selection/selection_lists.dart +++ b/lib/screens/filters/selection/selection_lists.dart @@ -27,20 +27,34 @@ class SelectionList extends StatelessWidget { itemCount: lists.length+1, itemBuilder: (context, index) { if (index == 0) { - return CheckboxListTile( - title: Text(AppLocalizations.of(context)!.selectAll), - value: lists.length == selectedLists.length, - onChanged: (value) { - if (value == true) { - selectAll(); - } - else { - unselectAll(); - } - }, + return Card( + margin: const EdgeInsets.all(16), + child: CheckboxListTile( + title: Text( + AppLocalizations.of(context)!.selectAll, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + value: lists.length == selectedLists.length, + onChanged: (value) { + if (value == true) { + selectAll(); + } + else { + unselectAll(); + } + }, + checkboxShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4) + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12) + ), + ), ); } - return _Tile( + return _CheckboxTile( list: lists[index-1], onSelect: onSelect, isSelected: selectedLists.contains(lists[index-1]), @@ -206,10 +220,95 @@ class _Tile extends StatelessWidget { horizontal: 16 ), selected: isSelected, - selectedTileColor: Theme.of(context).colorScheme.primaryContainer, + selectedTileColor: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.5), selectedColor: Theme.of(context).colorScheme.onSurface, onTap: () => onSelect(list), ); } } +class _CheckboxTile extends StatelessWidget { + final Filter list; + final void Function(Filter) onSelect; + final bool isSelected; + + const _CheckboxTile({ + Key? key, + required this.list, + required this.onSelect, + required this.isSelected, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + + return ListTile( + leading: Checkbox( + value: isSelected, + onChanged: (_) => onSelect(list), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4) + ), + ), + title: Text( + list.name, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + list.url, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 8), + Row( + children: [ + Icon( + list.enabled == true + ? Icons.check_rounded + : Icons.close_rounded, + size: 16, + color: list.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + const SizedBox(width: 4), + Text( + list.enabled == true + ? AppLocalizations.of(context)!.enabled + : AppLocalizations.of(context)!.disabled, + style: TextStyle( + fontSize: 12, + color: list.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ), + ) + ], + ) + ], + ), + isThreeLine: true, + contentPadding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 16 + ), + onTap: () => onSelect(list), + ); + } +} + diff --git a/lib/screens/filters/selection/selection_result_modal.dart b/lib/screens/filters/selection/selection_result_modal.dart new file mode 100644 index 0000000..3a343d3 --- /dev/null +++ b/lib/screens/filters/selection/selection_result_modal.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/models/filtering.dart'; + +enum SelectionResultMode { delete, enableDisable } + +class SelectionResultModal extends StatelessWidget { + final List results; + final void Function() onClose; + final SelectionResultMode mode; + + const SelectionResultModal({ + Key? key, + required this.results, + required this.onClose, + required this.mode, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final failedItems = results.where((r) => r.successful == false).toList(); + + return AlertDialog( + title: Column( + children: [ + Icon( + mode == SelectionResultMode.delete + ? Icons.delete_rounded + : Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + mode == SelectionResultMode.delete + ? AppLocalizations.of(context)!.deletionResult + : AppLocalizations.of(context)!.enableDisableResult, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: failedItems.isEmpty + ? Text( + mode == SelectionResultMode.delete + ? AppLocalizations.of(context)!.allSelectedListsDeletedSuccessfully + : AppLocalizations.of(context)!.selectedListsEnabledDisabledSuccessfully, + ) + : SizedBox( + width: double.maxFinite, + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16, top: 8), + child: Text( + AppLocalizations.of(context)!.failedElements, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500 + ), + ), + ), + ], + ), + ListView.builder( + primary: false, + shrinkWrap: true, + itemCount: failedItems.length, + itemBuilder: (context, index) => Padding( + padding: const EdgeInsets.all(4), + child: Text("• ${failedItems[index].list.name}"), + ), + ), + ], + ), + ), + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.pop(context); + onClose(); + }, + child: Text(AppLocalizations.of(context)!.close) + ), + ], + ) + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/filters/selection/selection_screen.dart b/lib/screens/filters/selection/selection_screen.dart index 375ae67..8ca8565 100644 --- a/lib/screens/filters/selection/selection_screen.dart +++ b/lib/screens/filters/selection/selection_screen.dart @@ -2,8 +2,12 @@ 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/filters/selection/enable_disable_selection_modal.dart'; +import 'package:adguard_home_manager/screens/filters/selection/delete_selection_modal.dart'; +import 'package:adguard_home_manager/screens/filters/selection/selection_result_modal.dart'; import 'package:adguard_home_manager/screens/filters/selection/selection_lists.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; @@ -39,7 +43,7 @@ class _SelectionScreenState extends State with TickerProviderSt vsync: this, ); _scrollController = ScrollController()..addListener(() { - setState(() => _isScrolled = _scrollController.offset > 0); + setState(() => _isScrolled = _scrollController.offset > 20); }); } @@ -71,11 +75,65 @@ class _SelectionScreenState extends State with TickerProviderSt final somethingSelected = _selectedBlacklists.isNotEmpty || _selectedWhitelists.isNotEmpty; void enableDisableSelected() { - + showDialog( + context: context, + builder: (ctx) => EnableDisableSelectionModal( + selectedWhitelists: _selectedWhitelists, + selectedBlacklists: _selectedBlacklists, + onDelete: () async { + Navigator.pop(context); + final processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.processingLists); + final result = await filteringProvider.enableDisableMultipleLists( + blacklists: _selectedBlacklists, + whitelists: _selectedWhitelists + ); + if (!mounted) return; + processModal.close(); + showDialog( + context: context, + builder: (ctx) => SelectionResultModal( + mode: SelectionResultMode.enableDisable, + results: result, + onClose: () => Navigator.pop(context), + ), + barrierDismissible: false + ); + }, + ), + barrierDismissible: false + ); } void deleteSelected() { - + showDialog( + context: context, + builder: (ctx) => DeleteSelectionModal( + selectedWhitelists: _selectedWhitelists, + selectedBlacklists: _selectedBlacklists, + onDelete: () async { + Navigator.pop(context); + final processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.deletingLists); + final result = await filteringProvider.deleteMultipleLists( + blacklists: _selectedBlacklists, + whitelists: _selectedWhitelists + ); + if (!mounted) return; + processModal.close(); + showDialog( + context: context, + builder: (ctx) => SelectionResultModal( + mode: SelectionResultMode.delete, + results: result, + onClose: () => Navigator.pop(context), + ), + barrierDismissible: false + ); + }, + ), + barrierDismissible: false + ); } if (widget.isModal == true) { @@ -107,7 +165,21 @@ class _SelectionScreenState extends State with TickerProviderSt ) ], ), - + Row( + children: [ + IconButton( + onPressed: enableDisableSelected, + icon: const Icon(Icons.shield_rounded), + tooltip: AppLocalizations.of(context)!.enableDisableSelected, + ), + const SizedBox(width: 8), + IconButton( + onPressed: deleteSelected, + icon: const Icon(Icons.delete_rounded), + tooltip: AppLocalizations.of(context)!.deleteSelectedLists, + ), + ], + ) ], ), ), @@ -141,7 +213,7 @@ class _SelectionScreenState extends State with TickerProviderSt selectedLists: _selectedWhitelists, onSelect: (list) => handleSelect(list, ListType.whitelist), selectAll: () => setState(() => _selectedWhitelists = filteringProvider.filtering!.whitelistFilters), - unselectAll: () => setState(() => []) + unselectAll: () => setState(() => _selectedWhitelists = []) ), SelectionList( lists: filteringProvider.filtering!.filters, @@ -240,7 +312,7 @@ class _SelectionScreenState extends State with TickerProviderSt Icons.shield_rounded, color: somethingSelected == true ? Theme.of(context).colorScheme.onPrimaryContainer - : Theme.of(context).colorScheme.secondary, + : Theme.of(context).colorScheme.onPrimaryContainer.withOpacity(0.5), ), ), const SizedBox(height: 16), @@ -253,7 +325,7 @@ class _SelectionScreenState extends State with TickerProviderSt Icons.delete_rounded, color: somethingSelected == true ? Theme.of(context).colorScheme.onPrimaryContainer - : Theme.of(context).colorScheme.secondary, + : Theme.of(context).colorScheme.onPrimaryContainer.withOpacity(0.5), ), ), ], diff --git a/lib/widgets/system_ui_overlay_style.dart b/lib/widgets/system_ui_overlay_style.dart index 8ceaf4b..83557f1 100644 --- a/lib/widgets/system_ui_overlay_style.dart +++ b/lib/widgets/system_ui_overlay_style.dart @@ -20,7 +20,7 @@ class OverlayStyle extends StatelessWidget { statusBarIconBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light, - systemNavigationBarColor: Theme.of(context).scaffoldBackgroundColor, + systemNavigationBarColor: Theme.of(context).colorScheme.background, systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light, From a19612575bb569c7df8239db54c1601c2fd9615d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 18 Nov 2023 23:00:00 +0100 Subject: [PATCH 377/676] Auto close context menu --- lib/screens/filters/list_options_menu.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 0dbf2ab..e2521a3 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -127,12 +127,18 @@ class ListOptionsMenu extends StatelessWidget { CustomListTile( title: AppLocalizations.of(context)!.openListUrl, icon: Icons.open_in_browser_rounded, - onTap: () => openUrl(list.url) + onTap: () { + Navigator.pop(context); // Closes the context menu + openUrl(list.url); + } ), CustomListTile( title: AppLocalizations.of(context)!.selectionMode, icon: Icons.check_rounded, - onTap: openSelectionMode + onTap: () { + Navigator.pop(context); // Closes the context menu + openSelectionMode(); + } ), ], child: Material( From 0a06ee6118d274d4843b261f727c9845227cb5ad Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 18 Nov 2023 23:06:46 +0100 Subject: [PATCH 378/676] Change location files filters screen --- lib/screens/filters/add_button.dart | 4 ++-- lib/screens/filters/{ => details}/add_list_modal.dart | 0 .../filters/{ => details}/check_host_modal.dart | 0 .../filters/{ => details}/list_details_screen.dart | 4 ++-- lib/screens/filters/filters.dart | 10 +++++----- lib/screens/filters/{ => modals}/add_custom_rule.dart | 0 .../filters/{ => modals}/blocked_services_screen.dart | 0 .../filters/{ => modals}/delete_list_modal.dart | 0 .../filters/{ => modals}/remove_custom_rule_modal.dart | 0 .../{ => modals}/update_interval_lists_modal.dart | 0 10 files changed, 9 insertions(+), 9 deletions(-) rename lib/screens/filters/{ => details}/add_list_modal.dart (100%) rename lib/screens/filters/{ => details}/check_host_modal.dart (100%) rename lib/screens/filters/{ => details}/list_details_screen.dart (98%) rename lib/screens/filters/{ => modals}/add_custom_rule.dart (100%) rename lib/screens/filters/{ => modals}/blocked_services_screen.dart (100%) rename lib/screens/filters/{ => modals}/delete_list_modal.dart (100%) rename lib/screens/filters/{ => modals}/remove_custom_rule_modal.dart (100%) rename lib/screens/filters/{ => modals}/update_interval_lists_modal.dart (100%) diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index e96bb51..fbab84c 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -6,8 +6,8 @@ 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/filters/add_custom_rule.dart'; -import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; +import 'package:adguard_home_manager/screens/filters/modals/add_custom_rule.dart'; +import 'package:adguard_home_manager/screens/filters/details/add_list_modal.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; diff --git a/lib/screens/filters/add_list_modal.dart b/lib/screens/filters/details/add_list_modal.dart similarity index 100% rename from lib/screens/filters/add_list_modal.dart rename to lib/screens/filters/details/add_list_modal.dart diff --git a/lib/screens/filters/check_host_modal.dart b/lib/screens/filters/details/check_host_modal.dart similarity index 100% rename from lib/screens/filters/check_host_modal.dart rename to lib/screens/filters/details/check_host_modal.dart diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/details/list_details_screen.dart similarity index 98% rename from lib/screens/filters/list_details_screen.dart rename to lib/screens/filters/details/list_details_screen.dart index 90fb5c7..8c8199a 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/details/list_details_screen.dart @@ -7,8 +7,8 @@ import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; -import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart'; +import 'package:adguard_home_manager/screens/filters/details/add_list_modal.dart'; +import 'package:adguard_home_manager/screens/filters/modals/delete_list_modal.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index cb5cbdb..6d811a2 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -6,13 +6,13 @@ 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/filters/check_host_modal.dart'; +import 'package:adguard_home_manager/screens/filters/details/check_host_modal.dart'; import 'package:adguard_home_manager/screens/filters/filters_tabs_view.dart'; import 'package:adguard_home_manager/screens/filters/filters_triple_column.dart'; -import 'package:adguard_home_manager/screens/filters/list_details_screen.dart'; -import 'package:adguard_home_manager/screens/filters/remove_custom_rule_modal.dart'; -import 'package:adguard_home_manager/screens/filters/blocked_services_screen.dart'; -import 'package:adguard_home_manager/screens/filters/update_interval_lists_modal.dart'; +import 'package:adguard_home_manager/screens/filters/details/list_details_screen.dart'; +import 'package:adguard_home_manager/screens/filters/modals/remove_custom_rule_modal.dart'; +import 'package:adguard_home_manager/screens/filters/modals/blocked_services_screen.dart'; +import 'package:adguard_home_manager/screens/filters/modals/update_interval_lists_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; diff --git a/lib/screens/filters/add_custom_rule.dart b/lib/screens/filters/modals/add_custom_rule.dart similarity index 100% rename from lib/screens/filters/add_custom_rule.dart rename to lib/screens/filters/modals/add_custom_rule.dart diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/modals/blocked_services_screen.dart similarity index 100% rename from lib/screens/filters/blocked_services_screen.dart rename to lib/screens/filters/modals/blocked_services_screen.dart diff --git a/lib/screens/filters/delete_list_modal.dart b/lib/screens/filters/modals/delete_list_modal.dart similarity index 100% rename from lib/screens/filters/delete_list_modal.dart rename to lib/screens/filters/modals/delete_list_modal.dart diff --git a/lib/screens/filters/remove_custom_rule_modal.dart b/lib/screens/filters/modals/remove_custom_rule_modal.dart similarity index 100% rename from lib/screens/filters/remove_custom_rule_modal.dart rename to lib/screens/filters/modals/remove_custom_rule_modal.dart diff --git a/lib/screens/filters/update_interval_lists_modal.dart b/lib/screens/filters/modals/update_interval_lists_modal.dart similarity index 100% rename from lib/screens/filters/update_interval_lists_modal.dart rename to lib/screens/filters/modals/update_interval_lists_modal.dart From 6ecc4324bb1f53cd977f7ab9f7ac08abb9b6970a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 18 Nov 2023 23:14:44 +0100 Subject: [PATCH 379/676] Removed androidOverscrollIndicator property --- lib/config/theme.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/config/theme.dart b/lib/config/theme.dart index 7391677..8a8aadf 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -15,7 +15,6 @@ ThemeData lightTheme(ColorScheme? dynamicColorScheme) => ThemeData( textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), ), - androidOverscrollIndicator: AndroidOverscrollIndicator.stretch, ); ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( @@ -34,7 +33,6 @@ ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), ), - androidOverscrollIndicator: AndroidOverscrollIndicator.stretch, ); ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( @@ -53,7 +51,6 @@ ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( iconColor: Color.fromRGBO(117, 117, 117, 1), ), brightness: Brightness.light, - androidOverscrollIndicator: AndroidOverscrollIndicator.stretch ); ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( @@ -75,5 +72,4 @@ ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( iconColor: Color.fromRGBO(187, 187, 187, 1), ), brightness: Brightness.dark, - androidOverscrollIndicator: AndroidOverscrollIndicator.stretch ); \ No newline at end of file From 0e4f4c8eff056b5aa08632d9cab5b3988954f761 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 18 Nov 2023 23:31:14 +0100 Subject: [PATCH 380/676] Updated libraries and flutter version --- README.md | 3 +- android/app/src/main/AndroidManifest.xml | 3 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 +- macos/Podfile.lock | 32 +-- pubspec.lock | 202 ++++++++++-------- pubspec.yaml | 43 ++-- 6 files changed, 150 insertions(+), 135 deletions(-) diff --git a/README.md b/README.md index 4128ac3..0a4af9d 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,7 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [flutter dotenv](https://pub.dev/packages/flutter_dotenv) - [flutter reorderable list](https://pub.dev/packages/flutter_reorderable_list) - [pie chart](https://pub.dev/packages/pie_chart) -- [go router](https://pub.dev/packages/go_router) -- [flutter hooks](https://pub.dev/packages/flutter_hooks) +- [segmented button slide](https://pub.dev/packages/segmented_button_slide)
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index dbe31f9..603fecc 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -15,7 +15,8 @@ android:label="AdGuard Home Manager" android:name="${applicationName}" android:requestLegacyExternalStorage="true" - android:icon="@mipmap/ic_launcher"> + android:icon="@mipmap/ic_launcher" + android:enableOnBackInvokedCallback="true"> = 2.7.5) - - sqlite3 (3.43.0): - - sqlite3/common (= 3.43.0) - - sqlite3/common (3.43.0) - - sqlite3/fts5 (3.43.0): + - sqlite3 (3.44.0): + - sqlite3/common (= 3.44.0) + - sqlite3/common (3.44.0) + - sqlite3/fts5 (3.44.0): - sqlite3/common - - sqlite3/perf-threadsafe (3.43.0): + - sqlite3/perf-threadsafe (3.44.0): - sqlite3/common - - sqlite3/rtree (3.43.0): + - sqlite3/rtree (3.44.0): - sqlite3/common - sqlite3_flutter_libs (0.0.1): - FlutterMacOS - - sqlite3 (~> 3.43.0) + - sqlite3 (~> 3.44.0) - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree @@ -83,12 +83,12 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - Sentry: e3203780941722a1fcfee99e351de14244c7f806 - sentry_flutter: 8f0ffd53088e6a4d50c095852c5cad9e4405025c - SentryPrivate: 5e3683390f66611fc7c6215e27645873adb55d13 + Sentry: 6f5742b4c47c17c9adcf265f6f328cf4a0ed1923 + sentry_flutter: 2c309a1d4b45e59d02cfa15795705687f1e2081b + SentryPrivate: b2f7996f37781080f04a946eb4e377ff63c64195 sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea - sqlite3: 7afcf055d3700254769a4dcba56f27d26b5515c9 - sqlite3_flutter_libs: 03613b0558ba0bb5544aa3ba3d0862c09c7a19b3 + sqlite3: 6e2d4a4879854d0ec86b476bf3c3e30870bac273 + sqlite3_flutter_libs: 5b7e226d522d67be60d7ade93f5aa11ebc0cd796 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 diff --git a/pubspec.lock b/pubspec.lock index 0741c5f..b32374c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: archive - sha256: "49b1fad315e57ab0bbc15bcbb874e83116a1d78f77ebd500a4af6c9407d6b28e" + sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b" url: "https://pub.dev" source: hosted - version: "3.3.8" + version: "3.4.9" args: dependency: transitive description: @@ -85,10 +85,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" contextmenu: dependency: "direct main" description: @@ -133,10 +133,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "86add5ef97215562d2e090535b0a16f197902b10c369c558a100e74ea06e8659" + sha256: "7035152271ff67b072a211152846e9f1259cf1be41e34cd3e0b5463d2d6b8419" url: "https://pub.dev" source: hosted - version: "9.0.3" + version: "9.1.0" device_info_plus_platform_interface: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: de4798a7069121aee12d5895315680258415de9b00e717723a1bd73d58f0126d + sha256: "8b8bd1d798bd393e11eddeaa8ae95b12ff028bf7d5998fc5d003488cd5f4ce2f" url: "https://pub.dev" source: hosted - version: "1.6.6" + version: "1.6.8" equatable: dependency: transitive description: @@ -197,10 +197,10 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: "48a1b69be9544e2b03d9a8e843affd89e43f3194c9248776222efcb4206bb1ec" + sha256: "6b9eb2b3017241d05c482c01f668dd05cc909ec9a0114fdd49acd958ff2432fa" url: "https://pub.dev" source: hosted - version: "0.62.0" + version: "0.64.0" flutter: dependency: "direct main" description: flutter @@ -222,14 +222,6 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.0" - flutter_hooks: - dependency: "direct main" - description: - name: flutter_hooks - sha256: "7c8db779c2d1010aa7f9ea3fbefe8f86524fcb87b69e8b0af31e1a4b55422dec" - url: "https://pub.dev" - source: hosted - version: "0.20.3" flutter_html: dependency: "direct main" description: @@ -250,10 +242,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "3.0.1" flutter_localizations: dependency: "direct main" description: flutter @@ -263,18 +255,18 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: d4a1cb250c4e059586af0235f32e02882860a508e189b61f2b31b8810c1e1330 + sha256: "35108526a233cc0755664d445f8a6b4b61e6f8fe993b3658b80b4a26827fc196" url: "https://pub.dev" source: hosted - version: "0.6.17+2" + version: "0.6.18+2" flutter_native_splash: dependency: "direct dev" description: name: flutter_native_splash - sha256: ecff62b3b893f2f665de7e4ad3de89f738941fcfcaaba8ee601e749efafa4698 + sha256: d93394f22f73e810bda59e11ebe83329c5511d6460b6b7509c4e1f3c92d6d625 url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.5" flutter_reorderable_list: dependency: "direct main" description: @@ -296,10 +288,10 @@ packages: dependency: "direct main" description: name: flutter_svg - sha256: "6ff9fa12892ae074092de2fa6a9938fb21dbabfdaa2ff57dc697ff912fc8d4b2" + sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c url: "https://pub.dev" source: hosted - version: "1.1.6" + version: "2.0.9" flutter_test: dependency: "direct dev" description: flutter @@ -346,10 +338,10 @@ packages: dependency: transitive description: name: image - sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf + sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271" url: "https://pub.dev" source: hosted - version: "4.0.17" + version: "4.1.3" intl: dependency: "direct main" description: @@ -378,10 +370,10 @@ packages: dependency: transitive description: name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "3.0.0" list_counter: dependency: transitive description: @@ -418,10 +410,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" nested: dependency: transitive description: @@ -434,10 +426,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "6ff267fcd9d48cb61c8df74a82680e8b82e940231bb5f68356672fde0397334a" + sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017" url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "4.2.0" package_info_plus_platform_interface: dependency: transitive description: @@ -454,14 +446,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" - path_drawing: - dependency: transitive - description: - name: path_drawing - sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 - url: "https://pub.dev" - source: hosted - version: "1.0.1" path_parsing: dependency: transitive description: @@ -482,26 +466,26 @@ packages: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: eeb2d1428ee7f4170e2bd498827296a18d4e7fc462b71727d111c0ac7707cfa6 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.1" pie_chart: dependency: "direct main" description: name: pie_chart - sha256: "5dba6d0eb4718e8ed00a9079361cd8947c3f84ac5a5d76f05a27f4ec5e27589e" + sha256: "58e6a46999ac938bfa1c3e5be414d6e149f037647197dca03ba3614324c12c82" url: "https://pub.dev" source: hosted - version: "5.3.2" + version: "5.4.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.7" pointycastle: dependency: transitive description: @@ -514,10 +498,10 @@ packages: dependency: "direct main" description: name: provider - sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" url: "https://pub.dev" source: hosted - version: "6.0.5" + version: "6.1.1" segmented_button_slide: dependency: "direct main" description: @@ -530,18 +514,18 @@ packages: dependency: transitive description: name: sentry - sha256: "39c23342fc96105da449914f7774139a17a0ca8a4e70d9ad5200171f7e47d6ba" + sha256: e8040183ea1a0323999bce69786ed8429b1b89fbe5815a504d5bb7493a6464cc url: "https://pub.dev" source: hosted - version: "7.9.0" + version: "7.13.1" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: ff68ab31918690da004a42e20204242a3ad9ad57da7e2712da8487060ac9767f + sha256: "843e317e605e5860e30ae431e9b8724c54f1a8567c9ad495e04595926bf22376" url: "https://pub.dev" source: hosted - version: "7.9.0" + version: "7.13.1" sky_engine: dependency: transitive description: flutter @@ -555,6 +539,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" sqflite: dependency: "direct main" description: @@ -567,18 +559,18 @@ packages: dependency: transitive description: name: sqflite_common - sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" + sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.5.0+2" sqflite_common_ffi: dependency: "direct main" description: name: sqflite_common_ffi - sha256: "0d5cc1be2eb18400ac6701c31211d44164393aa75886093002ecdd947be04f93" + sha256: "35d2fce1e971707c227cc4775cc017d5eafe06c2654c3435ebd5c3ad6c170f5f" url: "https://pub.dev" source: hosted - version: "2.3.0+2" + version: "2.3.0+4" sqlite3: dependency: transitive description: @@ -591,18 +583,18 @@ packages: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: fb115050b0c2589afe2085a62d77f5deda4db65db20a5c65a6e0c92fda89b45e + sha256: "3e3583b77cf888a68eae2e49ee4f025f66b86623ef0d83c297c8d903daa14871" url: "https://pub.dev" source: hosted - version: "0.5.16" + version: "0.5.18" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" store_checker: dependency: "direct main" description: @@ -615,10 +607,10 @@ packages: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -647,10 +639,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" typed_data: dependency: transitive description: @@ -671,74 +663,98 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" + sha256: b1c9e98774adf8820c96fbc7ae3601231d324a7d5ebd8babe27b6dfac91357ba url: "https://pub.dev" source: hosted - version: "6.1.14" + version: "6.2.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 + sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" + sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.2.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e + sha256: "9f2d390e096fdbe1e6e6256f97851e51afc2d9c423d3432f1d6a02a8a9a8b9fd" url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.1.0" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" + sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.0" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5" + sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" url: "https://pub.dev" source: hosted - version: "2.0.20" + version: "2.2.0" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" + sha256: "7754a1ad30ee896b265f8d14078b0513a4dba28d358eabb9d5f339886f4a1adc" url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.1.0" uuid: dependency: "direct main" description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + sha256: df5a4d8f22ee4ccd77f8839ac7cb274ebc11ef9adcce8b92be14b797fe889921 url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "4.2.1" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26 + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" vector_math: dependency: transitive description: @@ -751,26 +767,26 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" win32: dependency: transitive description: name: win32 - sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa" + sha256: "7c99c0e1e2fa190b48d25c81ca5e42036d5cac81430ef249027d97b0935c553f" url: "https://pub.dev" source: hosted - version: "5.0.7" + version: "5.1.0" win32_registry: dependency: transitive description: name: win32_registry - sha256: e4506d60b7244251bc59df15656a3093501c37fb5af02105a944d73eb95be4c9 + sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" window_size: dependency: "direct main" description: @@ -784,10 +800,10 @@ packages: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: af5e77e9b83f2f4adc5d3f0a4ece1c7f45a2467b695c2540381bac793e34e556 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.4.2" yaml: dependency: transitive description: @@ -797,5 +813,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.3 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 7fcccf0..482ca92 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,26 +39,26 @@ dependencies: flutter_localizations: sdk: flutter intl: any - provider: ^6.0.3 + provider: ^6.1.1 sqflite: ^2.3.0 - package_info_plus: ^4.0.1 + package_info_plus: ^4.2.0 flutter_displaymode: ^0.6.0 - dynamic_color: ^1.6.5 - animations: ^2.0.5 - device_info_plus: ^9.0.1 - uuid: ^3.0.6 + dynamic_color: ^1.6.8 + animations: ^2.0.8 + device_info_plus: ^9.1.0 + uuid: ^4.2.1 expandable: ^5.0.1 - fl_chart: ^0.62.0 + fl_chart: ^0.64.0 flutter_web_browser: ^0.17.1 - flutter_svg: ^1.1.5 - percent_indicator: ^4.2.2 - store_checker: ^1.2.0 - flutter_markdown: ^0.6.14 - markdown: ^7.0.2 - html: ^0.15.2 - flutter_html: ^3.0.0-alpha.6 - sqlite3_flutter_libs: ^0.5.16 - sqflite_common_ffi: ^2.3.0+2 + flutter_svg: ^2.0.9 + percent_indicator: ^4.2.3 + store_checker: ^1.4.0 + flutter_markdown: ^0.6.18+2 + markdown: ^7.1.1 + html: ^0.15.4 + flutter_html: ^3.0.0-beta.2 + sqlite3_flutter_libs: ^0.5.18 + sqflite_common_ffi: ^2.3.0+4 window_size: git: url: https://github.com/google/flutter-desktop-embedding @@ -69,12 +69,11 @@ dependencies: ref: master-alt url_launcher: ^6.1.11 contextmenu: ^3.0.0 - async: ^2.10.0 - sentry_flutter: ^7.9.0 - flutter_dotenv: ^5.0.2 + async: ^2.11.0 + sentry_flutter: ^7.13.1 + flutter_dotenv: ^5.1.0 flutter_reorderable_list: ^1.3.1 - pie_chart: ^5.3.2 - flutter_hooks: ^0.20.3 + pie_chart: ^5.4.0 segmented_button_slide: ^1.0.4 dev_dependencies: @@ -86,7 +85,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.0 + flutter_lints: ^3.0.1 flutter_launcher_icons: ^0.13.1 flutter_native_splash: ^2.2.10+1 From ea8b35a0a2e585e6d7b3fdba12244b4e8e56c9d2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 19 Nov 2023 04:22:59 +0100 Subject: [PATCH 381/676] Icon changes and other improvements --- lib/screens/filters/filters_tabs_view.dart | 2 +- lib/screens/filters/list_options_menu.dart | 4 +- .../enable_disable_selection_modal.dart | 2 +- .../selection/selection_result_modal.dart | 6 +- .../filters/selection/selection_screen.dart | 72 ++++++++----------- lib/widgets/options_modal.dart | 30 ++++---- 6 files changed, 54 insertions(+), 62 deletions(-) diff --git a/lib/screens/filters/filters_tabs_view.dart b/lib/screens/filters/filters_tabs_view.dart index 63e6a4e..f6016e5 100644 --- a/lib/screens/filters/filters_tabs_view.dart +++ b/lib/screens/filters/filters_tabs_view.dart @@ -77,7 +77,7 @@ class _FiltersTabsViewState extends State with TickerProviderSt children: [ const Icon(Icons.verified_user_rounded), const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.whitelists,) + Text(AppLocalizations.of(context)!.whitelists) ], ), ), diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index e2521a3..853eb7c 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -26,11 +26,11 @@ class ListOptionsMenu extends StatelessWidget { final String listType; const ListOptionsMenu({ - Key? key, + super.key, required this.list, required this.child, required this.listType, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/filters/selection/enable_disable_selection_modal.dart b/lib/screens/filters/selection/enable_disable_selection_modal.dart index 08a9b3d..fdb809c 100644 --- a/lib/screens/filters/selection/enable_disable_selection_modal.dart +++ b/lib/screens/filters/selection/enable_disable_selection_modal.dart @@ -29,7 +29,7 @@ class _EnableDisableSelectionModalState extends State createState() => _SelectionScreenState(); @@ -168,13 +168,17 @@ class _SelectionScreenState extends State with TickerProviderSt Row( children: [ IconButton( - onPressed: enableDisableSelected, - icon: const Icon(Icons.shield_rounded), + onPressed: somethingSelected == true + ? () => enableDisableSelected() + : null, + icon: const Icon(Icons.remove_moderator_rounded), tooltip: AppLocalizations.of(context)!.enableDisableSelected, ), const SizedBox(width: 8), IconButton( - onPressed: deleteSelected, + onPressed: somethingSelected == true + ? () => deleteSelected() + : null, icon: const Icon(Icons.delete_rounded), tooltip: AppLocalizations.of(context)!.deleteSelectedLists, ), @@ -270,7 +274,24 @@ class _SelectionScreenState extends State with TickerProviderSt quantity: _selectedBlacklists.length ), ] - ) + ), + actions: [ + IconButton( + onPressed: somethingSelected == true + ? () => enableDisableSelected() + : null, + icon: const Icon(Icons.remove_moderator_rounded), + tooltip: AppLocalizations.of(context)!.enableDisableSelected, + ), + IconButton( + onPressed: somethingSelected == true + ? () => deleteSelected() + : null, + icon: const Icon(Icons.delete_rounded), + tooltip: AppLocalizations.of(context)!.deleteSelectedLists, + ), + const SizedBox(width: 8), + ], ), ) ]; @@ -296,41 +317,7 @@ class _SelectionScreenState extends State with TickerProviderSt ) ) ), - AnimatedPositioned( - duration: const Duration(milliseconds: 200), - curve: Curves.ease, - right: 16, - bottom: _isScrolled ? -150 : 16, - child: Column( - children: [ - FloatingActionButton.small( - onPressed: somethingSelected == true - ? () => enableDisableSelected() - : null, - tooltip: AppLocalizations.of(context)!.enableDisableSelected, - child: Icon( - Icons.shield_rounded, - color: somethingSelected == true - ? Theme.of(context).colorScheme.onPrimaryContainer - : Theme.of(context).colorScheme.onPrimaryContainer.withOpacity(0.5), - ), - ), - const SizedBox(height: 16), - FloatingActionButton.small( - onPressed: somethingSelected == true - ? () => deleteSelected() - : null, - tooltip: AppLocalizations.of(context)!.deleteSelected, - child: Icon( - Icons.delete_rounded, - color: somethingSelected == true - ? Theme.of(context).colorScheme.onPrimaryContainer - : Theme.of(context).colorScheme.onPrimaryContainer.withOpacity(0.5), - ), - ), - ], - ), - ) + ], ), ); @@ -344,11 +331,10 @@ class _Tab extends StatelessWidget { final int quantity; const _Tab({ - Key? key, required this.icon, required this.text, required this.quantity - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/options_modal.dart b/lib/widgets/options_modal.dart index 4128fb2..75a55a5 100644 --- a/lib/widgets/options_modal.dart +++ b/lib/widgets/options_modal.dart @@ -8,9 +8,9 @@ class OptionsModal extends StatelessWidget { final List options; const OptionsModal({ - Key? key, + super.key, required this.options, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -32,16 +32,22 @@ class OptionsModal extends StatelessWidget { ) ], ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: options.map((opt) => CustomListTileDialog( - title: opt.title, - icon: opt.icon, - onTap: () { - Navigator.pop(context); - opt.action(); - }, - )).toList() + content: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: SingleChildScrollView( + child: Wrap( + children: options.map((opt) => CustomListTileDialog( + title: opt.title, + icon: opt.icon, + onTap: () { + Navigator.pop(context); + opt.action(); + }, + )).toList() + ), + ), ), actions: [ Row( From 96d84e1565bf9f5879b4c1acc0c20b08ad394c5b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 19 Nov 2023 04:24:28 +0100 Subject: [PATCH 382/676] Removed scroll controller --- lib/screens/filters/selection/selection_screen.dart | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/screens/filters/selection/selection_screen.dart b/lib/screens/filters/selection/selection_screen.dart index ec3436f..793a077 100644 --- a/lib/screens/filters/selection/selection_screen.dart +++ b/lib/screens/filters/selection/selection_screen.dart @@ -27,9 +27,6 @@ class SelectionScreen extends StatefulWidget { class _SelectionScreenState extends State with TickerProviderStateMixin { late TabController _tabController; - late ScrollController _scrollController; - - bool _isScrolled = false; List _selectedWhitelists = []; List _selectedBlacklists = []; @@ -42,9 +39,6 @@ class _SelectionScreenState extends State with TickerProviderSt length: 2, vsync: this, ); - _scrollController = ScrollController()..addListener(() { - setState(() => _isScrolled = _scrollController.offset > 20); - }); } void handleSelect(Filter list, ListType type) { @@ -245,7 +239,6 @@ class _SelectionScreenState extends State with TickerProviderSt DefaultTabController( length: 2, child: NestedScrollView( - controller: _scrollController, headerSliverBuilder: ((context, innerBoxIsScrolled) { return [ SliverOverlapAbsorber( From f14828ae198245966aefce673afd31fc8cabe3fd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 19 Nov 2023 04:56:51 +0100 Subject: [PATCH 383/676] Fixed tabbar position --- lib/providers/clients_provider.dart | 18 +- lib/screens/filters/filters_tabs_view.dart | 5 +- .../filters/selection/selection_lists.dart | 3 +- .../filters/selection/selection_screen.dart | 1 - .../access_settings/access_settings.dart | 188 ++++++----- .../access_settings/add_client_modal.dart | 316 +++++++++--------- .../access_settings/clients_list.dart | 28 +- 7 files changed, 306 insertions(+), 253 deletions(-) diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart index 8cf79a5..a06d27c 100644 --- a/lib/providers/clients_provider.dart +++ b/lib/providers/clients_provider.dart @@ -8,6 +8,8 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +enum AccessSettingsList { allowed, disallowed, domains } + class ClientsProvider with ChangeNotifier { ServersProvider? _serversProvider; StatusProvider? _statusProvider; @@ -195,20 +197,20 @@ class ClientsProvider with ChangeNotifier { } } - Future> addClientList(String item, String type) async { + Future> addClientList(String item, AccessSettingsList type) async { Map> body = { "allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [], "disallowed_clients": clients!.clientsAllowedBlocked?.disallowedClients ?? [], "blocked_hosts": clients!.clientsAllowedBlocked?.blockedHosts ?? [], }; - if (type == 'allowed') { + if (type == AccessSettingsList.allowed) { body['allowed_clients']!.add(item); } - else if (type == 'disallowed') { + else if (type == AccessSettingsList.disallowed) { body['disallowed_clients']!.add(item); } - else if (type == 'domains') { + else if (type == AccessSettingsList.domains) { body['blocked_hosts']!.add(item); } @@ -239,20 +241,20 @@ class ClientsProvider with ChangeNotifier { } } - Future> removeClientList(String client, String type) async { + Future> removeClientList(String client, AccessSettingsList type) async { Map> body = { "allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [], "disallowed_clients": clients!.clientsAllowedBlocked?.disallowedClients ?? [], "blocked_hosts": clients!.clientsAllowedBlocked?.blockedHosts ?? [], }; - if (type == 'allowed') { + if (type == AccessSettingsList.allowed) { body['allowed_clients'] = body['allowed_clients']!.where((c) => c != client).toList(); } - else if (type == 'disallowed') { + else if (type == AccessSettingsList.disallowed) { body['disallowed_clients'] = body['disallowed_clients']!.where((c) => c != client).toList(); } - else if (type == 'domains') { + else if (type == AccessSettingsList.domains) { body['blocked_hosts'] = body['blocked_hosts']!.where((c) => c != client).toList(); } diff --git a/lib/screens/filters/filters_tabs_view.dart b/lib/screens/filters/filters_tabs_view.dart index f6016e5..bc96bc8 100644 --- a/lib/screens/filters/filters_tabs_view.dart +++ b/lib/screens/filters/filters_tabs_view.dart @@ -18,12 +18,12 @@ class FiltersTabsView extends StatefulWidget { final void Function(Filter, String) onOpenDetailsModal; const FiltersTabsView({ - Key? key, + super.key, required this.appConfigProvider, required this.actions, required this.onOpenDetailsModal, required this.onRemoveCustomRule - }) : super(key: key); + }); @override State createState() => _FiltersTabsViewState(); @@ -70,6 +70,7 @@ class _FiltersTabsViewState extends State with TickerProviderSt controller: tabController, isScrollable: true, unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabAlignment: TabAlignment.start, tabs: [ Tab( child: Row( diff --git a/lib/screens/filters/selection/selection_lists.dart b/lib/screens/filters/selection/selection_lists.dart index 1525e24..9562e74 100644 --- a/lib/screens/filters/selection/selection_lists.dart +++ b/lib/screens/filters/selection/selection_lists.dart @@ -152,11 +152,10 @@ class _Tile extends StatelessWidget { final bool isSelected; const _Tile({ - Key? key, required this.list, required this.onSelect, required this.isSelected, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/filters/selection/selection_screen.dart b/lib/screens/filters/selection/selection_screen.dart index 793a077..108544e 100644 --- a/lib/screens/filters/selection/selection_screen.dart +++ b/lib/screens/filters/selection/selection_screen.dart @@ -310,7 +310,6 @@ class _SelectionScreenState extends State with TickerProviderSt ) ) ), - ], ), ); diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index ca9cf12..d5673f7 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -11,105 +11,38 @@ import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; class AccessSettings extends StatefulWidget { - const AccessSettings({Key? key}) : super(key: key); + const AccessSettings({super.key}); @override State createState() => _AccessSettingsState(); } class _AccessSettingsState extends State with TickerProviderStateMixin { - final ScrollController scrollController = ScrollController(); - late TabController tabController; + late ScrollController _scrollController; + late TabController _tabController; @override void initState() { Provider.of(context, listen: false).fetchClients(updateLoading: true); super.initState(); - tabController = TabController( + _tabController = TabController( initialIndex: 0, length: 3, vsync: this, ); + _scrollController = ScrollController(); } @override Widget build(BuildContext context) { - final clientsProvider = Provider.of(context); - final width = MediaQuery.of(context).size.width; - Widget body() { - return TabBarView( - controller: tabController, - children: [ - ClientsList( - type: 'allowed', - scrollController: scrollController, - loadStatus: clientsProvider.loadStatus, - data: clientsProvider.loadStatus == LoadStatus.loaded - ? clientsProvider.clients!.clientsAllowedBlocked!.allowedClients : [], - ), - ClientsList( - type: 'disallowed', - scrollController: scrollController, - loadStatus: clientsProvider.loadStatus, - data: clientsProvider.loadStatus == LoadStatus.loaded - ? clientsProvider.clients!.clientsAllowedBlocked!.disallowedClients : [], - ), - ClientsList( - type: 'domains', - scrollController: scrollController, - loadStatus: clientsProvider.loadStatus, - data: clientsProvider.loadStatus == LoadStatus.loaded - ? clientsProvider.clients!.clientsAllowedBlocked!.blockedHosts : [], - ), - ] - ); - } - - PreferredSizeWidget tabBar() { - return TabBar( - controller: tabController, - isScrollable: true, - unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, - tabs: [ - Tab( - child: Row( - children: [ - const Icon(Icons.check), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.allowedClients) - ], - ), - ), - Tab( - child: Row( - children: [ - const Icon(Icons.block), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.disallowedClients) - ], - ), - ), - Tab( - child: Row( - children: [ - const Icon(Icons.link_rounded), - const SizedBox(width: 8), - Text(AppLocalizations.of(context)!.disallowedDomains) - ], - ), - ), - ] - ); - } - if (Platform.isAndroid || Platform.isIOS) { return Scaffold( body: DefaultTabController( length: 3, child: NestedScrollView( - controller: scrollController, + controller: _scrollController, headerSliverBuilder: ((context, innerBoxIsScrolled) { return [ SliverOverlapAbsorber( @@ -123,13 +56,19 @@ class _AccessSettingsState extends State with TickerProviderStat centerTitle: false, forceElevated: innerBoxIsScrolled, surfaceTintColor: isDesktop(width) ? Colors.transparent : null, - bottom: tabBar() + bottom: PreferredSize( + preferredSize: const Size(double.maxFinite, 50), + child: _Tabs(tabController: _tabController) + ) ), ), ) ]; }), - body: body() + body: _TabsView( + tabController: _tabController, + scrollController: _scrollController + ) ) ), ); @@ -139,10 +78,105 @@ class _AccessSettingsState extends State with TickerProviderStat appBar: AppBar( title: Text(AppLocalizations.of(context)!.accessSettings), centerTitle: false, - bottom: tabBar() + bottom: PreferredSize( + preferredSize: const Size(double.maxFinite, 50), + child: _Tabs(tabController: _tabController) + ) ), - body: body(), + body: _TabsView( + tabController: _tabController, + scrollController: _scrollController + ) ); } } +} + +class _Tabs extends StatelessWidget { + final TabController tabController; + + const _Tabs({ + required this.tabController, + }); + + @override + Widget build(BuildContext context) { + return TabBar( + controller: tabController, + isScrollable: true, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabAlignment: TabAlignment.start, + tabs: [ + Tab( + child: Row( + children: [ + const Icon(Icons.check), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.allowedClients) + ], + ), + ), + Tab( + child: Row( + children: [ + const Icon(Icons.block), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.disallowedClients) + ], + ), + ), + Tab( + child: Row( + children: [ + const Icon(Icons.link_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.disallowedDomains) + ], + ), + ), + ] + ); + } +} + +class _TabsView extends StatelessWidget { + final TabController tabController; + final ScrollController scrollController; + + const _TabsView({ + required this.tabController, + required this.scrollController, + }); + + @override + Widget build(BuildContext context) { + final clientsProvider = Provider.of(context); + + return TabBarView( + controller: tabController, + children: [ + ClientsList( + type: AccessSettingsList.allowed, + scrollController: scrollController, + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.clients!.clientsAllowedBlocked!.allowedClients : [], + ), + ClientsList( + type: AccessSettingsList.disallowed, + scrollController: scrollController, + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.clients!.clientsAllowedBlocked!.disallowedClients : [], + ), + ClientsList( + type: AccessSettingsList.domains, + scrollController: scrollController, + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.clients!.clientsAllowedBlocked!.blockedHosts : [], + ), + ] + ); + } } \ No newline at end of file diff --git a/lib/screens/settings/access_settings/add_client_modal.dart b/lib/screens/settings/access_settings/add_client_modal.dart index 14ba98a..014babd 100644 --- a/lib/screens/settings/access_settings/add_client_modal.dart +++ b/lib/screens/settings/access_settings/add_client_modal.dart @@ -1,162 +1,23 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -class AddClientModal extends StatefulWidget { - final String type; - final void Function(String, String) onConfirm; +import 'package:adguard_home_manager/providers/clients_provider.dart'; + +class AddClientModal extends StatelessWidget { + final AccessSettingsList type; + final void Function(String, AccessSettingsList) onConfirm; final bool dialog; const AddClientModal({ - Key? key, + super.key, required this.type, required this.onConfirm, required this.dialog, - }) : super(key: key); + }); - @override - State createState() => _AddClientModalState(); -} - -class _AddClientModalState extends State { - TextEditingController fieldController = TextEditingController(); - - bool validData = false; - - void checkValidValues() { - if (fieldController.text != '') { - setState(() => validData = true); - } - else { - setState(() => validData = false); - } - } - @override Widget build(BuildContext context) { - IconData icon() { - switch (widget.type) { - case 'allowed': - return Icons.check; - - case 'disallowed': - return Icons.block; - - case 'domains': - return Icons.link_rounded; - - default: - return Icons.check; - } - } - - String title() { - switch (widget.type) { - case 'allowed': - return AppLocalizations.of(context)!.allowClient; - - case 'disallowed': - return AppLocalizations.of(context)!.disallowClient; - - case 'domains': - return AppLocalizations.of(context)!.disallowedDomains; - - default: - return ""; - } - } - - Widget content() { - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - icon(), - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - title(), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ), - TextFormField( - controller: fieldController, - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - helperText: widget.type == 'allowed' || widget.type == 'disallowed' - ? AppLocalizations.of(context)!.addClientFieldDescription : null, - labelText: widget.type == 'allowed' || widget.type == 'disallowed' - ? AppLocalizations.of(context)!.clientIdentifier - : AppLocalizations.of(context)!.domain, - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.only(top: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ), - const SizedBox(width: 16), - TextButton( - onPressed: validData == true - ? () { - Navigator.pop(context); - widget.onConfirm(fieldController.text, widget.type); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: validData == true - ? Theme.of(context).colorScheme.primary - : Colors.grey - ), - ) - ), - ], - ), - ), - ], - ), - ); - } - - if (widget.dialog == true) { + if (dialog == true) { return Padding( padding: MediaQuery.of(context).viewInsets, child: Dialog( @@ -164,7 +25,10 @@ class _AddClientModalState extends State { constraints: const BoxConstraints( maxWidth: 400 ), - child: content() + child: _Content( + type: type, + onConfirm: onConfirm, + ) ), ), ); @@ -180,9 +44,163 @@ class _AddClientModalState extends State { topRight: Radius.circular(28) ) ), - child: content() + child: _Content( + type: type, + onConfirm: onConfirm, + ) ), ); } } +} + +class _Content extends StatefulWidget { + final AccessSettingsList type; + final void Function(String, AccessSettingsList) onConfirm; + + const _Content({ + required this.type, + required this.onConfirm, + }); + + @override + State<_Content> createState() => _ContentState(); +} + +class _ContentState extends State<_Content> { + TextEditingController fieldController = TextEditingController(); + bool validData = false; + + void checkValidValues() { + if (fieldController.text != '') { + setState(() => validData = true); + } + else { + setState(() => validData = false); + } + } + + @override + Widget build(BuildContext context) { + IconData icon() { + switch (widget.type) { + case AccessSettingsList.allowed: + return Icons.check; + + case AccessSettingsList.disallowed: + return Icons.block; + + case AccessSettingsList.domains: + return Icons.link_rounded; + + default: + return Icons.check; + } + } + + String title() { + switch (widget.type) { + case AccessSettingsList.allowed: + return AppLocalizations.of(context)!.allowClient; + + case AccessSettingsList.disallowed: + return AppLocalizations.of(context)!.disallowClient; + + case AccessSettingsList.domains: + return AppLocalizations.of(context)!.disallowedDomains; + + default: + return ""; + } + } + + return Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + icon(), + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + title(), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ), + TextFormField( + controller: fieldController, + onChanged: (_) => checkValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + helperText: widget.type == AccessSettingsList.allowed || widget.type == AccessSettingsList.disallowed + ? AppLocalizations.of(context)!.addClientFieldDescription : null, + labelText: widget.type == AccessSettingsList.allowed || widget.type == AccessSettingsList.disallowed + ? AppLocalizations.of(context)!.clientIdentifier + : AppLocalizations.of(context)!.domain, + ), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + const SizedBox(width: 16), + TextButton( + onPressed: validData == true + ? () { + Navigator.pop(context); + widget.onConfirm(fieldController.text, widget.type); + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, + style: TextStyle( + color: validData == true + ? Theme.of(context).colorScheme.primary + : Colors.grey + ), + ) + ), + ], + ), + ), + ], + ), + ); + } } \ No newline at end of file diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index fcffbef..a9b1662 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -18,18 +18,18 @@ import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; class ClientsList extends StatefulWidget { - final String type; + final AccessSettingsList type; final ScrollController scrollController; final LoadStatus loadStatus; final List data; const ClientsList({ - Key? key, + super.key, required this.type, required this.scrollController, required this.loadStatus, required this.data, - }) : super(key: key); + }); @override State createState() => _ClientsListState(); @@ -79,20 +79,20 @@ class _ClientsListState extends State { } } - void confirmRemoveItem(String client, String type) async { + void confirmRemoveItem(String client, AccessSettingsList type) async { Map> body = { "allowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.allowedClients ?? [], "disallowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.disallowedClients ?? [], "blocked_hosts": clientsProvider.clients!.clientsAllowedBlocked?.blockedHosts ?? [], }; - if (type == 'allowed') { + if (type == AccessSettingsList.allowed) { body['allowed_clients'] = body['allowed_clients']!.where((c) => c != client).toList(); } - else if (type == 'disallowed') { + else if (type == AccessSettingsList.disallowed) { body['disallowed_clients'] = body['disallowed_clients']!.where((c) => c != client).toList(); } - else if (type == 'domains') { + else if (type == AccessSettingsList.domains) { body['blocked_hosts'] = body['blocked_hosts']!.where((c) => c != client).toList(); } @@ -128,7 +128,7 @@ class _ClientsListState extends State { } } - void confirmAddItem(String item, String type) async { + void confirmAddItem(String item, AccessSettingsList type) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); @@ -163,13 +163,13 @@ class _ClientsListState extends State { String description() { switch (widget.type) { - case 'allowed': + case AccessSettingsList.allowed: return AppLocalizations.of(context)!.allowedClientsDescription; - case 'disallowed': + case AccessSettingsList.disallowed: return AppLocalizations.of(context)!.blockedClientsDescription; - case 'domains': + case AccessSettingsList.domains: return AppLocalizations.of(context)!.disallowedDomainsDescription; default: @@ -179,13 +179,13 @@ class _ClientsListState extends State { String noItems() { switch (widget.type) { - case 'allowed': + case AccessSettingsList.allowed: return AppLocalizations.of(context)!.noAllowedClients; - case 'disallowed': + case AccessSettingsList.disallowed: return AppLocalizations.of(context)!.noBlockedClients; - case 'domains': + case AccessSettingsList.domains: return AppLocalizations.of(context)!.noDisallowedDomains; default: From e161cfb59446c22b6283456ae8c1c6ab0f0e93f8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 19 Nov 2023 22:52:40 +0100 Subject: [PATCH 384/676] Changed api requests --- lib/classes/http_client.dart | 200 +++++ lib/functions/check_app_updates.dart | 12 +- lib/functions/clear_dns_cache.dart | 15 +- lib/providers/clients_provider.dart | 63 +- lib/providers/dhcp_provider.dart | 36 +- lib/providers/dns_provider.dart | 106 +-- lib/providers/filtering_provider.dart | 100 +-- lib/providers/rewrite_rules_provider.dart | 18 +- lib/providers/servers_provider.dart | 40 +- lib/providers/status_provider.dart | 96 +-- .../filters/details/check_host_modal.dart | 6 +- lib/screens/filters/filters.dart | 4 +- .../management_modal/management_modal.dart | 5 +- .../logs/configuration/logs_config_modal.dart | 94 +-- lib/screens/logs/logs_list_appbar.dart | 24 +- .../access_settings/clients_list.dart | 12 +- lib/screens/settings/dhcp/dhcp.dart | 17 +- lib/screens/settings/dhcp/dhcp_leases.dart | 6 +- lib/screens/settings/dns/bootstrap_dns.dart | 6 +- lib/screens/settings/dns/cache_config.dart | 8 +- lib/screens/settings/dns/dns.dart | 2 +- .../settings/dns/dns_server_settings.dart | 6 +- .../settings/dns/private_reverse_servers.dart | 4 +- lib/screens/settings/dns/upstream_dns.dart | 6 +- .../settings/encryption/encryption.dart | 136 ++-- .../settings/update_server/update.dart | 4 +- lib/services/api_client.dart | 764 ++++++++++++++++++ lib/services/external_requests.dart | 80 ++ lib/services/http_requests.dart | 215 ----- lib/widgets/add_server/add_server_modal.dart | 6 +- .../servers_list/servers_list_item.dart | 14 +- .../servers_list/servers_tile_item.dart | 11 +- 32 files changed, 1376 insertions(+), 740 deletions(-) create mode 100644 lib/classes/http_client.dart create mode 100644 lib/services/api_client.dart create mode 100644 lib/services/external_requests.dart diff --git a/lib/classes/http_client.dart b/lib/classes/http_client.dart new file mode 100644 index 0000000..f14b839 --- /dev/null +++ b/lib/classes/http_client.dart @@ -0,0 +1,200 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:sentry_flutter/sentry_flutter.dart'; + +import 'package:adguard_home_manager/models/server.dart'; + +enum ExceptionType { socket, timeout, handshake, unknown } + +class HttpResponse { + final bool successful; + final String? body; + final int? statusCode; + final ExceptionType? exception; + + const HttpResponse({ + required this.successful, + required this.body, + required this.statusCode, + this.exception, + }); +} + +String getConnectionString({ + required Server server, + required String urlPath, +}) { + return "${server.connectionMethod}://${server.domain}${server.port != null ? ':${server.port}' : ""}${server.path ?? ""}/control$urlPath"; +} + +class HttpRequestClient { + static Future get({ + required String urlPath, + required Server server, + int timeout = 10, + }) async{ + final String connectionString = getConnectionString(server: server, urlPath: urlPath); + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.getUrl(Uri.parse(connectionString)); + if (server.authToken != null) { + request.headers.set('Authorization', 'Basic ${server.authToken}'); + } + HttpClientResponse response = await request.close().timeout( + Duration(seconds: timeout) + ); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + return HttpResponse( + successful: response.statusCode >= 400 ? false : true, + body: reply, + statusCode: response.statusCode + ); + } on SocketException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.socket + ); + } on TimeoutException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.timeout + ); + } on HandshakeException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.handshake + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.unknown + ); + } + } + + static Future post({ + required String urlPath, + required Server server, + dynamic body, + int timeout = 10, + }) async{ + final String connectionString = getConnectionString(server: server, urlPath: urlPath); + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.postUrl(Uri.parse(connectionString)); + if (server.authToken != null) { + request.headers.set('Authorization', 'Basic ${server.authToken}'); + } + request.headers.set('content-type', 'application/json'); + request.add(utf8.encode(json.encode(body))); + HttpClientResponse response = await request.close().timeout( + Duration(seconds: timeout) + ); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + return HttpResponse( + successful: response.statusCode >= 400 ? false : true, + body: reply, + statusCode: response.statusCode + ); + } on SocketException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.socket + ); + } on TimeoutException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.timeout + ); + } on HandshakeException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.handshake + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.unknown + ); + } + } + + static Future put({ + required String urlPath, + required Server server, + dynamic body, + int timeout = 10, + }) async{ + final String connectionString = getConnectionString(server: server, urlPath: urlPath); + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.putUrl(Uri.parse(connectionString)); + if (server.authToken != null) { + request.headers.set('Authorization', 'Basic ${server.authToken}'); + } + request.headers.set('content-type', 'application/json'); + request.add(utf8.encode(json.encode(body))); + HttpClientResponse response = await request.close().timeout( + Duration(seconds: timeout) + ); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + return HttpResponse( + successful: response.statusCode >= 400 ? false : true, + body: reply, + statusCode: response.statusCode + ); + } on SocketException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.socket + ); + } on TimeoutException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.timeout + ); + } on HandshakeException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.handshake + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.unknown + ); + } + } +} \ No newline at end of file diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart index 306b2ea..7ab8352 100644 --- a/lib/functions/check_app_updates.dart +++ b/lib/functions/check_app_updates.dart @@ -3,8 +3,8 @@ import 'dart:io'; import 'package:store_checker/store_checker.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/services/external_requests.dart'; import 'package:adguard_home_manager/models/github_release.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; Future checkAppUpdates({ required String currentBuildNumber, @@ -13,16 +13,16 @@ Future checkAppUpdates({ required bool isBeta }) async { var result = isBeta - ? await getReleasesGitHub() - : await getLatestReleaseGitHub(); + ? await ExternalRequests.getReleasesGitHub() + : await ExternalRequests.getLatestReleaseGitHub(); - if (result['result'] == 'success') { + if (result.successful == true) { late GitHubRelease gitHubRelease; if (isBeta) { - gitHubRelease = (result['body'] as List).firstWhere((r) => r.prerelease == true); + gitHubRelease = (result.content as List).firstWhere((r) => r.prerelease == true); } else { - gitHubRelease = result['body'] as GitHubRelease; + gitHubRelease = result.content as GitHubRelease; } final update = gitHubUpdateExists( diff --git a/lib/functions/clear_dns_cache.dart b/lib/functions/clear_dns_cache.dart index 0ff1606..d0b44cd 100644 --- a/lib/functions/clear_dns_cache.dart +++ b/lib/functions/clear_dns_cache.dart @@ -4,27 +4,20 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/server.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -Future clearDnsCache(BuildContext context, Server server) async { +Future clearDnsCache(BuildContext context, Server server) async { final serversProvider = Provider.of(context, listen: false); final ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.clearingDnsCache); - final result = await serversProvider.apiClient!.resetDnsCache(); + final result = await serversProvider.apiClient2!.resetDnsCache(); processModal.close(); - if (result['result'] == 'success') { - return true; - } - else { - final appConfigProvider = Provider.of(context, listen: false); - appConfigProvider.addLog(result['log']); - return false; - } + return result; } \ No newline at end of file diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart index a06d27c..ae9cb28 100644 --- a/lib/providers/clients_provider.dart +++ b/lib/providers/clients_provider.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/maps_fns.dart'; @@ -105,9 +106,9 @@ class ClientsProvider with ChangeNotifier { if (updateLoading == true) { _loadStatus = LoadStatus.loading; } - final result = await _serversProvider!.apiClient!.getClients(); - if (result['result'] == 'success') { - setClientsData(result['data'], false); + final result = await _serversProvider!.apiClient2!.getClients(); + if (result.successful == true) { + setClientsData(result.content as Clients, false); _loadStatus = LoadStatus.loaded; notifyListeners(); return true; @@ -122,9 +123,9 @@ class ClientsProvider with ChangeNotifier { } Future deleteClient(Client client) async { - final result = await _serversProvider!.apiClient!.postDeleteClient(name: client.name); + final result = await _serversProvider!.apiClient2!.postDeleteClient(name: client.name); - if (result['result'] == 'success') { + if (result.successful == true) { Clients clientsData = clients!; clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); setClientsData(clientsData, false); @@ -138,7 +139,7 @@ class ClientsProvider with ChangeNotifier { } Future editClient(Client client) async { - final result = await _serversProvider!.apiClient!.postUpdateClient( + final result = await _serversProvider!.apiClient2!.postUpdateClient( data: { 'name': client.name, 'data': serverVersionIsAhead( @@ -151,7 +152,7 @@ class ClientsProvider with ChangeNotifier { } ); - if (result['result'] == 'success') { + if (result.successful == true) { Clients clientsData = clients!; clientsData.clients = clientsData.clients.map((e) { if (e.name == client.name) { @@ -173,7 +174,7 @@ class ClientsProvider with ChangeNotifier { } Future addClient(Client client) async { - final result = await _serversProvider!.apiClient!.postAddClient( + final result = await _serversProvider!.apiClient2!.postAddClient( data: serverVersionIsAhead( currentVersion: _statusProvider!.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', @@ -183,7 +184,7 @@ class ClientsProvider with ChangeNotifier { : removePropFromMap(client.toJson(), 'safe_search') ); - if (result['result'] == 'success') { + if (result.successful == true) { Clients clientsData = clients!; clientsData.clients.add(client); setClientsData(clientsData, false); @@ -197,7 +198,7 @@ class ClientsProvider with ChangeNotifier { } } - Future> addClientList(String item, AccessSettingsList type) async { + Future addClientList(String item, AccessSettingsList type) async { Map> body = { "allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [], "disallowed_clients": clients!.clientsAllowedBlocked?.disallowedClients ?? [], @@ -214,34 +215,30 @@ class ClientsProvider with ChangeNotifier { body['blocked_hosts']!.add(item); } - final result = await _serversProvider!.apiClient!.requestAllowedBlockedClientsHosts(body); + final result = await _serversProvider!.apiClient2!.requestAllowedBlockedClientsHosts( + body: body + ); - if (result['result'] == 'success') { + if (result.successful == true) { _clients?.clientsAllowedBlocked = ClientsAllowedBlocked( allowedClients: body['allowed_clients'] ?? [], disallowedClients: body['disallowed_clients'] ?? [], blockedHosts: body['blocked_hosts'] ?? [], ); notifyListeners(); - return { 'success': true }; + return result; } - else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + else if (result.successful == false && result.content == 'client_another_list') { notifyListeners(); - return { - 'success': false, - 'error': 'client_another_list' - }; + return result; } else { notifyListeners(); - return { - 'success': false, - 'error': null - }; + return result; } } - Future> removeClientList(String client, AccessSettingsList type) async { + Future removeClientList(String client, AccessSettingsList type) async { Map> body = { "allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [], "disallowed_clients": clients!.clientsAllowedBlocked?.disallowedClients ?? [], @@ -258,30 +255,26 @@ class ClientsProvider with ChangeNotifier { body['blocked_hosts'] = body['blocked_hosts']!.where((c) => c != client).toList(); } - final result = await _serversProvider!.apiClient!.requestAllowedBlockedClientsHosts(body); + final result = await _serversProvider!.apiClient2!.requestAllowedBlockedClientsHosts( + body: body + ); - if (result['result'] == 'success') { + if (result.successful == true) { _clients?.clientsAllowedBlocked = ClientsAllowedBlocked( allowedClients: body['allowed_clients'] ?? [], disallowedClients: body['disallowed_clients'] ?? [], blockedHosts: body['blocked_hosts'] ?? [], ); notifyListeners(); - return { 'success': true }; + return result; } - else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + else if (result.successful == false && result.content == 'client_another_list') { notifyListeners(); - return { - 'success': false, - 'error': 'client_another_list' - }; + return result; } else { notifyListeners(); - return { - 'success': false, - 'error': null - }; + return result; } } } \ No newline at end of file diff --git a/lib/providers/dhcp_provider.dart b/lib/providers/dhcp_provider.dart index 2c2e7d9..637f870 100644 --- a/lib/providers/dhcp_provider.dart +++ b/lib/providers/dhcp_provider.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; @@ -41,9 +42,9 @@ class DhcpProvider with ChangeNotifier { _loadStatus = LoadStatus.loading; notifyListeners(); } - final result = await _serversProvider!.apiClient!.getDhcpData(); - if (result['result'] == 'success') { - _dhcp = result['data']; + final result = await _serversProvider!.apiClient2!.getDhcpData(); + if (result.successful == true) { + _dhcp = result.content as DhcpModel; _loadStatus = LoadStatus.loaded; notifyListeners(); return true; @@ -58,7 +59,7 @@ class DhcpProvider with ChangeNotifier { } Future deleteLease(Lease lease) async { - final result = await _serversProvider!.apiClient!.deleteStaticLease( + final result = await _serversProvider!.apiClient2!.deleteStaticLease( data: { "mac": lease.mac, "ip": lease.ip, @@ -66,7 +67,7 @@ class DhcpProvider with ChangeNotifier { } ); - if (result['result'] == 'success') { + if (result.successful == true) { DhcpModel data = dhcp!; data.dhcpStatus.staticLeases = data.dhcpStatus.staticLeases.where((l) => l.mac != lease.mac).toList(); setDhcpData(data); @@ -78,8 +79,8 @@ class DhcpProvider with ChangeNotifier { } } - Future> createLease(Lease lease) async { - final result = await _serversProvider!.apiClient!.createStaticLease( + Future createLease(Lease lease) async { + final result = await _serversProvider!.apiClient2!.createStaticLease( data: { "mac": lease.mac, "ip": lease.ip, @@ -87,29 +88,14 @@ class DhcpProvider with ChangeNotifier { } ); - if (result['result'] == 'success') { + if (result.successful == true) { DhcpModel data = dhcp!; data.dhcpStatus.staticLeases.add(lease); setDhcpData(data); - return { 'success': true }; - } - else if (result['result'] == 'error' && result['message'] == 'already_exists' ) { - return { - 'success': false, - 'error': 'already_exists' - }; - } - else if (result['result'] == 'error' && result['message'] == 'server_not_configured' ) { - return { - 'success': false, - 'error': 'server_not_configured' - }; + return result; } else { - return { - 'success': false, - 'error': null - }; + return result; } } } \ No newline at end of file diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index 0965725..db1767f 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; @@ -58,12 +59,12 @@ class DnsProvider with ChangeNotifier { } } - Future> savePrivateReverseServersConfig(Map value) async { - final result = await _serversProvider!.apiClient!.setDnsConfig( + Future savePrivateReverseServersConfig(Map value) async { + final result = await _serversProvider!.apiClient2!.setDnsConfig( data: value ); - if (result['result'] == 'success') { + if (result.successful == true) { DnsInfo data = dnsInfo!; if (value['local_ptr_upstreams'] != null) { data.localPtrUpstreams = value['local_ptr_upstreams']; @@ -71,107 +72,71 @@ class DnsProvider with ChangeNotifier { data.usePrivatePtrResolvers = value['use_private_ptr_resolvers']; data.resolveClients = value['resolve_clients']; setDnsInfoData(data); - return { 'success': true }; - } - else if (result['log'] != null && result['log'].statusCode == '400') { - return { - 'success': false, - 'error': 400 - }; + return result; } else { - return { - 'success': false, - 'error': null - }; - } + return result; + } } - Future> saveUpstreamDnsConfig(Map value) async { - final result = await _serversProvider!.apiClient!.setDnsConfig( + Future saveUpstreamDnsConfig(Map value) async { + final result = await _serversProvider!.apiClient2!.setDnsConfig( data: value ); - if (result['result'] == 'success') { + if (result.successful == true) { DnsInfo data = dnsInfo!; data.upstreamDns = List.from(value['upstream_dns']); data.upstreamMode = value['upstream_mode']; setDnsInfoData(data); - return { 'success': true }; - } - else if (result['log'] != null && result['log'].statusCode == '400') { - return { - 'success': false, - 'error': 400 - }; + return result; } else { - return { - 'success': false, - 'error': null - }; - } + return result; + } } - Future> saveBootstrapDnsConfig(Map value) async { - final result = await _serversProvider!.apiClient!.setDnsConfig( + Future saveBootstrapDnsConfig(Map value) async { + final result = await _serversProvider!.apiClient2!.setDnsConfig( data: value ); - if (result['result'] == 'success') { + if (result.successful == true) { DnsInfo data = dnsInfo!; data.bootstrapDns = List.from(value['bootstrap_dns']); setDnsInfoData(data); - return { 'success': true }; - } - else if (result['log'] != null && result['log'].statusCode == '400') { - return { - 'success': false, - 'error': 400 - }; + return result; } else { - return { - 'success': false, - 'error': null - }; - } + return result; + } } - Future> saveCacheCacheConfig(Map value) async { - final result = await _serversProvider!.apiClient!.setDnsConfig( + Future saveCacheCacheConfig(Map value) async { + final result = await _serversProvider!.apiClient2!.setDnsConfig( data: value ); - if (result['result'] == 'success') { + if (result.successful == true) { DnsInfo data = dnsInfo!; data.cacheSize = value['cache_size']; data.cacheTtlMin = value['cache_ttl_min']; data.cacheTtlMax = value['cache_ttl_max']; data.cacheOptimistic = value['cache_optimistic']; setDnsInfoData(data); - return { 'success': true }; - } - else if (result['log'] != null && result['log'].statusCode == '400') { - return { - 'success': false, - 'error': 400 - }; + return result; } else { - return { - 'success': false, - 'error': null - }; - } + return result; + } } - Future> saveDnsServerConfig(Map value) async { - final result = await _serversProvider!.apiClient!.setDnsConfig( + Future saveDnsServerConfig(Map value) async { + final result = await _serversProvider!.apiClient2!.setDnsConfig( data: value ); - if (result['result'] == 'success') { + if (result.successful == true) { DnsInfo data = dnsInfo!; data.ratelimit = value['ratelimit']; data.ednsCsEnabled = value['edns_cs_enabled']; @@ -181,19 +146,10 @@ class DnsProvider with ChangeNotifier { data.blockingIpv4 = value['blocking_ipv4']; data.blockingIpv6 = value['blocking_ipv6']; setDnsInfoData(data); - return { 'success': true }; - } - else if (result['log'] != null && result['log'].statusCode == '400') { - return { - 'success': false, - 'error': 400 - }; + return result; } else { - return { - 'success': false, - 'error': null - }; - } + return result; + } } } \ No newline at end of file diff --git a/lib/providers/filtering_provider.dart b/lib/providers/filtering_provider.dart index 75cfbed..a264429 100644 --- a/lib/providers/filtering_provider.dart +++ b/lib/providers/filtering_provider.dart @@ -88,10 +88,10 @@ class FilteringProvider with ChangeNotifier { _blockedServicesLoadStatus = LoadStatus.loading; if (showLoader == true) notifyListeners(); - final result = await _serversProvider!.apiClient!.getBlockedServices(); - if (result['result'] == 'success') { + final result = await _serversProvider!.apiClient2!.getBlockedServices(); + if (result.successful == true) { _blockedServicesLoadStatus = LoadStatus.loaded; - _blockedServicesList = BlockedServices(services: result['data']); + _blockedServicesList = BlockedServices(services: result.content as List); notifyListeners(); return true; @@ -112,9 +112,9 @@ class FilteringProvider with ChangeNotifier { _loadStatus = LoadStatus.loading; } - final result = await _serversProvider!.apiClient!.getFiltering(); - if (result['result'] == 'success') { - _filtering = result['data']; + final result = await _serversProvider!.apiClient2!.getFiltering(); + if (result.successful == true) { + _filtering = result.content as Filtering; _loadStatus = LoadStatus.loaded; notifyListeners(); return true; @@ -127,15 +127,16 @@ class FilteringProvider with ChangeNotifier { } Future> updateLists() async { - final result = await _serversProvider!.apiClient!.updateLists(); - if (result['result'] == 'success') { - final result2 = await _serversProvider!.apiClient!.getFiltering(); - if (result2['result'] == 'success') { - _filtering = result2['data']; + final result = await _serversProvider!.apiClient2!.updateLists(); + if (result.successful == true) { + final result2 = await _serversProvider!.apiClient2!.getFiltering(); + if (result2.successful == true) { + _filtering = result2.content as Filtering; notifyListeners(); + print(result.content); return { "success": true, - "data": result['data'] + "data": result.content }; } else { @@ -151,10 +152,10 @@ class FilteringProvider with ChangeNotifier { Future enableDisableFiltering() async { final newValue = !_statusProvider!.serverStatus!.filteringEnabled; - final result = await _serversProvider!.apiClient!.updateFiltering( + final result = await _serversProvider!.apiClient2!.updateFiltering( enable: newValue ); - if (result['result'] == 'success') { + if (result.successful == true) { setFilteringProtectionStatus(newValue, false); notifyListeners(); return true; @@ -166,13 +167,13 @@ class FilteringProvider with ChangeNotifier { } Future changeUpdateFrequency(int value) async { - final result = await _serversProvider!.apiClient!.requestChangeUpdateFrequency( + final result = await _serversProvider!.apiClient2!.requestChangeUpdateFrequency( data: { "enabled": filtering!.enabled, "interval": value } ); - if (result['result'] == 'success') { + if (result.successful == true) { setFiltersUpdateFrequency(value); return true; } @@ -185,9 +186,9 @@ class FilteringProvider with ChangeNotifier { Future removeCustomRule(String rule) async { final List newRules = filtering!.userRules.where((r) => r != rule).toList(); - final result = await _serversProvider!.apiClient!.setCustomRules(rules: newRules); + final result = await _serversProvider!.apiClient2!.setCustomRules(rules: newRules); - if (result['result'] == 'success') { + if (result.successful == true) { Filtering filteringData = filtering!; filteringData.userRules = newRules; _filtering = filteringData; @@ -205,18 +206,18 @@ class FilteringProvider with ChangeNotifier { required String listUrl, required String type }) async { - final result1 = await _serversProvider!.apiClient!.deleteFilterList( + final result1 = await _serversProvider!.apiClient2!.deleteFilterList( data: { "url": listUrl, "whitelist": type == 'whitelist' ? true : false } ); - if (result1['result'] == 'success') { - final result2 = await _serversProvider!.apiClient!.getFiltering(); + if (result1.successful == true) { + final result2 = await _serversProvider!.apiClient2!.getFiltering(); - if (result2['result'] == 'success') { - _filtering = result2['data']; + if (result2.successful == true) { + _filtering = result2.content as Filtering; notifyListeners(); return true; } @@ -236,7 +237,7 @@ class FilteringProvider with ChangeNotifier { required String type, required FilteringListActions action }) async { - final result1 = await _serversProvider!.apiClient!.updateFilterList( + final result1 = await _serversProvider!.apiClient2!.updateFilterList( data: { "data": { "enabled": action == FilteringListActions.disable || action == FilteringListActions.enable @@ -250,11 +251,11 @@ class FilteringProvider with ChangeNotifier { } ); - if (result1['result'] == 'success') { - final result2 = await _serversProvider!.apiClient!.getFiltering(); + if (result1.successful == true) { + final result2 = await _serversProvider!.apiClient2!.getFiltering(); - if (result2['result'] == 'success') { - _filtering = result2['data']; + if (result2.successful == true) { + _filtering = result2.content as Filtering; notifyListeners(); return true; } @@ -273,9 +274,9 @@ class FilteringProvider with ChangeNotifier { final List newRules = filtering!.userRules; newRules.add(rule); - final result = await _serversProvider!.apiClient!.setCustomRules(rules: newRules); - - if (result['result'] == 'success') { + final result = await _serversProvider!.apiClient2!.setCustomRules(rules: newRules); + + if (result.successful == true) { Filtering filteringData = filtering!; filteringData.userRules = newRules; _filtering = filteringData; @@ -287,8 +288,9 @@ class FilteringProvider with ChangeNotifier { return false; } } + Future> addList({required String name, required String url, required String type}) async { - final result1 = await _serversProvider!.apiClient!.addFilteringList( + final result1 = await _serversProvider!.apiClient2!.addFilteringList( data: { 'name': name, 'url': url, @@ -296,13 +298,13 @@ class FilteringProvider with ChangeNotifier { } ); - if (result1['result'] == 'success') { - if (result1['data'].toString().contains("OK")) { - final result2 = await _serversProvider!.apiClient!.getFiltering(); - final items = result1['data'].toString().split(' ')[1]; + if (result1.successful == true) { + if (result1.content.toString().contains("OK")) { + final result2 = await _serversProvider!.apiClient2!.getFiltering(); + final items = result1.content.toString().split(' ')[1]; - if (result2['result'] == 'success') { - _filtering = result2['data']; + if (result2.successful == true) { + _filtering = result2.content as Filtering; notifyListeners(); return { 'success': true, @@ -325,14 +327,14 @@ class FilteringProvider with ChangeNotifier { }; } } - else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains("data is HTML, not plain text")) { + else if (result1.successful == false && result1.statusCode == 400 && result1.content.toString().contains("data is HTML, not plain text")) { notifyListeners(); return { 'success': false, 'error': 'invalid_url' }; } - else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains('url already exists')) { + else if (result1.successful == false && result1.statusCode == 400 && result1.content.toString().contains('url already exists')) { notifyListeners(); return { 'success': false, @@ -355,9 +357,9 @@ class FilteringProvider with ChangeNotifier { _blockedServicesLoadStatus = LoadStatus.loading; } - final result = await _serversProvider!.apiClient!.getBlockedServices(); - if (result['result'] == 'success') { - _blockedServicesList = BlockedServices(services: result['data']); + final result = await _serversProvider!.apiClient2!.getBlockedServices(); + if (result.successful == true) { + _blockedServicesList = BlockedServices(services: result.content as List); _blockedServicesLoadStatus = LoadStatus.loaded; notifyListeners(); @@ -371,11 +373,11 @@ class FilteringProvider with ChangeNotifier { } Future updateBlockedServices(List values) async { - final result = await _serversProvider!.apiClient!.setBlockedServices( + final result = await _serversProvider!.apiClient2!.setBlockedServices( data: values ); - if (result['result'] == 'success') { + if (result.successful == true) { setBlockedServices(values); return true; } @@ -393,13 +395,13 @@ class FilteringProvider with ChangeNotifier { required Filter list, required bool isWhitelist, }) async { - final result = await _serversProvider!.apiClient!.deleteFilterList( + final result = await _serversProvider!.apiClient2!.deleteFilterList( data: { "url": list.url, "whitelist": isWhitelist } ); - if (result['result'] == 'success') { + if (result.successful == true) { return ProcessedList(list: list, successful: true); } else { @@ -426,7 +428,7 @@ class FilteringProvider with ChangeNotifier { required Filter list, required bool isWhitelist, }) async { - final result = await _serversProvider!.apiClient!.updateFilterList( + final result = await _serversProvider!.apiClient2!.updateFilterList( data: { "data": { "enabled": !list.enabled, @@ -437,7 +439,7 @@ class FilteringProvider with ChangeNotifier { "whitelist": isWhitelist } ); - if (result['result'] == 'success') { + if (result.successful == true) { return ProcessedList(list: list, successful: true); } else { diff --git a/lib/providers/rewrite_rules_provider.dart b/lib/providers/rewrite_rules_provider.dart index 1e3bda3..ec8ea1d 100644 --- a/lib/providers/rewrite_rules_provider.dart +++ b/lib/providers/rewrite_rules_provider.dart @@ -35,14 +35,14 @@ class RewriteRulesProvider with ChangeNotifier { } Future addDnsRewrite(RewriteRules rule) async { - final result = await _serversProvider!.apiClient!.addDnsRewriteRule( + final result = await _serversProvider!.apiClient2!.addDnsRewriteRule( data: { "domain": rule.domain, "answer": rule.answer } ); - if (result['result'] == 'success') { + if (result.successful == true) { List data = rewriteRules!; data.add(rule); setRewriteRulesData(data); @@ -55,7 +55,7 @@ class RewriteRulesProvider with ChangeNotifier { } Future editDnsRewrite(RewriteRules newRule, RewriteRules oldRule) async { - final result = await _serversProvider!.apiClient!.updateRewriteRule( + final result = await _serversProvider!.apiClient2!.updateRewriteRule( body: { "target": { "answer": oldRule.answer, @@ -68,7 +68,7 @@ class RewriteRulesProvider with ChangeNotifier { } ); - if (result['result'] == 'success') { + if (result.successful == true) { List data = rewriteRules!; final index = data.indexOf(oldRule); data[index] = newRule; @@ -82,14 +82,14 @@ class RewriteRulesProvider with ChangeNotifier { } Future deleteDnsRewrite(RewriteRules rule) async { - final result = await _serversProvider!.apiClient!.deleteDnsRewriteRule( + final result = await _serversProvider!.apiClient2!.deleteDnsRewriteRule( data: { "domain": rule.domain, "answer": rule.answer } ); - if (result['result'] == 'success') { + if (result.successful == true) { List data = rewriteRules!; data = data.where((item) => item.domain != rule.domain).toList(); setRewriteRulesData(data); @@ -108,10 +108,10 @@ class RewriteRulesProvider with ChangeNotifier { _loadStatus = LoadStatus.loading; } - final result = await _serversProvider!.apiClient!.getDnsRewriteRules(); + final result = await _serversProvider!.apiClient2!.getDnsRewriteRules(); - if (result['result'] == 'success') { - _rewriteRules = result['data']; + if (result.successful == true) { + _rewriteRules = result.content as List; _loadStatus = LoadStatus.loaded; notifyListeners(); return true; diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 3a0e1ad..600c46e 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -3,6 +3,8 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; +import 'package:adguard_home_manager/services/external_requests.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -16,6 +18,7 @@ class ServersProvider with ChangeNotifier { List _serversList = []; Server? _selectedServer; ApiClient? _apiClient; + ApiClientV2? _apiClient2; bool _updatingServer = false; @@ -28,6 +31,10 @@ class ServersProvider with ChangeNotifier { return _apiClient; } + ApiClientV2? get apiClient2 { + return _apiClient2; + } + List get serversList { return _serversList; } @@ -75,6 +82,11 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } + void setApiClient2(ApiClientV2 client) { + _apiClient2 = client; + notifyListeners(); + } + void setUpdatingServer(bool status) { _updatingServer = status; notifyListeners(); @@ -176,9 +188,9 @@ class ServersProvider with ChangeNotifier { final result = await client!.checkServerUpdates(); if (result['result'] == 'success') { UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); - final gitHubResult = await client.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); - if (gitHubResult['result'] == 'success') { - data.changelog = gitHubResult['body']; + final gitHubResult = await ExternalRequests.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); + if (gitHubResult.successful == true) { + data.changelog = gitHubResult.content; } setUpdateAvailableData(data); setUpdateAvailableLoadStatus(LoadStatus.loaded, true); @@ -188,9 +200,9 @@ class ServersProvider with ChangeNotifier { } } - Future initializateServer(Server server, ApiClient apiClient) async { - final serverStatus = await _apiClient!.getServerStatus(); - if (serverStatus['result'] == 'success') { + Future initializateServer(Server server, ApiClient apiClient, ApiClientV2 apiClient2) async { + final serverStatus = await _apiClient2!.getServerStatus(); + if (serverStatus.successful == true) { checkServerUpdatesAvailable( // Do not await server: server, apiClient: apiClient @@ -226,8 +238,10 @@ class ServersProvider with ChangeNotifier { if (defaultServer != null) { _selectedServer = defaultServer; final client = ApiClient(server: defaultServer); + final client2 = ApiClientV2(server: defaultServer); _apiClient = client; - initializateServer(defaultServer, client); + _apiClient2 = client2; + initializateServer(defaultServer, client, client2); } } else { @@ -244,13 +258,13 @@ class ServersProvider with ChangeNotifier { const Duration(seconds: 2), (timer) async { if (_selectedServer != null && _selectedServer == server) { - final result = await _apiClient!.checkServerUpdates(); - if (result['result'] == 'success') { - UpdateAvailableData data = UpdateAvailableData.fromJsonUpdate(result['data']); + final result = await _apiClient2!.checkServerUpdates(); + if (result.successful == true) { + UpdateAvailableData data = UpdateAvailableData.fromJsonUpdate(result.content); if (data.currentVersion == data.newVersion) { - final gitHubResult = await _apiClient!.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); - if (gitHubResult['result'] == 'success') { - data.changelog = gitHubResult['body']; + final gitHubResult = await ExternalRequests.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); + if (gitHubResult.successful == true) { + data.changelog = gitHubResult.content; } setUpdateAvailableData(data); timer.cancel(); diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 5a4ef73..38193b8 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -6,7 +6,6 @@ import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/time_server_disabled.dart'; class StatusProvider with ChangeNotifier { @@ -104,7 +103,7 @@ class StatusProvider with ChangeNotifier { } } - Future updateBlocking({ + Future updateBlocking({ required String block, required bool newStatus, int? time @@ -114,14 +113,14 @@ class StatusProvider with ChangeNotifier { _protectionsManagementProcess.add('general'); notifyListeners(); - final result = await _serversProvider!.apiClient!.updateGeneralProtection( + final result = await _serversProvider!.apiClient2!.updateGeneralProtection( enable: newStatus, time: time ); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); - if (result['result'] == 'success') { + if (result.successful == true) { _serverStatus!.generalEnabled = newStatus; if (time != null) { final deadline = generateTimeDeadline(time); @@ -135,32 +134,12 @@ class StatusProvider with ChangeNotifier { stopCountdown(); } notifyListeners(); - return null; + return true; } else { - notifyListeners(); - return result['log']; + return false; } - case 'general_legacy': - _protectionsManagementProcess.add('general'); - notifyListeners(); - - final result = await _serversProvider!.apiClient!.updateGeneralProtectionLegacy(newStatus); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); - - if (result['result'] == 'success') { - _serverStatus!.generalEnabled = newStatus; - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - case 'filtering': _protectionsManagementProcess.add('filtering'); notifyListeners(); @@ -174,72 +153,61 @@ class StatusProvider with ChangeNotifier { if (result['result'] == 'success') { _serverStatus!.filteringEnabled = newStatus; notifyListeners(); - return null; + return true; } else { - - notifyListeners(); - return result['log']; + return false; } case 'safeSearch': _protectionsManagementProcess.add('safeSearch'); notifyListeners(); - final result = serverVersionIsAhead( - currentVersion: serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? await _serversProvider!.apiClient!.updateSafeSearchSettings(body: { 'enabled': newStatus }) - : await _serversProvider!.apiClient!.updateSafeSearchLegacy(newStatus); + final result = await _serversProvider!.apiClient2!.updateSafeSearchSettings(body: { 'enabled': newStatus }); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeSearch').toList(); - if (result['result'] == 'success') { + if (result.successful == true) { _serverStatus!.safeSearchEnabled = newStatus; notifyListeners(); - return null; + return true; } else { - notifyListeners(); - return result['log']; + return false; } case 'safeBrowsing': _protectionsManagementProcess.add('safeBrowsing'); notifyListeners(); - final result = await _serversProvider!.apiClient!.updateSafeBrowsing(newStatus); + final result = await _serversProvider!.apiClient2!.updateSafeBrowsing(enable: newStatus); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeBrowsing').toList(); - if (result['result'] == 'success') { + if (result.successful == true) { _serverStatus!.safeBrowsingEnabled = newStatus; notifyListeners(); - return null; + return true; } else { - notifyListeners(); - return result['log']; + return false; } case 'parentalControl': _protectionsManagementProcess.add('parentalControl'); notifyListeners(); - final result = await _serversProvider!.apiClient!.updateParentalControl(newStatus); + final result = await _serversProvider!.apiClient2!.updateParentalControl(enable: newStatus); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'parentalControl').toList(); - if (result['result'] == 'success') { + if (result.successful == true) { _serverStatus!.parentalControlEnabled = newStatus; notifyListeners(); - return null; + return true; } else { - notifyListeners(); - return result['log']; + return false; } default: @@ -252,9 +220,9 @@ class StatusProvider with ChangeNotifier { } Future getFilteringRules() async { - final result = await _serversProvider!.apiClient!.getFilteringRules(); - if (result['result'] == 'success') { - _filteringStatus = result['data']; + final result = await _serversProvider!.apiClient2!.getFilteringRules(); + if (result.successful == true) { + _filteringStatus = result.content as FilteringStatus; notifyListeners(); return true; } @@ -270,10 +238,10 @@ class StatusProvider with ChangeNotifier { _loadStatus = LoadStatus.loading; } - final result = await _serversProvider!.apiClient!.getServerStatus(); - if (result['result'] == 'success') { + final result = await _serversProvider!.apiClient2!.getServerStatus(); + if (result.successful == true) { setServerStatusData( - data: result['data'] + data: result.content as ServerStatus ); _loadStatus = LoadStatus.loaded; notifyListeners(); @@ -292,12 +260,12 @@ class StatusProvider with ChangeNotifier { }) async { if (_serverStatus == null) return false; - final rules = await _serversProvider!.apiClient!.getFilteringRules(); + final rules = await _serversProvider!.apiClient2!.getFilteringRules(); - if (rules['result'] == 'success') { + if (rules.successful == true) { FilteringStatus oldStatus = _serverStatus!.filteringStatus; - List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); + List newRules = (rules.content as FilteringStatus).userRules.where((d) => !d.contains(domain)).toList(); if (newStatus == 'block') { newRules.add("||$domain^"); } @@ -308,9 +276,9 @@ class StatusProvider with ChangeNotifier { newObj.userRules = newRules; _filteringStatus = newObj; - final result = await _serversProvider!.apiClient!.postFilteringRules(data: {'rules': newRules}); + final result = await _serversProvider!.apiClient2!.postFilteringRules(data: {'rules': newRules}); - if (result['result'] == 'success') { + if (result.successful == true) { return true; } else { @@ -324,11 +292,11 @@ class StatusProvider with ChangeNotifier { } Future updateSafeSearchConfig(Map status) async { - final result = await _serversProvider!.apiClient!.updateSafeSearchSettings( + final result = await _serversProvider!.apiClient2!.updateSafeSearchSettings( body: status ); - if (result['result'] == 'success') { + if (result.successful == true) { ServerStatus data = serverStatus!; data.safeSearchEnabled = status['enabled'] ?? false; data.safeSeachBing = status['bing'] ?? false; diff --git a/lib/screens/filters/details/check_host_modal.dart b/lib/screens/filters/details/check_host_modal.dart index 90e93ab..5325ada 100644 --- a/lib/screens/filters/details/check_host_modal.dart +++ b/lib/screens/filters/details/check_host_modal.dart @@ -58,11 +58,11 @@ class _CheckHostModalState extends State { void checkHost() async { setState(() => resultWidget = checking()); - final result = await serversProvider.apiClient!.checkHostFiltered(host: domainController.text); + final result = await serversProvider.apiClient2!.checkHostFiltered(host: domainController.text); if (mounted) { - if (result['result'] == 'success') { - final status = getFilteredStatus(context, appConfigProvider, result['data']['reason'], true); + if (result.successful == true) { + final status = getFilteredStatus(context, appConfigProvider, result.content['reason'], true); if (mounted) { setState(() => resultWidget = Row( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 6d811a2..7953b81 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -53,11 +53,9 @@ class _FiltersState extends State { void updateLists() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingLists); - final result = await filteringProvider.updateLists(); - + if (!mounted) return; processModal.close(); - if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/home/management_modal/management_modal.dart b/lib/screens/home/management_modal/management_modal.dart index 8fa968c..5096a9d 100644 --- a/lib/screens/home/management_modal/management_modal.dart +++ b/lib/screens/home/management_modal/management_modal.dart @@ -81,10 +81,7 @@ class _ManagementModalState extends State with SingleTickerProv newStatus: value, time: time ); - if (mounted && result != null) { - if (result != false) { - appConfigProvider.addLog(result); - } + if (mounted && result == false) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.invalidUsernamePassword, diff --git a/lib/screens/logs/configuration/logs_config_modal.dart b/lib/screens/logs/configuration/logs_config_modal.dart index 8db61ba..fb260b9 100644 --- a/lib/screens/logs/configuration/logs_config_modal.dart +++ b/lib/screens/logs/configuration/logs_config_modal.dart @@ -7,8 +7,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/configuration/config_widgets.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class RetentionItem { @@ -21,62 +19,27 @@ class RetentionItem { }); } -class LogsConfigModal extends StatelessWidget { - final void Function(Map) onConfirm; - final void Function() onClear; - final bool dialog; - final String serverVersion; - - const LogsConfigModal({ - Key? key, - required this.onConfirm, - required this.onClear, - required this.dialog, - required this.serverVersion - }) : super(key: key); - - @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return LogsConfigModalWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - context: context, - onConfirm: onConfirm, - onClear: onClear, - dialog: dialog, - serverVersion: serverVersion, - ); - } -} - -class LogsConfigModalWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; +class LogsConfigModal extends StatefulWidget { final BuildContext context; final void Function(Map) onConfirm; final void Function() onClear; final bool dialog; final String serverVersion; - const LogsConfigModalWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, + const LogsConfigModal({ + super.key, required this.context, required this.onConfirm, required this.onClear, required this.dialog, required this.serverVersion - }) : super(key: key); + }); @override - State createState() => _LogsConfigModalWidgetState(); + State createState() => _LogsConfigModalState(); } -class _LogsConfigModalWidgetState extends State { +class _LogsConfigModalState extends State { bool generalSwitch = false; bool anonymizeClientIp = false; double? retentionTime; @@ -88,21 +51,15 @@ class _LogsConfigModalWidgetState extends State { void loadData() async { final serversProvider = Provider.of(context, listen: false); - final result = serverVersionIsAhead( - currentVersion: widget.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? await serversProvider.apiClient!.getQueryLogInfo() - : await serversProvider.apiClient!.getQueryLogInfoLegacy(); + final result = await serversProvider.apiClient2!.getQueryLogInfo(); if (mounted) { - if (result['result'] == 'success') { + if (result.successful == true) { setState(() { - generalSwitch = result['data']['enabled']; - anonymizeClientIp = result['data']['anonymize_client_ip']; - retentionTime = result['data']['interval'] != null - ? double.parse(result['data']['interval'].toString()) + generalSwitch = result.content['enabled']; + anonymizeClientIp = result.content['anonymize_client_ip']; + retentionTime = result.content['interval'] != null + ? double.parse(result.content['interval'].toString()) : null; loadStatus = LoadStatus.loaded; }); @@ -115,11 +72,7 @@ class _LogsConfigModalWidgetState extends State { @override void initState() { - retentionItems = serverVersionIsAhead( - currentVersion: widget.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true ? [ + retentionItems = [ RetentionItem( label: AppLocalizations.of(widget.context)!.hours6, value: 21600000 @@ -140,27 +93,6 @@ class _LogsConfigModalWidgetState extends State { label: AppLocalizations.of(widget.context)!.days90, value: 7776000000 ), - ] : [ - RetentionItem( - label: AppLocalizations.of(widget.context)!.hours6, - value: 0.25 - ), - RetentionItem( - label: AppLocalizations.of(widget.context)!.hours24, - value: 1 - ), - RetentionItem( - label: AppLocalizations.of(widget.context)!.days7, - value: 7 - ), - RetentionItem( - label: AppLocalizations.of(widget.context)!.days30, - value: 30 - ), - RetentionItem( - label: AppLocalizations.of(widget.context)!.days90, - value: 90 - ), ]; loadData(); diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 8e02aed..7b99435 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -25,10 +25,10 @@ class LogsListAppBar extends StatelessWidget { final bool showDivider; const LogsListAppBar({ - Key? key, + super.key, required this.innerBoxIsScrolled, required this.showDivider, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -43,17 +43,11 @@ class LogsListAppBar extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingSettings); - final result = serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? await serversProvider.apiClient!.updateQueryLogParameters(data: data) - : await serversProvider.apiClient!.updateQueryLogParametersLegacy(data: data); - + final result = await serversProvider.apiClient2!.updateQueryLogParameters(data: data); + processModal.close(); - if (result['result'] == 'success') { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsConfigUpdated, @@ -61,8 +55,6 @@ class LogsListAppBar extends StatelessWidget { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsConfigNotUpdated, @@ -75,11 +67,11 @@ class LogsListAppBar extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingSettings); - final result = await serversProvider.apiClient!.clearLogs(); + final result = await serversProvider.apiClient2!.clearLogs(); processModal.close(); - if (result['result'] == 'success') { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsCleared, @@ -159,6 +151,7 @@ class LogsListAppBar extends StatelessWidget { showDialog( context: context, builder: (context) => LogsConfigModal( + context: context, onConfirm: updateConfig, onClear: clearQueries, dialog: true, @@ -172,6 +165,7 @@ class LogsListAppBar extends StatelessWidget { context: context, useRootNavigator: true, builder: (context) => LogsConfigModal( + context: context, onConfirm: updateConfig, onClear: clearQueries, dialog: false, diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index a9b1662..4dedc24 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -103,14 +103,14 @@ class _ClientsListState extends State { processModal.close(); - if (result['success'] == true) { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientRemovedSuccessfully, color: Colors.green ); } - else if (result['success'] == false && result['error'] == 'client_another_list') { + else if (result.successful == false && result.content == 'client_another_list') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, @@ -120,7 +120,7 @@ class _ClientsListState extends State { else { showSnacbkar( appConfigProvider: appConfigProvider, - label: type == 'allowed' || type == 'blocked' + label: type == AccessSettingsList.allowed || type == AccessSettingsList.disallowed ? AppLocalizations.of(context)!.clientNotRemoved : AppLocalizations.of(context)!.domainNotAdded, color: Colors.red @@ -136,14 +136,14 @@ class _ClientsListState extends State { processModal.close(); - if (result['success'] == true) { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAddedSuccessfully, color: Colors.green ); } - else if (result['success'] == false && result['error'] == 'client_another_list') { + else if (result.successful == false && result.content == 'client_another_list') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, @@ -153,7 +153,7 @@ class _ClientsListState extends State { else { showSnacbkar( appConfigProvider: appConfigProvider, - label: type == 'allowed' || type == 'blocked' + label: type == AccessSettingsList.allowed || type == AccessSettingsList.disallowed ? AppLocalizations.of(context)!.clientNotRemoved : AppLocalizations.of(context)!.domainNotAdded, color: Colors.red diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index c003ea2..6440e3b 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -194,8 +194,7 @@ class _DhcpScreenState extends State { void saveSettings() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingSettings); - - final result = await serversProvider.apiClient!.saveDhcpConfig( + final result = await serversProvider.apiClient2!.saveDhcpConfig( data: { "enabled": enabled, "interface_name": selectedInterface!.name, @@ -213,10 +212,9 @@ class _DhcpScreenState extends State { } } ); - + if (!mounted) return; processModal.close(); - - if (result['result'] == 'success') { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsSaved, @@ -236,14 +234,11 @@ class _DhcpScreenState extends State { Future.delayed(const Duration(seconds: 0), () async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.restoringConfig); - - final result = await serversProvider.apiClient!.resetDhcpConfig(); - + final result = await serversProvider.apiClient2!.resetDhcpConfig(); + if (!mounted) return; processModal.close(); - - if (result['result'] == 'success') { + if (result.successful == true) { clearAll(); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.configRestored, diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index 60a5644..d6f5051 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -66,21 +66,21 @@ class DhcpLeases extends StatelessWidget { processModal.close(); - if (result['success'] == true) { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseCreated, color: Colors.green ); } - else if (result['success'] == false && result['error'] == 'already_exists' ) { + else if (result.successful == false && result.content == "already_exists") { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseExists, color: Colors.red ); } - else if (result['success'] == false && result['error'] == 'server_not_configured' ) { + else if (result.successful == false && result.content == "server_not_configured") { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverNotConfigured, diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index 291601a..a439367 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -11,7 +11,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class BootstrapDnsScreen extends StatefulWidget { - const BootstrapDnsScreen({Key? key}) : super(key: key); + const BootstrapDnsScreen({super.key}); @override State createState() => _BootstrapDnsScreenState(); @@ -79,14 +79,14 @@ class _BootstrapDnsScreenState extends State { processModal.close(); - if (result['success'] == true) { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['success'] == false && result['error'] == 400) { + else if (result.successful == false && result.statusCode == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index b092a8b..13d1836 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -16,7 +16,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class CacheConfigDnsScreen extends StatefulWidget { - const CacheConfigDnsScreen({Key? key}) : super(key: key); + const CacheConfigDnsScreen({super.key}); @override State createState() => _CacheConfigDnsScreenState(); @@ -85,14 +85,14 @@ class _CacheConfigDnsScreenState extends State { processModal.close(); - if (result['success'] == true) { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['success'] == false && result['error'] == 400) { + else if (result.successful== false && result.statusCode == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -138,7 +138,7 @@ class _CacheConfigDnsScreenState extends State { void clearCache() async { final result = await clearDnsCache(context, serversProvider.selectedServer!); - if (result == true) { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheCleared, diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 1f74669..02ec5d6 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -63,7 +63,7 @@ class _DnsSettingsState extends State { void clearCache() async { final result = await clearDnsCache(context, serversProvider.selectedServer!); - if (result == true) { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheCleared, diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index b8481a0..6602af0 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -15,7 +15,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class DnsServerSettingsScreen extends StatefulWidget { - const DnsServerSettingsScreen({Key? key}) : super(key: key); + const DnsServerSettingsScreen({super.key}); @override State createState() => _DnsServerSettingsScreenState(); @@ -118,14 +118,14 @@ class _DnsServerSettingsScreenState extends State { processModal.close(); - if (result['success'] == true) { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['success'] == false && result['error'] == 400) { + else if (result.successful == false && result.statusCode == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index 2373d44..98b1cb9 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -111,14 +111,14 @@ class _PrivateReverseDnsServersScreenState extends State createState() => _UpstreamDnsScreenState(); @@ -151,14 +151,14 @@ class _UpstreamDnsScreenState extends State { processModal.close(); - if (result['success'] == true) { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['success'] == false && result['error'] == 400) { + else if (result.successful == false && result.statusCode == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 3c4744c..fc38216 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -13,6 +13,8 @@ import 'package:adguard_home_manager/screens/settings/encryption/master_switch.d import 'package:adguard_home_manager/screens/settings/encryption/encryption_functions.dart'; import 'package:adguard_home_manager/screens/settings/encryption/error_message.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/encryption.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/base64.dart'; @@ -20,37 +22,16 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class EncryptionSettings extends StatelessWidget { - const EncryptionSettings({Key? key}) : super(key: key); +class EncryptionSettings extends StatefulWidget { + const EncryptionSettings({super.key}); + @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return EncryptionSettingsWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _EncryptionSettingsState(); } -class EncryptionSettingsWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const EncryptionSettingsWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - }) : super(key: key); - - @override - State createState() => _EncryptionSettingsWidgetState(); -} - -class _EncryptionSettingsWidgetState extends State { - int loadStatus = 0; +class _EncryptionSettingsState extends State { + LoadStatus loadStatus = LoadStatus.loading; bool enabled = false; @@ -96,54 +77,52 @@ class _EncryptionSettingsWidgetState extends State { bool formEdited = false; void fetchData({bool? showRefreshIndicator}) async { - setState(() => loadStatus = 0); + setState(() => loadStatus = LoadStatus.loading); - final result = await Provider.of(context, listen: false).apiClient!.getEncryptionSettings(); + final result = await Provider.of(context, listen: false).apiClient2!.getEncryptionSettings(); + if (!mounted) return; - if (mounted) { - if (result['result'] == 'success') { - await checkValidDataApi(data: result['data'].toJson()); + final data = result.content as EncryptionData; + + if (result.successful == true) { + await checkValidDataApi(data: data.toJson()); + if (!mounted) return; - if (mounted) { - setState(() { - enabled = result['data'].enabled; - domainNameController.text = result['data'].serverName ?? ''; - redirectHttps = result['data'].forceHttps; - httpsPortController.text = result['data'].portHttps != null ? result['data'].portHttps.toString() : ''; - tlsPortController.text = result['data'].portDnsOverTls != null ? result['data'].portDnsOverTls.toString() : ''; - dnsOverQuicPortController.text = result['data'].portDnsOverQuic != null ? result['data'].portDnsOverQuic.toString() : ''; - if (result['data'].certificateChain != '') { - certificateOption = 1; - certificateContentController.text = decodeBase64(result['data'].certificateChain); - } - else { - certificateOption = 0; - certificatePathController.text = result['data'].certificatePath; - } - if (result['data'].privateKey != '' || result['data'].privateKeySaved == true) { - privateKeyOption = 1; - } - else { - privateKeyOption = 0; - privateKeyPathController.text = result['data'].privateKeyPath; - } - usePreviouslySavedKey = result['data'].privateKeySaved; - - loadStatus = 1; - }); + setState(() { + enabled = data.enabled; + domainNameController.text = data.serverName ?? ''; + redirectHttps = data.forceHttps ?? false; + httpsPortController.text = data.portHttps != null ? data.portHttps.toString() : ''; + tlsPortController.text = data.portDnsOverTls != null ? data.portDnsOverTls.toString() : ''; + dnsOverQuicPortController.text = data.portDnsOverQuic != null ? data.portDnsOverQuic.toString() : ''; + if (data.certificateChain != '') { + certificateOption = 1; + certificateContentController.text = decodeBase64(data.certificateChain); } - } - else { - widget.appConfigProvider.addLog(result['log']); - setState(() => loadStatus = 2); - } + else { + certificateOption = 0; + certificatePathController.text = data.certificatePath; + } + if (data.privateKey != '' || data.privateKeySaved == true) { + privateKeyOption = 1; + } + else { + privateKeyOption = 0; + privateKeyPathController.text = data.privateKeyPath; + } + usePreviouslySavedKey = data.privateKeySaved; + loadStatus = LoadStatus.loaded; + }); + } + else { + setState(() => loadStatus = LoadStatus.error); } } Future checkValidDataApi({Map? data}) async { setState(() => certKeyValidApi = 0); - final result = await Provider.of(context, listen: false).apiClient!.checkEncryptionSettings( + final result = await Provider.of(context, listen: false).apiClient2!.checkEncryptionSettings( data: data ?? { "enabled": enabled, "server_name": domainNameController.text, @@ -160,23 +139,20 @@ class _EncryptionSettingsWidgetState extends State { ); if (mounted) { - if (result['result'] == 'success') { + if (result.successful == true) { setState(() { - if (result['data']['warning_validation'] != null && result['data']['warning_validation'] != '') { + if (result.content['warning_validation'] != null && result.content['warning_validation'] != '') { certKeyValidApi = 2; - validDataError = result['data']['warning_validation']; + validDataError = result.content['warning_validation']; } else { certKeyValidApi = 1; validDataError = null; } - certKeyValid = result['data']; + certKeyValid = result.content; }); } else { - if (result['log'].resBody != null) { - setState(() => validDataError = result['log'].resBody); - } setState(() => certKeyValidApi = 2); } } @@ -228,7 +204,7 @@ class _EncryptionSettingsWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await serversProvider.apiClient!.saveEncryptionSettings( + final result = await serversProvider.apiClient2!.saveEncryptionSettings( data: { "enabled": enabled, "server_name": domainNameController.text, @@ -246,7 +222,7 @@ class _EncryptionSettingsWidgetState extends State { processModal.close(); - if (result['result'] == 'success') { + if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.encryptionConfigSaved, @@ -254,19 +230,17 @@ class _EncryptionSettingsWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.encryptionConfigNotSaved, color: Colors.red ); - if (result['log'].resBody != null) { + if (result.content != null) { showDialog( context: context, builder: (context) => ErrorMessageEncryption( - errorMessage: result['log'].resBody + errorMessage: result.content ) ); } @@ -303,7 +277,7 @@ class _EncryptionSettingsWidgetState extends State { body: Builder( builder: (context) { switch (loadStatus) { - case 0: + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -324,7 +298,7 @@ class _EncryptionSettingsWidgetState extends State { ) ); - case 1: + case LoadStatus.loaded: return ListView( children: [ EncryptionMasterSwitch( @@ -641,7 +615,7 @@ class _EncryptionSettingsWidgetState extends State { ], ); - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index 3467994..f1c63a8 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -35,11 +35,11 @@ class UpdateScreen extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.requestingUpdate); - final result = await serversProvider.apiClient!.requestUpdateServer(); + final result = await serversProvider.apiClient2!.requestUpdateServer(); processModal.close(); - if (result['result'] == 'success') { + if (result.successful == true) { serversProvider.recheckPeriodServerUpdated(); showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart new file mode 100644 index 0000000..692739c --- /dev/null +++ b/lib/services/api_client.dart @@ -0,0 +1,764 @@ +import 'dart:convert'; + +import 'package:sentry_flutter/sentry_flutter.dart'; + +import 'package:adguard_home_manager/models/blocked_services.dart'; +import 'package:adguard_home_manager/models/dns_info.dart'; +import 'package:adguard_home_manager/models/encryption.dart'; +import 'package:adguard_home_manager/models/dhcp.dart'; +import 'package:adguard_home_manager/models/rewrite_rules.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/models/filtering_status.dart'; +import 'package:adguard_home_manager/models/server_info.dart'; +import 'package:adguard_home_manager/models/logs.dart'; +import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; +import 'package:adguard_home_manager/models/server.dart'; +import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/classes/http_client.dart'; + +class ApiResponse { + final bool successful; + final dynamic content; + final int? statusCode; + + const ApiResponse({ + required this.successful, + this.content, + this.statusCode, + }); +} + +class ApiClientV2 { + final Server server; + + ApiClientV2({ + required this.server + }); + + Future getServerStatus() async { + final results = await Future.wait([ + HttpRequestClient.get(urlPath: "/stats", server: server), + HttpRequestClient.get(urlPath: "/status", server: server), + HttpRequestClient.get(urlPath: "/filtering/status", server: server), + HttpRequestClient.get(urlPath: "/safesearch/status", server: server), + HttpRequestClient.get(urlPath: "/safebrowsing/status", server: server), + HttpRequestClient.get(urlPath: "/parental/status", server: server), + HttpRequestClient.get(urlPath: "/clients", server: server), + ]); + + if ( + results.map((e) => e.successful).every((e) => e == true) && + results.map((e) => e.body).every((e) => e != null) + ) { + final Map mappedData = { + 'stats': jsonDecode(results[0].body!), + 'clients': jsonDecode(results[6].body!)['clients'], + 'status': jsonDecode(results[1].body!), + 'filtering': jsonDecode(results[2].body!), + 'safeSearch': jsonDecode(results[3].body!), + 'safeBrowsingEnabled': jsonDecode(results[4].body!), + 'parentalControlEnabled': jsonDecode(results[5].body!), + }; + return ApiResponse( + successful: true, + content: ServerStatus.fromJson(mappedData) + ); + } + else { + return const ApiResponse(successful: false); + } + } + + Future updateFiltering({ + required bool enable + }) async { + final result = await HttpRequestClient.post( + urlPath: "/filtering/config", + server: server, + body: { + 'enabled': enable + } + ); + return ApiResponse( + successful: result.successful, + ); + } + + Future updateSafeBrowsing({ + required bool enable + }) async { + final result = await HttpRequestClient.post( + urlPath: enable == true + ? "/safebrowsing/enable" + : "/safebrowsing/disable", + server: server, + ); + return ApiResponse( + successful: result.successful, + ); + } + + Future updateParentalControl({ + required bool enable + }) async { + final result = await HttpRequestClient.post( + urlPath: enable == true + ? "/parental/enable" + : "/parental/disable", + server: server, + ); + return ApiResponse( + successful: result.successful, + ); + } + + Future updateGeneralProtection({ + required bool enable, + int? time, + }) async { + final result = await HttpRequestClient.post( + urlPath: "/protection", + server: server, + body: { + 'enabled': enable, + 'duration': time + } + ); + return ApiResponse( + successful: result.successful, + ); + } + + Future getClients() async { + final results = await Future.wait([ + HttpRequestClient.get(urlPath: "/clients", server: server), + HttpRequestClient.get(urlPath: "/access/list", server: server), + ]); + if ( + results.map((e) => e.successful).every((e) => e == true) && + results.map((e) => e.body).every((e) => e != null) + ) { + try { + final clients = Clients.fromJson(jsonDecode(results[0].body!)); + clients.clientsAllowedBlocked = ClientsAllowedBlocked.fromJson(jsonDecode(results[1].body!)); + return ApiResponse( + successful: true, + content: clients + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future requestAllowedBlockedClientsHosts({ + required Map?> body + }) async { + final result = await HttpRequestClient.post( + urlPath: "/access/set", + server: server, + body: body + ); + if (result.statusCode == 400) { + return const ApiResponse( + successful: false, + content: "client_another_list" + ); + } + return ApiResponse(successful: result.successful); + } + + Future getLogs({ + required int count, + int? offset, + DateTime? olderThan, + String? responseStatus, + String? search + }) async { + final result = await HttpRequestClient.get( + urlPath: '/querylog?limit=$count${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}', + server: server + ); + if (result.successful == true) { + try { + return ApiResponse( + successful: true, + content: LogsData.fromJson(jsonDecode(result.body!)) + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future getFilteringRules() async { + final result = await HttpRequestClient.get(urlPath: '/filtering/status', server: server); + if (result.successful == true) { + try { + return ApiResponse( + successful: true, + content: FilteringStatus.fromJson(jsonDecode(result.body!)) + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future postFilteringRules({ + required Map> data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/filtering/set_rules', + server: server, + body: data + ); + return ApiResponse(successful: result.successful); + } + + Future postAddClient({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/clients/add', + server: server, + body: data + ); + return ApiResponse(successful: result.successful); + } + + Future postUpdateClient({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/clients/update', + server: server, + body: data + ); + return ApiResponse(successful: result.successful); + } + + Future postDeleteClient({ + required String name, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/clients/delete', + server: server, + body: {'name': name}, + ); + return ApiResponse(successful: result.successful); + } + + Future getFiltering() async { + final results = await Future.wait([ + HttpRequestClient.get(urlPath: '/filtering/status', server: server), + HttpRequestClient.get(urlPath: '/blocked_services/list', server: server), + ]); + if (results[0].successful == true && results[0].body != null) { + try { + return ApiResponse( + successful: true, + content: Filtering.fromJson({ + ...jsonDecode(results[0].body!), + "blocked_services": results[1].body != null + ? jsonDecode(results[1].body!) + : [] + }) + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future setCustomRules({ + required List rules, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/filtering/set_rules', + server: server, + body: {'rules': rules}, + ); + return ApiResponse(successful: result.successful); + } + + Future addFilteringList({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/filtering/add_url', + server: server, + body: data, + ); + return ApiResponse( + successful: result.successful, + content: result.body, + statusCode: result.statusCode + ); + } + + Future updateFilterList({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/filtering/set_url', + server: server, + body: data, + ); + return ApiResponse(successful: result.successful); + } + + Future deleteFilterList({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/filtering/remove_url', + server: server, + body: data, + ); + return ApiResponse(successful: result.successful); + } + + Future getServerInfo() async { + final result = await HttpRequestClient.get(urlPath: "/status", server: server); + if (result.successful) { + try { + return ApiResponse( + successful: true, + content: ServerInfoData.fromJson(jsonDecode(result.body!)) + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future updateLists() async { + final results = await Future.wait([ + HttpRequestClient.post( + urlPath: '/filtering/refresh', + server: server, + body: {'whitelist': true}, + ), + HttpRequestClient.post( + urlPath: '/filtering/refresh', + server: server, + body: {'whitelist': false}, + ), + ]); + if ( + results.map((e) => e.successful).every((e) => e == true) && + results.map((e) => e.body).every((e) => e != null) + ) { + try { + final clients = Clients.fromJson(jsonDecode(results[0].body!)); + clients.clientsAllowedBlocked = ClientsAllowedBlocked.fromJson(jsonDecode(results[1].body!)); + return ApiResponse( + successful: true, + content: {'updated': jsonDecode(results[0].body!)['updated']+jsonDecode(results[1].body!)['updated']} + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future checkHostFiltered({ + required String host + }) async { + final result = await HttpRequestClient.get(urlPath: '/filtering/check_host?name=$host', server: server); + if (result.successful) { + return ApiResponse( + successful: true, + content: jsonDecode(result.body!) + ); + } + else { + return const ApiResponse(successful: false); + } + } + + Future requestChangeUpdateFrequency({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/filtering/config', + server: server, + body: data, + ); + return ApiResponse(successful: result.successful); + } + + Future setBlockedServices({ + required List data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/blocked_services/set', + server: server, + body: data, + ); + return ApiResponse(successful: result.successful); + } + + Future getDhcpData() async { + final results = await Future.wait([ + HttpRequestClient.get(urlPath: '/dhcp/interfaces', server: server), + HttpRequestClient.get(urlPath: '/dhcp/status', server: server), + ]); + if ( + results.map((e) => e.successful).every((e) => e == true) && + results.map((e) => e.body).every((e) => e != null) + ) { + try { + List interfaces = List.from(jsonDecode(results[0].body!).entries.map((entry) => NetworkInterface.fromJson(entry.value))); + return ApiResponse( + successful: true, + content: DhcpModel( + networkInterfaces: interfaces, + dhcpStatus: DhcpStatus.fromJson(jsonDecode(results[1].body!)) + ) + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future saveDhcpConfig({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/dhcp/set_config', + server: server, + body: data, + ); + return ApiResponse(successful: result.successful); + } + + Future resetDhcpConfig() async { + final result = await HttpRequestClient.post( + urlPath: '/dhcp/reset', + server: server, + body: {}, + ); + return ApiResponse(successful: result.successful); + } + + Future deleteStaticLease({ + required Map data + }) async { + final result = await HttpRequestClient.post( + urlPath: '/dhcp/remove_static_lease', + server: server, + body: data, + ); + return ApiResponse(successful: result.successful); + } + + Future createStaticLease({ + required Map data + }) async { + final result = await HttpRequestClient.post( + urlPath: '/dhcp/add_static_lease', + server: server, + body: data, + ); + if (result.statusCode == 400 && result.body != null && result.body!.contains('static lease already exists')) { + return const ApiResponse( + successful: false, + content: "already_exists", + statusCode: 400 + ); + } + if (result.statusCode == 400 && result.body != null && result.body!.contains('server is unconfigured')) { + return const ApiResponse( + successful: false, + content: "server_not_configured", + statusCode: 400 + ); + } + return ApiResponse(successful: result.successful); + } + + Future restoreAllLeases() async { + final result = await HttpRequestClient.post( + urlPath: '/dhcp/reset_leases', + server: server, + body: {}, + ); + return ApiResponse(successful: result.successful); + } + + Future getDnsRewriteRules() async { + final result = await HttpRequestClient.get(urlPath: '/rewrite/list', server: server); + if (result.successful) { + try { + final List data = List.from( + jsonDecode(result.body!).map((item) => RewriteRules.fromJson(item)) + ); + return ApiResponse( + successful: true, + content: data + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future deleteDnsRewriteRule({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/rewrite/delete', + server: server, + body: data, + ); + return ApiResponse(successful: result.successful); + } + + Future addDnsRewriteRule({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/rewrite/add', + server: server, + body: data, + ); + return ApiResponse(successful: result.successful); + } + + Future getQueryLogInfo() async { + final result = await HttpRequestClient.get(urlPath: '/querylog/config', server: server); + if (result.successful) { + return ApiResponse( + successful: true, + content: jsonDecode(result.body!) + ); + } + else { + return const ApiResponse(successful: false); + } + } + + Future updateQueryLogParameters({ + required Map data, + }) async { + final result = await HttpRequestClient.put( + urlPath: '/querylog/config/update', + server: server, + body: data, + ); + return ApiResponse(successful: result.successful); + } + + Future clearLogs() async { + final result = await HttpRequestClient.put( + urlPath: '/querylog_clear', + server: server, + body: {}, + ); + return ApiResponse(successful: result.successful); + } + + Future getDnsInfo() async { + final result = await HttpRequestClient.get(urlPath: '/dns_info', server: server); + if (result.successful) { + try { + return ApiResponse( + successful: true, + content: DnsInfo.fromJson(jsonDecode(result.body!)) + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future setDnsConfig({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/dns_config', + server: server, + body: data, + ); + if (result.statusCode == 400) { + return ApiResponse( + successful: result.successful, + content: "data_not_valid", + statusCode: result.statusCode + ); + } + return ApiResponse(successful: result.successful); + } + + Future getEncryptionSettings() async { + final result = await HttpRequestClient.get(urlPath: '/tls/status', server: server); + if (result.successful) { + try { + return ApiResponse( + successful: true, + content: EncryptionData.fromJson(jsonDecode(result.body!)) + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future getBlockedServices() async { + final result = await HttpRequestClient.get(urlPath: '/blocked_services/all', server: server); + if (result.successful) { + try { + return ApiResponse( + successful: true, + content: List.from( + BlockedServicesFromApi.fromJson(jsonDecode(result.body!)).blockedServices + ) + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future checkEncryptionSettings({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/tls/validate', + server: server, + body: data, + ); + return ApiResponse( + successful: result.successful, + content: result.body != null ? jsonDecode(result.body!) : null + ); + } + + Future saveEncryptionSettings({ + required Map data, + }) async { + final result = await HttpRequestClient.post( + urlPath: '/tls/configure', + server: server, + body: data, + ); + return ApiResponse( + successful: result.successful, + content: result.body + ); + } + + Future resetDnsCache() async { + final result = await HttpRequestClient.post( + urlPath: '/cache_clear', + server: server, + ); + return ApiResponse(successful: result.successful); + } + + Future checkServerUpdates() async { + final results = await Future.wait([ + HttpRequestClient.post(urlPath: '/version.json', server: server, body: { "recheck_now": true }), + HttpRequestClient.get(urlPath: '/status', server: server), + ]); + if ( + results.map((e) => e.successful).every((e) => e == true) && + results.map((e) => e.body).every((e) => e != null) + ) { + try { + final Map obj = { + ...jsonDecode(results[0].body!), + 'current_version': ServerInfoData.fromJson(jsonDecode(results[1].body!)).version + }; + return ApiResponse( + successful: true, + content: obj + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future requestUpdateServer() async { + final result = await HttpRequestClient.post( + urlPath: '/update', + server: server, + ); + return ApiResponse(successful: result.successful); + } + + Future updateSafeSearchSettings({ + required Map body + }) async { + final result = await HttpRequestClient.put( + urlPath: '/safesearch/settings', + server: server, + body: body + ); + return ApiResponse(successful: result.successful); + } + + Future updateRewriteRule({ + required Map body + }) async { + final result = await HttpRequestClient.put( + urlPath: '/rewrite/update', + server: server, + body: body + ); + return ApiResponse(successful: result.successful); + } +} \ No newline at end of file diff --git a/lib/services/external_requests.dart b/lib/services/external_requests.dart new file mode 100644 index 0000000..b63b6fb --- /dev/null +++ b/lib/services/external_requests.dart @@ -0,0 +1,80 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:sentry_flutter/sentry_flutter.dart'; + +import 'package:adguard_home_manager/models/github_release.dart'; +import 'package:adguard_home_manager/constants/urls.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; + +class ExternalRequests { + static Future getUpdateChangelog({ + required String releaseTag + }) async { + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.getUrl(Uri.parse("${Urls.adGuardHomeReleasesTags}/$releaseTag")); + HttpClientResponse response = await request.close(); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + if (response.statusCode == 200) { + return ApiResponse( + successful: true, + content: jsonDecode(reply)['body'], + statusCode: response.statusCode + ); + } + else { + return const ApiResponse(successful: false); + } + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + + static Future getReleasesGitHub() async { + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getReleasesGitHub)); + HttpClientResponse response = await request.close(); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + if (response.statusCode == 200) { + return ApiResponse( + successful: true, + content: List.from(jsonDecode(reply).map((entry) => GitHubRelease.fromJson(entry))) + ); + } + else { + return const ApiResponse(successful: false); + } + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } + + static Future getLatestReleaseGitHub() async { + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getLatestReleaseGitHub)); + HttpClientResponse response = await request.close(); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + if (response.statusCode == 200) { + return ApiResponse( + successful: true, + content: GitHubRelease.fromJson(jsonDecode(reply)), + statusCode: response.statusCode + ); + } + else { + return const ApiResponse(successful: false); + } + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } + } +} \ No newline at end of file diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index a2eb5ec..8063b4f 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -2165,79 +2165,6 @@ class ApiClient { } } - Future getUpdateChangelog({ - required String releaseTag - }) async { - try { - HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse("${Urls.adGuardHomeReleasesTags}/$releaseTag")); - HttpClientResponse response = await request.close(); - String reply = await response.transform(utf8.decoder).join(); - httpClient.close(); - if (response.statusCode == 200) { - return { - 'result': 'success', - 'hasResponse': true, - 'error': false, - 'statusCode': response.statusCode, - 'body': jsonDecode(reply)['body'] - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: response.statusCode.toString(), - resBody: reply, - ) - }; - } - } on SocketException { - return { - 'result': 'no_connection', - 'message': 'SocketException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'SocketException' - ) - }; - } on TimeoutException { - return { - 'result': 'no_connection', - 'message': 'TimeoutException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'TimeoutException' - ) - }; - } on HandshakeException { - return { - 'result': 'ssl_error', - 'message': 'HandshakeException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'HandshakeException' - ) - }; - } catch (e) { - return { - 'result': 'error', - 'message': e.toString(), - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: e.toString() - ) - }; - } - } - Future requestUpdateServer() async { final result = await apiRequest( urlPath: '/update', @@ -2333,146 +2260,4 @@ class ApiClient { return result; } } -} - -Future getReleasesGitHub() async { - try { - HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getReleasesGitHub)); - HttpClientResponse response = await request.close(); - String reply = await response.transform(utf8.decoder).join(); - httpClient.close(); - if (response.statusCode == 200) { - return { - 'result': 'success', - 'hasResponse': true, - 'error': false, - 'statusCode': response.statusCode, - 'body': List.from(jsonDecode(reply).map((entry) => GitHubRelease.fromJson(entry))) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: response.statusCode.toString(), - resBody: reply, - ) - }; - } - } on SocketException { - return { - 'result': 'no_connection', - 'message': 'SocketException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'SocketException' - ) - }; - } on TimeoutException { - return { - 'result': 'no_connection', - 'message': 'TimeoutException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'TimeoutException' - ) - }; - } on HandshakeException { - return { - 'result': 'ssl_error', - 'message': 'HandshakeException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'HandshakeException' - ) - }; - } catch (e) { - return { - 'result': 'error', - 'message': e.toString(), - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: e.toString() - ) - }; - } -} - -Future getLatestReleaseGitHub() async { - try { - HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getLatestReleaseGitHub)); - HttpClientResponse response = await request.close(); - String reply = await response.transform(utf8.decoder).join(); - httpClient.close(); - if (response.statusCode == 200) { - return { - 'result': 'success', - 'hasResponse': true, - 'error': false, - 'statusCode': response.statusCode, - 'body': GitHubRelease.fromJson(jsonDecode(reply)) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: response.statusCode.toString(), - resBody: reply, - ) - }; - } - } on SocketException { - return { - 'result': 'no_connection', - 'message': 'SocketException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'SocketException' - ) - }; - } on TimeoutException { - return { - 'result': 'no_connection', - 'message': 'TimeoutException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'TimeoutException' - ) - }; - } on HandshakeException { - return { - 'result': 'ssl_error', - 'message': 'HandshakeException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'HandshakeException' - ) - }; - } catch (e) { - return { - 'result': 'error', - 'message': e.toString(), - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: e.toString() - ) - }; - } } \ No newline at end of file diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index 511d367..d237939 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -12,6 +12,7 @@ import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; @@ -191,10 +192,11 @@ class _AddServerModalState extends State { statusProvider.setServerStatusLoad(LoadStatus.loading); final ApiClient apiClient = ApiClient(server: serverObj); final serverStatus = await apiClient.getServerStatus(); + final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); + final serverStatus2 = await apiClient2.getServerStatus(); // If something goes wrong when fetching server status - if (serverStatus['result'] != 'success') { - appConfigProvider.addLog(serverStatus['log']); + if (serverStatus2.successful == false) { statusProvider.setServerStatusLoad(LoadStatus.error); Navigator.pop(context); return; diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 280ae7c..492a5e8 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -8,6 +8,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; +import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -104,23 +106,21 @@ class _ServersListItemState extends State with SingleTickerProv if (result['result'] == 'success') { final ApiClient apiClient = ApiClient(server: server); serversProvider.setApiClient(apiClient); + final ApiClientV2 apiClient2 = ApiClientV2(server: server); + serversProvider.setApiClient2(apiClient2); serversProvider.setSelectedServer(server); statusProvider.setServerStatusLoad(LoadStatus.loading); - final serverStatus = await apiClient.getServerStatus(); - if (serverStatus['result'] == 'success') { + final serverStatus = await apiClient2.getServerStatus(); + if (serverStatus.successful == true) { statusProvider.setServerStatusData( - data: serverStatus['data'] + data: serverStatus.content as ServerStatus ); serversProvider.checkServerUpdatesAvailable( server: server, ); statusProvider.setServerStatusLoad(LoadStatus.loaded); } - else { - appConfigProvider.addLog(serverStatus['log']); - statusProvider.setServerStatusLoad(LoadStatus.error); - } process.close(); } diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index 8407526..0422368 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -7,6 +7,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; +import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -73,13 +75,15 @@ class _ServersTileItemState extends State with SingleTickerProv if (result['result'] == 'success') { final ApiClient apiClient = ApiClient(server: server); serversProvider.setApiClient(apiClient); + final ApiClientV2 apiClient2 = ApiClientV2(server: server); + serversProvider.setApiClient2(apiClient2); serversProvider.setSelectedServer(server); statusProvider.setServerStatusLoad(LoadStatus.loading); - final serverStatus = await apiClient.getServerStatus(); - if (serverStatus['result'] == 'success') { + final serverStatus = await apiClient2.getServerStatus(); + if (serverStatus.successful == true) { statusProvider.setServerStatusData( - data: serverStatus['data'] + data: serverStatus.content as ServerStatus ); serversProvider.checkServerUpdatesAvailable( server: server, @@ -87,7 +91,6 @@ class _ServersTileItemState extends State with SingleTickerProv statusProvider.setServerStatusLoad(LoadStatus.loaded); } else { - appConfigProvider.addLog(serverStatus['log']); statusProvider.setServerStatusLoad(LoadStatus.error); } From 6acc5105839ad8c8b0a00baa49ae6f7a6ae9a20d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 19 Nov 2023 22:53:24 +0100 Subject: [PATCH 385/676] Removed unused imports --- lib/screens/logs/logs_list_appbar.dart | 1 - lib/services/http_requests.dart | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 7b99435..d2f0ec9 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -11,7 +11,6 @@ import 'package:adguard_home_manager/screens/logs/configuration/logs_config_moda import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 8063b4f..2d001f2 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -4,12 +4,13 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:sentry_flutter/sentry_flutter.dart'; + import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/encryption.dart'; import 'package:adguard_home_manager/models/filtering.dart'; -import 'package:adguard_home_manager/models/github_release.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/models/app_log.dart'; @@ -19,8 +20,6 @@ import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/server.dart'; -import 'package:adguard_home_manager/constants/urls.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; Future> apiRequest({ From d38b895076eac0e646f7982f87dc15ccede8d5d9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 01:51:17 +0100 Subject: [PATCH 386/676] Added warning message https connections --- lib/widgets/add_server/add_server_modal.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index d237939..509ed95 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -395,6 +395,21 @@ class _AddServerModalState extends State { horizontal: 24, ), ), + if (connectionType == ConnectionType.https) Card( + margin: const EdgeInsets.only( + top: 16, left: 24, right: 24 + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + const Icon(Icons.info_rounded), + const SizedBox(width: 16), + Flexible(child: Text(AppLocalizations.of(context)!.sslWarning)) + ], + ), + ), + ), const SizedBox(height: 30), FormTextField( label: AppLocalizations.of(context)!.ipDomain, From e5528c0d2c67cf13ed8aa70bdeabb58f511be4e1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 01:51:35 +0100 Subject: [PATCH 387/676] Changed auth functions --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/services/api_client.dart | 13 ++++ lib/services/auth.dart | 82 ++++++++++++++++++++ lib/widgets/add_server/add_server_modal.dart | 69 +++++++--------- 5 files changed, 129 insertions(+), 41 deletions(-) create mode 100644 lib/services/auth.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 2fc732c..cc45a00 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -681,5 +681,6 @@ "failedElements": "Failed elements", "processingLists": "Processing lists...", "enableDisableResult": "Enable or disable result", - "selectedListsEnabledDisabledSuccessfully": "All selected lists have been enabled or disabled successfully" + "selectedListsEnabledDisabledSuccessfully": "All selected lists have been enabled or disabled successfully", + "sslWarning": "If you are using an HTTPS connection with a self signed certificate, make sure to enable \"Don't check SSL certificate\" at Settings > Advanced settings." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 6f2d8d6..9676508 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -681,5 +681,6 @@ "failedElements": "Elementos fallidos", "processingLists": "Procesando listas...", "enableDisableResult": "Resultado de activar o desactivar", - "selectedListsEnabledDisabledSuccessfully": "Todas las listas seleccionadas se han activado o desactivado correctamente." + "selectedListsEnabledDisabledSuccessfully": "Todas las listas seleccionadas se han activado o desactivado correctamente.", + "sslWarning": "Si estás usando una conexión HTTPS con un certificado autofirmado, asegúrate de activar \"No comprobar el certificado SSL\" en Ajustes > Ajustes avanzados." } \ No newline at end of file diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index 692739c..a957fc3 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -36,6 +36,19 @@ class ApiClientV2 { required this.server }); + Future getServerVersion() async { + final result = await HttpRequestClient.get(urlPath: '/status', server: server); + if (result.successful == true) { + return ApiResponse( + successful: true, + content: jsonDecode(result.body!)['version'] + ); + } + else { + return const ApiResponse(successful: false); + } + } + Future getServerStatus() async { final results = await Future.wait([ HttpRequestClient.get(urlPath: "/stats", server: server), diff --git a/lib/services/auth.dart b/lib/services/auth.dart new file mode 100644 index 0000000..a450348 --- /dev/null +++ b/lib/services/auth.dart @@ -0,0 +1,82 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:adguard_home_manager/classes/http_client.dart'; +import 'package:adguard_home_manager/models/server.dart'; + +enum AuthStatus { + success, + invalidCredentials, + manyAttepts, + serverError, + socketException, + timeoutException, + handshakeException, + unknown +} + +class ServerAuth { + static Future login(Server server) async { + try { + final body = { + "name": server.user, + "password": server.password + }; + final connectionString = "${server.connectionMethod}://${server.domain}${server.port != null ? ':${server.port}' : ""}${server.path ?? ""}/control/login"; + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.postUrl(Uri.parse(connectionString)); + request.headers.set('content-type', 'application/json'); + request.headers.contentLength = utf8.encode(jsonEncode(body)).length; + request.add(utf8.encode(json.encode(body))); + HttpClientResponse response = await request.close().timeout(const Duration(seconds: 10)); + httpClient.close(); + if (response.statusCode == 200) { + return AuthStatus.success; + } + else if (response.statusCode == 400 || response.statusCode == 401 || response.statusCode == 403) { + return AuthStatus.invalidCredentials; + } + else if (response.statusCode == 429) { + return AuthStatus.manyAttepts; + } + else if (response.statusCode == 500) { + return AuthStatus.serverError; + } + else { + return AuthStatus.unknown; + } + } on SocketException { + return AuthStatus.socketException; + } on TimeoutException { + return AuthStatus.timeoutException; + } on HandshakeException { + return AuthStatus.handshakeException; + } catch (e) { + return AuthStatus.unknown; + } + } + + static Future loginHA(Server server) async { + try { + final result = await HttpRequestClient.get(urlPath: "/status", server: server); + if (result.successful) { + return AuthStatus.success; + } + else if (result.statusCode == 401 || result.statusCode == 403) { + return AuthStatus.invalidCredentials; + } + else { + return AuthStatus.unknown; + } + } on SocketException { + return AuthStatus.socketException; + } on TimeoutException { + return AuthStatus.timeoutException; + } on HandshakeException { + return AuthStatus.handshakeException; + } catch (e) { + return AuthStatus.unknown; + } + } +} \ No newline at end of file diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index 509ed95..049bf7f 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -1,5 +1,4 @@ // ignore_for_file: use_build_context_synchronously - import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import 'package:segmented_button_slide/segmented_button_slide.dart'; @@ -11,6 +10,8 @@ import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; +import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/services/auth.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -19,7 +20,6 @@ import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/base64.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/server.dart'; @@ -32,11 +32,11 @@ class AddServerModal extends StatefulWidget { final void Function(String version) onUnsupportedVersion; const AddServerModal({ - Key? key, + super.key, this.server, required this.fullScreen, required this.onUnsupportedVersion - }) : super(key: key); + }); @override State createState() => _AddServerModalState(); @@ -119,11 +119,11 @@ class _AddServerModalState extends State { )); } - String getErrorMessage(String message) { - if (message == 'invalid_username_password') return AppLocalizations.of(context)!.invalidUsernamePassword; - if (message == 'many_attempts') return AppLocalizations.of(context)!.tooManyAttempts; - if (message == 'no_connection') return AppLocalizations.of(context)!.cantReachServer; - if (message == 'server_error') return AppLocalizations.of(context)!.serverError; + String getErrorMessage(AuthStatus status) { + if (status == AuthStatus.invalidCredentials) return AppLocalizations.of(context)!.invalidUsernamePassword; + if (status == AuthStatus.manyAttepts) return AppLocalizations.of(context)!.tooManyAttempts; + if (status == AuthStatus.socketException || status == AuthStatus.timeoutException) return AppLocalizations.of(context)!.cantReachServer; + if (status == AuthStatus.serverError) return AppLocalizations.of(context)!.serverError; return AppLocalizations.of(context)!.unknownError; } @@ -146,17 +146,16 @@ class _AddServerModalState extends State { ); final result = homeAssistant == true - ? await loginHA(serverObj) - : await login(serverObj); + ? await ServerAuth.loginHA(serverObj) + : await ServerAuth.login(serverObj); // If something goes wrong with the connection - if (result['result'] != 'success') { + if (result != AuthStatus.success) { cancelConnecting(); - appConfigProvider.addLog(result['log']); if (mounted) { showSnacbkar( appConfigProvider: appConfigProvider, - label: getErrorMessage(result['result']), + label: getErrorMessage(result), color: Colors.red ); } @@ -172,13 +171,6 @@ class _AddServerModalState extends State { // If something goes wrong when saving the connection on the db if (serverCreated != null) { if (mounted) setState(() => isConnecting = false); - appConfigProvider.addLog( - AppLog( - type: 'save_connection_db', - dateTime: DateTime.now(), - message: serverCreated.toString() - ) - ); if (mounted) { showSnacbkar( appConfigProvider: appConfigProvider, @@ -190,27 +182,27 @@ class _AddServerModalState extends State { } statusProvider.setServerStatusLoad(LoadStatus.loading); - final ApiClient apiClient = ApiClient(server: serverObj); - final serverStatus = await apiClient.getServerStatus(); final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); - final serverStatus2 = await apiClient2.getServerStatus(); + final serverStatus = await apiClient2.getServerStatus(); // If something goes wrong when fetching server status - if (serverStatus2.successful == false) { + if (serverStatus.successful == false) { statusProvider.setServerStatusLoad(LoadStatus.error); Navigator.pop(context); return; } + final status = serverStatus.content as ServerStatus; + // If everything is successful statusProvider.setServerStatusData( - data: serverStatus['data'] + data: status ); - serversProvider.setApiClient(apiClient); + serversProvider.setApiClient2(apiClient2); statusProvider.setServerStatusLoad(LoadStatus.loaded); - if (serverStatus['data'].serverVersion.contains('a') || serverStatus['data'].serverVersion.contains('b')) { + if (status.serverVersion.contains('a') || status.serverVersion.contains('b')) { Navigator.pop(context); - widget.onUnsupportedVersion(serverStatus['data'].serverVersion); + widget.onUnsupportedVersion(status.serverVersion); } else { Navigator.pop(context); @@ -236,17 +228,16 @@ class _AddServerModalState extends State { ); final result = homeAssistant == true - ? await loginHA(serverObj) - : await login(serverObj); + ? await ServerAuth.loginHA(serverObj) + : await ServerAuth.login(serverObj); // If something goes wrong with the connection - if (result['result'] != 'success') { + if (result != AuthStatus.success) { cancelConnecting(); - appConfigProvider.addLog(result['log']); if (mounted) { showSnacbkar( appConfigProvider: appConfigProvider, - label: getErrorMessage(result['result']), + label: getErrorMessage(result), color: Colors.red ); } @@ -279,14 +270,14 @@ class _AddServerModalState extends State { } // If everything is successful - final ApiClient apiClient = ApiClient(server: serverObj); - final version = await apiClient.getServerVersion(); + final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); + final version = await apiClient2.getServerVersion(); if ( - version['result'] == 'success' && - (version['data'].contains('a') || version['data'].contains('b')) // alpha or beta + version.successful == true && + (version.content.contains('a') || version.content.contains('b')) // alpha or beta ) { Navigator.pop(context); - widget.onUnsupportedVersion(version['data']); + widget.onUnsupportedVersion(version.content); } else { Navigator.pop(context); From e08404b140429aa6e335f83bb01abe3613ab0992 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 02:17:22 +0100 Subject: [PATCH 388/676] Check server version --- lib/config/minimum_server_version.dart | 4 + lib/l10n/app_en.arb | 6 +- lib/l10n/app_es.arb | 6 +- lib/widgets/add_server/add_server_modal.dart | 79 +++++++++++++++---- .../add_server/unsupported_version_modal.dart | 76 ++++++++++++++++++ 5 files changed, 152 insertions(+), 19 deletions(-) create mode 100644 lib/config/minimum_server_version.dart create mode 100644 lib/widgets/add_server/unsupported_version_modal.dart diff --git a/lib/config/minimum_server_version.dart b/lib/config/minimum_server_version.dart new file mode 100644 index 0000000..f554cb9 --- /dev/null +++ b/lib/config/minimum_server_version.dart @@ -0,0 +1,4 @@ +class MinimumServerVersion { + static const String stable = "v0.107.28"; + static const String beta = "v0.108.0-b.33"; +} \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index cc45a00..7c126ba 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -682,5 +682,9 @@ "processingLists": "Processing lists...", "enableDisableResult": "Enable or disable result", "selectedListsEnabledDisabledSuccessfully": "All selected lists have been enabled or disabled successfully", - "sslWarning": "If you are using an HTTPS connection with a self signed certificate, make sure to enable \"Don't check SSL certificate\" at Settings > Advanced settings." + "sslWarning": "If you are using an HTTPS connection with a self signed certificate, make sure to enable \"Don't check SSL certificate\" at Settings > Advanced settings.", + "unsupportedServerVersion": "Unsupported server version", + "unsupportedServerVersionMessage": "Your AdGuard Home server version is too old and is not supported by AdGuard Home Manager. You will need to upgrade your AdGuard Home server to a newer version to use this application.", + "yourVersion": "Your version: {version}", + "minimumRequiredVersion": "Minimum required version: {version}" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 9676508..9033460 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -682,5 +682,9 @@ "processingLists": "Procesando listas...", "enableDisableResult": "Resultado de activar o desactivar", "selectedListsEnabledDisabledSuccessfully": "Todas las listas seleccionadas se han activado o desactivado correctamente.", - "sslWarning": "Si estás usando una conexión HTTPS con un certificado autofirmado, asegúrate de activar \"No comprobar el certificado SSL\" en Ajustes > Ajustes avanzados." + "sslWarning": "Si estás usando una conexión HTTPS con un certificado autofirmado, asegúrate de activar \"No comprobar el certificado SSL\" en Ajustes > Ajustes avanzados.", + "unsupportedServerVersion": "Versión del servidor no soportada", + "unsupportedServerVersionMessage": "La versión de tu servidor AdGuard Home es demasiado antigua y no está soportada por AdGuard Home Manager. Necesitarás actualizar tu servidor AdGuard Home a una versión más actual para utilizar esta aplicación.", + "yourVersion": "Tu versión: {version}", + "minimumRequiredVersion": "Versión mínima requerida: {version}" } \ No newline at end of file diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index 049bf7f..59e8a55 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -5,12 +5,15 @@ import 'package:segmented_button_slide/segmented_button_slide.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/add_server/unsupported_version_modal.dart'; import 'package:adguard_home_manager/widgets/add_server/form_text_field.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; +import 'package:adguard_home_manager/config/minimum_server_version.dart'; import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/services/auth.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/api_client.dart'; @@ -166,6 +169,36 @@ class _AddServerModalState extends State { serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); } + statusProvider.setServerStatusLoad(LoadStatus.loading); + final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); + final serverStatus = await apiClient2.getServerStatus(); + + // If something goes wrong when fetching server status + if (serverStatus.successful == false) { + statusProvider.setServerStatusLoad(LoadStatus.error); + Navigator.pop(context); + return; + } + + final status = serverStatus.content as ServerStatus; + + // Check if ths server version is compatible + final validVersion = serverVersionIsAhead( + currentVersion: status.serverVersion, + referenceVersion: MinimumServerVersion.stable, + referenceVersionBeta: MinimumServerVersion.beta + ); + if (validVersion == false) { + showDialog( + context: context, + builder: (ctx) => UnsupportedVersionModal( + serverVersion: status.serverVersion, + onClose: () => Navigator.pop(context) + ) + ); + return; + } + final serverCreated = await serversProvider.createServer(serverObj); // If something goes wrong when saving the connection on the db @@ -181,19 +214,6 @@ class _AddServerModalState extends State { return; } - statusProvider.setServerStatusLoad(LoadStatus.loading); - final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); - final serverStatus = await apiClient2.getServerStatus(); - - // If something goes wrong when fetching server status - if (serverStatus.successful == false) { - statusProvider.setServerStatusLoad(LoadStatus.error); - Navigator.pop(context); - return; - } - - final status = serverStatus.content as ServerStatus; - // If everything is successful statusProvider.setServerStatusData( data: status @@ -247,6 +267,31 @@ class _AddServerModalState extends State { if (serverObj.user != null && serverObj.password != null) { serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); } + + final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); + final version = await apiClient2.getServerVersion(); + if (version.successful == false) { + if (mounted) setState(() => isConnecting = false); + return; + } + + // Check if ths server version is compatible + final validVersion = serverVersionIsAhead( + currentVersion: version.content, + referenceVersion: MinimumServerVersion.stable, + referenceVersionBeta: MinimumServerVersion.beta + ); + if (validVersion == false) { + showDialog( + context: context, + builder: (ctx) => UnsupportedVersionModal( + serverVersion: version.content, + onClose: () => Navigator.pop(context) + ) + ); + return; + } + final serverSaved = await serversProvider.editServer(serverObj); // If something goes wrong when saving the connection on the db @@ -270,8 +315,6 @@ class _AddServerModalState extends State { } // If everything is successful - final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); - final version = await apiClient2.getServerVersion(); if ( version.successful == true && (version.content.contains('a') || version.content.contains('b')) // alpha or beta @@ -499,7 +542,7 @@ class _AddServerModalState extends State { leading: CloseButton( onPressed: () => Navigator.pop(context), ), - title: widget.server != null + title: widget.server == null ? Text(AppLocalizations.of(context)!.createConnection) : Text(AppLocalizations.of(context)!.editConnection), actions: [ @@ -532,7 +575,9 @@ class _AddServerModalState extends State { ), const SizedBox(width: 8), Text( - AppLocalizations.of(context)!.createConnection, + widget.server == null + ? AppLocalizations.of(context)!.createConnection + : AppLocalizations.of(context)!.editConnection, style: const TextStyle( fontSize: 20 ), diff --git a/lib/widgets/add_server/unsupported_version_modal.dart b/lib/widgets/add_server/unsupported_version_modal.dart new file mode 100644 index 0000000..3340aad --- /dev/null +++ b/lib/widgets/add_server/unsupported_version_modal.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/config/minimum_server_version.dart'; + +class UnsupportedVersionModal extends StatelessWidget { + final String serverVersion; + final void Function() onClose; + + const UnsupportedVersionModal({ + super.key, + required this.serverVersion, + required this.onClose, + }); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Column( + children: [ + Icon( + Icons.error_rounded, + size: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.unsupportedServerVersion, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context)!.unsupportedServerVersionMessage, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.yourVersion(serverVersion), + style: const TextStyle( + fontStyle: FontStyle.italic + ), + ), + const SizedBox(height: 4), + Text( + AppLocalizations.of(context)!.minimumRequiredVersion( + serverVersion.contains("b") + ? MinimumServerVersion.beta + : MinimumServerVersion.stable + ), + style: const TextStyle( + fontStyle: FontStyle.italic + ), + ), + ], + ), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + onClose(); + }, + child: Text(AppLocalizations.of(context)!.close) + ), + ], + ); + } +} \ No newline at end of file From 93636526220d9ea6420c41ae1af1365cacc43adc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 02:26:53 +0100 Subject: [PATCH 389/676] Removed legacy code --- lib/models/clients.dart | 4 - lib/providers/clients_provider.dart | 16 +-- .../clients/client/added_client_tile.dart | 59 +++------ lib/screens/clients/client/client_form.dart | 25 +--- lib/screens/clients/client/client_screen.dart | 20 +-- lib/screens/clients/search_clients.dart | 26 ++-- .../home/management_modal/main_switch.dart | 115 +++++++----------- .../dns_rewrites/dns_rewrite_modal.dart | 12 -- lib/screens/settings/settings.dart | 6 +- 9 files changed, 70 insertions(+), 213 deletions(-) diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 4d8e7db..1472a0f 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -84,7 +84,6 @@ class Client { final bool filteringEnabled; final bool parentalEnabled; final bool safebrowsingEnabled; - final bool? safesearchEnabled; final bool useGlobalBlockedServices; final bool useGlobalSettings; final SafeSearch? safeSearch; @@ -98,7 +97,6 @@ class Client { required this.filteringEnabled, required this.parentalEnabled, required this.safebrowsingEnabled, - required this.safesearchEnabled, required this.useGlobalBlockedServices, required this.useGlobalSettings, required this.safeSearch, @@ -113,7 +111,6 @@ class Client { filteringEnabled: json["filtering_enabled"], parentalEnabled: json["parental_enabled"], safebrowsingEnabled: json["safebrowsing_enabled"], - safesearchEnabled: json["safesearch_enabled"], useGlobalBlockedServices: json["use_global_blocked_services"], useGlobalSettings: json["use_global_settings"], safeSearch: json["safe_search"] != null @@ -130,7 +127,6 @@ class Client { "filtering_enabled": filteringEnabled, "parental_enabled": parentalEnabled, "safebrowsing_enabled": safebrowsingEnabled, - "safesearch_enabled": safesearchEnabled, "safe_search": safeSearch, "use_global_blocked_services": useGlobalBlockedServices, "use_global_settings": useGlobalSettings, diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart index ae9cb28..a739c29 100644 --- a/lib/providers/clients_provider.dart +++ b/lib/providers/clients_provider.dart @@ -142,13 +142,7 @@ class ClientsProvider with ChangeNotifier { final result = await _serversProvider!.apiClient2!.postUpdateClient( data: { 'name': client.name, - 'data': serverVersionIsAhead( - currentVersion: _statusProvider!.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == false - ? removePropFromMap(client.toJson(), 'safesearch_enabled') - : removePropFromMap(client.toJson(), 'safe_search') + 'data': removePropFromMap(client.toJson(), 'safe_search') } ); @@ -175,13 +169,7 @@ class ClientsProvider with ChangeNotifier { Future addClient(Client client) async { final result = await _serversProvider!.apiClient2!.postAddClient( - data: serverVersionIsAhead( - currentVersion: _statusProvider!.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == false - ? removePropFromMap(client.toJson(), 'safesearch_enabled') - : removePropFromMap(client.toJson(), 'safe_search') + data: removePropFromMap(client.toJson(), 'safe_search') ); if (result.successful == true) { diff --git a/lib/screens/clients/client/added_client_tile.dart b/lib/screens/clients/client/added_client_tile.dart index aa3c31e..53a481a 100644 --- a/lib/screens/clients/client/added_client_tile.dart +++ b/lib/screens/clients/client/added_client_tile.dart @@ -5,8 +5,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -21,7 +19,7 @@ class AddedClientTile extends StatelessWidget { final bool? splitView; const AddedClientTile({ - Key? key, + super.key, required this.client, required this.onTap, required this.onLongPress, @@ -29,11 +27,10 @@ class AddedClientTile extends StatelessWidget { required this.onDelete, this.selectedClient, required this.splitView, - }) : super(key: key); + }); @override Widget build(BuildContext context) { - final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); if (splitView == true) { @@ -146,25 +143,13 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.search_rounded, size: 19, - color: serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? client.safeSearch != null && client.safeSearch!.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - : client.safesearchEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, + color: client.safeSearch != null && client.safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red ) ], ) @@ -260,25 +245,13 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.search_rounded, size: 19, - color: serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? client.safeSearch != null && client.safeSearch!.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - : client.safesearchEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, + color: client.safeSearch != null && client.safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red ) ], ) diff --git a/lib/screens/clients/client/client_form.dart b/lib/screens/clients/client/client_form.dart index ff4db9a..5d54b86 100644 --- a/lib/screens/clients/client/client_form.dart +++ b/lib/screens/clients/client/client_form.dart @@ -1,7 +1,6 @@ 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'; @@ -15,10 +14,8 @@ import 'package:adguard_home_manager/screens/clients/client/upstream_servers_sec 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; @@ -82,8 +79,6 @@ class ClientForm extends StatelessWidget { @override Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - return ListView( padding: const EdgeInsets.only(top: 0), children: [ @@ -195,13 +190,7 @@ class ClientForm extends StatelessWidget { onChange: (value) => updateEnableParentalControl(value), useGlobalSettingsFiltering: useGlobalSettingsFiltering, ), - if ( - serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ) CustomListTile( + CustomListTile( title: AppLocalizations.of(context)!.safeSearch, padding: const EdgeInsets.symmetric( horizontal: 42, @@ -226,18 +215,6 @@ class ClientForm extends StatelessWidget { ) : 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), diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index 243981c..34fb88b 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -6,10 +6,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.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/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/safe_search.dart'; 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 { @@ -75,8 +73,6 @@ class _ClientScreenState extends State { List upstreamServers = []; - bool version = false; - void enableDisableGlobalSettingsFiltering() { if (useGlobalSettingsFiltering == true) { setState(() { @@ -104,12 +100,6 @@ class _ClientScreenState extends State { @override void initState() { - version = serverVersionIsAhead( - currentVersion: Provider.of(context, listen: false).serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ); - if (widget.client != null) { validValues = true; @@ -123,12 +113,7 @@ class _ClientScreenState extends State { enableFiltering = widget.client!.filteringEnabled; enableParentalControl = widget.client!.parentalEnabled; enableSafeBrowsing = widget.client!.safebrowsingEnabled; - if (version == true) { - safeSearch = widget.client!.safeSearch; - } - else { - enableSafeSearch = widget.client!.safesearchEnabled ?? false; - } + safeSearch = widget.client!.safeSearch; useGlobalSettingsServices = widget.client!.useGlobalBlockedServices; blockedServices = widget.client!.blockedServices; upstreamServers = widget.client!.upstreams.map((e) => ControllerListItem( @@ -151,8 +136,7 @@ class _ClientScreenState extends State { filteringEnabled: enableFiltering ?? false, parentalEnabled: enableParentalControl ?? false, safebrowsingEnabled: enableSafeBrowsing ?? false, - safesearchEnabled: version == false ? enableSafeSearch : null, - safeSearch: version == true ? safeSearch : null, + safeSearch: safeSearch, useGlobalBlockedServices: useGlobalSettingsServices, blockedServices: blockedServices, upstreams: List.from(upstreamServers.map((e) => e.controller.text)), diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index 99d430c..a9c2cda 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -290,25 +290,13 @@ class _SearchClientsState extends State { Icon( Icons.search_rounded, size: 19, - color: serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? clientsScreen[index].safeSearch != null && clientsScreen[index].safeSearch!.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - : clientsScreen[index].safesearchEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, + color: clientsScreen[index].safeSearch != null && clientsScreen[index].safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red ) ], ) diff --git a/lib/screens/home/management_modal/main_switch.dart b/lib/screens/home/management_modal/main_switch.dart index 6c7b2ae..b2ae9ea 100644 --- a/lib/screens/home/management_modal/main_switch.dart +++ b/lib/screens/home/management_modal/main_switch.dart @@ -29,88 +29,55 @@ class MainSwitch extends StatelessWidget { return Padding( padding: const EdgeInsets.symmetric(horizontal: 24), - child: serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? ExpandableNotifier( - controller: expandableController, - child: Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: statusProvider.serverStatus!.generalEnabled == true && !statusProvider.protectionsManagementProcess.contains('general') - ? () => expandableController.toggle() - : null, + child: ExpandableNotifier( + controller: expandableController, + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: statusProvider.serverStatus!.generalEnabled == true && !statusProvider.protectionsManagementProcess.contains('general') + ? () => expandableController.toggle() + : null, + borderRadius: BorderRadius.circular(28), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + decoration: BoxDecoration( borderRadius: BorderRadius.circular(28), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12 - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(28), - color: Theme.of(context).colorScheme.primary.withOpacity(0.1) - ), - child: Expandable( - theme: const ExpandableThemeData( - animationDuration: Duration(milliseconds: 200), - fadeCurve: Curves.ease - ), - collapsed: _TopRow( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1) + ), + child: Expandable( + theme: const ExpandableThemeData( + animationDuration: Duration(milliseconds: 200), + fadeCurve: Curves.ease + ), + collapsed: _TopRow( + legacyMode: false, + expandableController: expandableController, + updateBlocking: updateBlocking, + animation: animation, + ), + expanded: Column( + children: [ + _TopRow( legacyMode: false, expandableController: expandableController, updateBlocking: updateBlocking, animation: animation, - ), - expanded: Column( - children: [ - _TopRow( - legacyMode: false, - expandableController: expandableController, - updateBlocking: updateBlocking, - animation: animation, - ), - _BottomRow( - disableWithCountdown: disableWithCountdown, - ), - const SizedBox(height: 8) - ], - ) - ), - ), - ), - ) - ) - : Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: statusProvider.protectionsManagementProcess.contains('general') == false - ? () => updateBlocking( - value: !statusProvider.serverStatus!.generalEnabled, - filter: 'general_legacy' - ) : null, - borderRadius: BorderRadius.circular(28), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12 - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(28), - color: Theme.of(context).primaryColor.withOpacity(0.1) - ), - child: _TopRow( - legacyMode: true, - expandableController: expandableController, - updateBlocking: updateBlocking, - animation: animation, + ), + _BottomRow( + disableWithCountdown: disableWithCountdown, + ), + const SizedBox(height: 8) + ], ) ), ), - ) + ), + ) + ) ); } } diff --git a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart index b43c168..74d50d8 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart @@ -181,11 +181,6 @@ class _AddDnsRewriteModalState extends State { TextButton( onPressed: validData == true ? () { - if (serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: '0.107.33', - referenceVersionBeta: '0.108.0-b.39' - )) { Navigator.pop(context); widget.onConfirm( RewriteRules( @@ -195,13 +190,6 @@ class _AddDnsRewriteModalState extends State { widget.rule ); } - else { - showDialog( - context: context, - builder: (context) => const ServerVersionNeeded(version: 'v0.107.33') - ); - } - } : null, child: Text( AppLocalizations.of(context)!.confirm, diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 6a67d28..ed3dd26 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -170,11 +170,7 @@ class _SettingsWidgetState extends State { serversProvider.apiClient != null ) ...[ SectionLabel(label: AppLocalizations.of(context)!.serverSettings), - if (serverVersionIsAhead( - currentVersion: statusProvider.serverStatus!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true) settingsTile( + settingsTile( icon: Icons.search_rounded, title: AppLocalizations.of(context)!.safeSearch, subtitle: AppLocalizations.of(context)!.safeSearchSettings, From 5e6708366125ff25e701535925222f9122ff62ba Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 02:31:07 +0100 Subject: [PATCH 390/676] Removed legacy code --- lib/screens/clients/search_clients.dart | 3 +- .../home/management_modal/main_switch.dart | 1 - .../dns_rewrites/dns_rewrite_modal.dart | 336 +++++++++--------- lib/screens/settings/settings.dart | 1 - 4 files changed, 176 insertions(+), 165 deletions(-) diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index a9c2cda..bbc330c 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -13,7 +13,6 @@ import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; @@ -21,7 +20,7 @@ import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; class SearchClients extends StatefulWidget { - const SearchClients({Key? key}) : super(key: key); + const SearchClients({super.key}); @override State createState() => _SearchClientsState(); diff --git a/lib/screens/home/management_modal/main_switch.dart b/lib/screens/home/management_modal/main_switch.dart index b2ae9ea..d4ce5ed 100644 --- a/lib/screens/home/management_modal/main_switch.dart +++ b/lib/screens/home/management_modal/main_switch.dart @@ -6,7 +6,6 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; class MainSwitch extends StatelessWidget { diff --git a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart index 74d50d8..fcd62d7 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart @@ -1,34 +1,78 @@ 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/settings/dns_rewrites/server_version_needed.dart'; - -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; -class DnsRewriteModal extends StatefulWidget { +class DnsRewriteModal extends StatelessWidget { final void Function(RewriteRules newRule, RewriteRules? previousRule) onConfirm; final bool dialog; final RewriteRules? rule; final void Function(RewriteRules) onDelete; const DnsRewriteModal({ - Key? key, + super.key, required this.onConfirm, required this.dialog, this.rule, required this.onDelete - }) : super(key: key); + }); @override - State createState() => _AddDnsRewriteModalState(); + Widget build(BuildContext context) { + if (dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: _Content( + onConfirm: onConfirm, + onDelete: onDelete, + rule: rule, + ) + ), + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor, + ), + child: _Content( + onConfirm: onConfirm, + onDelete: onDelete, + rule: rule, + ) + ), + ); + } + } } -class _AddDnsRewriteModalState extends State { +class _Content extends StatefulWidget { + final void Function(RewriteRules newRule, RewriteRules? previousRule) onConfirm; + final RewriteRules? rule; + final void Function(RewriteRules) onDelete; + + const _Content({ + required this.onConfirm, + this.rule, + required this.onDelete + }); + + @override + State<_Content> createState() => _ContentState(); +} + +class _ContentState extends State<_Content> { final TextEditingController domainController = TextEditingController(); String? domainError; final TextEditingController answerController = TextEditingController(); @@ -71,169 +115,139 @@ class _AddDnsRewriteModalState extends State { @override Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - widget.rule != null - ? Icons.edit - : Icons.add, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( widget.rule != null - ? AppLocalizations.of(context)!.editRewriteRule - : AppLocalizations.of(context)!.addDnsRewrite, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), + ? Icons.edit + : Icons.add, + size: 24, + color: Theme.of(context).listTileTheme.iconColor ), - const SizedBox(height: 16), - ], - ), - ], - ), - Padding( - padding: const EdgeInsets.only( - left: 24, right: 24, bottom: 12 - ), - child: TextFormField( - controller: domainController, - onChanged: validateDomain, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) ), - errorText: domainError, - labelText: AppLocalizations.of(context)!.domain, + const SizedBox(height: 16), + Text( + widget.rule != null + ? AppLocalizations.of(context)!.editRewriteRule + : AppLocalizations.of(context)!.addDnsRewrite, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 24), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, bottom: 12 + ), + child: TextFormField( + controller: domainController, + onChanged: validateDomain, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) ), + errorText: domainError, + labelText: AppLocalizations.of(context)!.domain, ), ), - Padding( - padding: const EdgeInsets.only( - left: 24, right: 24, top: 12 + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, top: 12 + ), + child: TextFormField( + controller: answerController, + onChanged: (_) => checkValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.system_update_alt_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.answer, ), - child: TextFormField( - controller: answerController, - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.system_update_alt_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.answer, + ), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (widget.rule != null) TextButton( + onPressed: () { + Navigator.pop(context); + widget.onDelete( + RewriteRules( + domain: domainController.text, + answer: answerController.text + ) + ); + }, + child: Text(AppLocalizations.of(context)!.delete), + ), + if (widget.rule == null) const SizedBox(), + Row( + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel), + ), + const SizedBox(width: 20), + TextButton( + onPressed: validData == true + ? () { + Navigator.pop(context); + widget.onConfirm( + RewriteRules( + domain: domainController.text, + answer: answerController.text + ), + widget.rule + ); + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, + style: TextStyle( + color: validData == true + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) ), ), ), ], - ), - ), + ) + ], ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (widget.rule != null) TextButton( - onPressed: () { - Navigator.pop(context); - widget.onDelete( - RewriteRules( - domain: domainController.text, - answer: answerController.text - ) - ); - }, - child: Text(AppLocalizations.of(context)!.delete), - ), - if (widget.rule == null) const SizedBox(), - Row( - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel), - ), - const SizedBox(width: 20), - TextButton( - onPressed: validData == true - ? () { - Navigator.pop(context); - widget.onConfirm( - RewriteRules( - domain: domainController.text, - answer: answerController.text - ), - widget.rule - ); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: validData == true - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - ), - ), - ), - ], - ) - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ); - } - - if (widget.dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 400 - ), - child: content() ), - ); - } - else { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor, - ), - child: content() - ), - ); - } + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); } } \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index ed3dd26..c3b1337 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -26,7 +26,6 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; From dbb26093399506c06123a990c7061a3c3e5c1037 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 02:31:47 +0100 Subject: [PATCH 391/676] Removed unused import --- lib/providers/clients_provider.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart index a739c29..bfcf19d 100644 --- a/lib/providers/clients_provider.dart +++ b/lib/providers/clients_provider.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/maps_fns.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -13,11 +12,9 @@ enum AccessSettingsList { allowed, disallowed, domains } class ClientsProvider with ChangeNotifier { ServersProvider? _serversProvider; - StatusProvider? _statusProvider; update(ServersProvider? servers, StatusProvider? status) { _serversProvider = servers; - _statusProvider = status; } LoadStatus _loadStatus = LoadStatus.loading; From 39cdcf648d6bf53e0fe5dce443a99a6bc49044ff Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 14:22:01 +0100 Subject: [PATCH 392/676] Show server version message on app start --- lib/config/globals.dart | 3 ++- lib/main.dart | 12 +++++++----- lib/providers/servers_provider.dart | 2 +- lib/providers/status_provider.dart | 27 ++++++++++++++++++++++++++- lib/widgets/layout.dart | 4 ++-- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/lib/config/globals.dart b/lib/config/globals.dart index d21860b..a955a77 100644 --- a/lib/config/globals.dart +++ b/lib/config/globals.dart @@ -1,3 +1,4 @@ import 'package:flutter/material.dart'; -final GlobalKey scaffoldMessengerKey = GlobalKey(); \ No newline at end of file +final GlobalKey scaffoldMessengerKey = GlobalKey(); +final GlobalKey globalNavigatorKey = GlobalKey(); \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index b025caa..5b38138 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -235,13 +235,16 @@ class _MainState extends State
{ Locale('tr', '') ], scaffoldMessengerKey: scaffoldMessengerKey, + navigatorKey: globalNavigatorKey, builder: (context, child) { return CustomMenuBar( child: MediaQuery( data: MediaQuery.of(context).copyWith( - textScaleFactor: !(Platform.isAndroid || Platform.isIOS) - ? 0.9 - : 1.0 + textScaler: TextScaler.linear( + !(Platform.isAndroid || Platform.isIOS) + ? 0.9 + : 1.0 + ) ), child: child!, ), @@ -251,5 +254,4 @@ class _MainState extends State
{ ), ); } -} - +} \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 600c46e..addf617 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -60,7 +60,7 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setSelectedServer(Server server) { + void setSelectedServer(Server? server) { _selectedServer = server; notifyListeners(); } diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 38193b8..53fd2f5 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -2,6 +2,11 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/widgets/add_server/unsupported_version_modal.dart'; + +import 'package:adguard_home_manager/config/globals.dart'; +import 'package:adguard_home_manager/config/minimum_server_version.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -240,11 +245,31 @@ class StatusProvider with ChangeNotifier { final result = await _serversProvider!.apiClient2!.getServerStatus(); if (result.successful == true) { + final status = result.content as ServerStatus; setServerStatusData( - data: result.content as ServerStatus + data: status ); _loadStatus = LoadStatus.loaded; notifyListeners(); + + // Check server version and launch modal if not valid + final validVersion = serverVersionIsAhead( + currentVersion: status.serverVersion, + referenceVersion: MinimumServerVersion.stable, + referenceVersionBeta: MinimumServerVersion.beta + ); + if (validVersion == false) { + showDialog( + context: globalNavigatorKey.currentContext!, + builder: (ctx) => UnsupportedVersionModal( + serverVersion: status.serverVersion, + onClose: () { + _serversProvider!.setSelectedServer(null); + } + ) + ); + } + return true; } else { diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index fe3aa1c..8a0a14b 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -15,8 +15,8 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; class Layout extends StatefulWidget { const Layout({ - Key? key, - }) : super(key: key); + super.key, + }); @override State createState() => _LayoutState(); From 48f33eee9bcb2f3ba6e07658cf582e23413c4cf4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 15:00:07 +0100 Subject: [PATCH 393/676] Replaced old http service with new one --- lib/providers/dns_provider.dart | 6 +- lib/providers/logs_provider.dart | 22 +- lib/providers/servers_provider.dart | 40 +- lib/providers/status_provider.dart | 4 +- .../clients/client/logs_list_client.dart | 2 +- lib/screens/settings/dhcp/dhcp.dart | 4 +- .../settings/server_info/server_info.dart | 58 +- lib/screens/settings/settings.dart | 2 +- lib/widgets/bottom_nav_bar.dart | 8 +- lib/widgets/layout.dart | 33 +- lib/widgets/navigation_rail.dart | 6 +- .../servers_list/server_tile_functions.dart | 140 +++++ .../servers_list/servers_list_item.dart | 2 - .../servers_list/servers_tile_item.dart | 570 ++++++++---------- 14 files changed, 466 insertions(+), 431 deletions(-) create mode 100644 lib/widgets/servers_list/server_tile_functions.dart diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index db1767f..0929f3a 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -42,10 +42,10 @@ class DnsProvider with ChangeNotifier { _loadStatus = LoadStatus.loading; } - final result = await _serversProvider!.apiClient!.getDnsInfo(); + final result = await _serversProvider!.apiClient2!.getDnsInfo(); - if (result['result'] == 'success') { - _dnsInfo = result['data']; + if (result.successful == true) { + _dnsInfo = result.content as DnsInfo; _loadStatus = LoadStatus.loaded; notifyListeners(); return true; diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index a3211b5..7861e6d 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -153,7 +153,7 @@ class LogsProvider with ChangeNotifier { notifyListeners(); } - final result = await _serversProvider!.apiClient!.getLogs( + final result = await _serversProvider!.apiClient2!.getLogs( count: logsQuantity, offset: offst, olderThan: logsOlderThan, @@ -166,11 +166,11 @@ class LogsProvider with ChangeNotifier { notifyListeners(); } - if (result['result'] == 'success') { + if (result.successful == true) { _offset = inOffset != null ? inOffset+logsQuantity : offset+logsQuantity; if (loadingMore != null && loadingMore == true && logsData != null) { - LogsData newLogsData = result['data']; - newLogsData.data = [...logsData!.data, ...result['data'].data]; + LogsData newLogsData = result.content; + newLogsData.data = [...logsData!.data, ...(result.content as LogsData).data]; if (appliedFilters.clients != null) { newLogsData.data = newLogsData.data.where( (item) => appliedFilters.clients!.contains(item.client) @@ -179,7 +179,7 @@ class LogsProvider with ChangeNotifier { _logsData = newLogsData; } else { - LogsData newLogsData = result['data']; + LogsData newLogsData = result.content; if (appliedFilters.clients != null) { newLogsData.data = newLogsData.data.where( (item) => appliedFilters.clients!.contains(item.client) @@ -204,7 +204,7 @@ class LogsProvider with ChangeNotifier { resetFilters(); - final result = await _serversProvider!.apiClient!.getLogs( + final result = await _serversProvider!.apiClient2!.getLogs( count: logsQuantity ); @@ -214,8 +214,8 @@ class LogsProvider with ChangeNotifier { clients: null ); - if (result['result'] == 'success') { - _logsData = result['data']; + if (result.successful == true) { + _logsData = result.content as LogsData; _loadStatus = LoadStatus.loaded; notifyListeners(); return true; @@ -233,7 +233,7 @@ class LogsProvider with ChangeNotifier { setOffset(0); - final result = await _serversProvider!.apiClient!.getLogs( + final result = await _serversProvider!.apiClient2!.getLogs( count: logsQuantity, olderThan: logsOlderThan, responseStatus: selectedResultStatus, @@ -246,8 +246,8 @@ class LogsProvider with ChangeNotifier { clients: selectedClients ); - if (result['result'] == 'success') { - LogsData newLogsData = result['data']; + if (result.successful == true) { + LogsData newLogsData = result.content as LogsData; if (appliedFilters.clients != null) { newLogsData.data = newLogsData.data.where( (item) => appliedFilters.clients!.contains(item.client) diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index addf617..a8f1003 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -7,7 +7,6 @@ import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/services/external_requests.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/models/update_available.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/services/db/queries.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -17,7 +16,7 @@ class ServersProvider with ChangeNotifier { List _serversList = []; Server? _selectedServer; - ApiClient? _apiClient; + // ApiClient? _apiClient; ApiClientV2? _apiClient2; bool _updatingServer = false; @@ -27,9 +26,9 @@ class ServersProvider with ChangeNotifier { data: null, ); - ApiClient? get apiClient { - return _apiClient; - } + // ApiClient? get apiClient { + // return _apiClient; + // } ApiClientV2? get apiClient2 { return _apiClient2; @@ -77,10 +76,10 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setApiClient(ApiClient client) { - _apiClient = client; - notifyListeners(); - } + // void setApiClient(ApiClient client) { + // _apiClient = client; + // notifyListeners(); + // } void setApiClient2(ApiClientV2 client) { _apiClient2 = client; @@ -153,7 +152,8 @@ class ServersProvider with ChangeNotifier { _serversList = newServers; if (selectedServer != null &&server.id == selectedServer!.id) { - _apiClient = ApiClient(server: server); + // _apiClient = ApiClient(server: server); + _apiClient2 = ApiClientV2(server: server); } notifyListeners(); @@ -168,7 +168,7 @@ class ServersProvider with ChangeNotifier { final result = await removeServerQuery(_dbInstance!, server.id); if (result == true) { _selectedServer = null; - _apiClient = null; + // _apiClient = null; List newServers = _serversList.where((s) => s.id != server.id).toList(); _serversList = newServers; notifyListeners(); @@ -181,13 +181,13 @@ class ServersProvider with ChangeNotifier { void checkServerUpdatesAvailable({ required Server server, - ApiClient? apiClient + ApiClientV2? apiClient }) async { - final client = apiClient ?? _apiClient; + final client = apiClient ?? _apiClient2; setUpdateAvailableLoadStatus(LoadStatus.loading, true); final result = await client!.checkServerUpdates(); - if (result['result'] == 'success') { - UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); + if (result.successful == true) { + UpdateAvailableData data = UpdateAvailableData.fromJson(result.content); final gitHubResult = await ExternalRequests.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); if (gitHubResult.successful == true) { data.changelog = gitHubResult.content; @@ -200,12 +200,12 @@ class ServersProvider with ChangeNotifier { } } - Future initializateServer(Server server, ApiClient apiClient, ApiClientV2 apiClient2) async { + Future initializateServer(Server server, /*ApiClient apiClient, */ ApiClientV2 apiClient2) async { final serverStatus = await _apiClient2!.getServerStatus(); if (serverStatus.successful == true) { checkServerUpdatesAvailable( // Do not await server: server, - apiClient: apiClient + apiClient: apiClient2 ); } } @@ -237,11 +237,11 @@ class ServersProvider with ChangeNotifier { if (defaultServer != null) { _selectedServer = defaultServer; - final client = ApiClient(server: defaultServer); + // final client = ApiClient(server: defaultServer); final client2 = ApiClientV2(server: defaultServer); - _apiClient = client; + // _apiClient = client; _apiClient2 = client2; - initializateServer(defaultServer, client, client2); + initializateServer(defaultServer, /*client,*/ client2); } } else { diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 53fd2f5..5fba2dd 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -149,13 +149,13 @@ class StatusProvider with ChangeNotifier { _protectionsManagementProcess.add('filtering'); notifyListeners(); - final result = await _serversProvider!.apiClient!.updateFiltering( + final result = await _serversProvider!.apiClient2!.updateFiltering( enable: newStatus, ); _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'filtering').toList(); - if (result['result'] == 'success') { + if (result.successful == true) { _serverStatus!.filteringEnabled = newStatus; notifyListeners(); return true; diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index 8d975a9..422c80c 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -67,7 +67,7 @@ class _LogsListClientState extends State { if (cancelableRequest != null) cancelableRequest!.cancel(); cancelableRequest = CancelableOperation.fromFuture( - serversProvider.apiClient!.getLogs( + serversProvider.apiClient2!.getLogs( count: logsQuantity, offset: offst, search: '"${widget.ip}"' diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 6440e3b..dbb4a9a 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -260,11 +260,11 @@ class _DhcpScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.restoringLeases); - final result = await serversProvider.apiClient!.restoreAllLeases(); + final result = await serversProvider.apiClient2!.restoreAllLeases(); processModal.close(); - if (result['result'] == 'success') { + if (result.successful == true) { DhcpModel data = dhcpProvider.dhcp!; data.dhcpStatus.staticLeases = []; data.dhcpStatus.leases = []; diff --git a/lib/screens/settings/server_info/server_info.dart b/lib/screens/settings/server_info/server_info.dart index 2a51a16..3032dcf 100644 --- a/lib/screens/settings/server_info/server_info.dart +++ b/lib/screens/settings/server_info/server_info.dart @@ -1,61 +1,37 @@ -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/functions/desktop_mode.dart'; -import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; +import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/server_info/dns_addresses_modal.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/server_info.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class ServerInformation extends StatelessWidget { - const ServerInformation({Key? key}) : super(key: key); +class ServerInformation extends StatefulWidget { + const ServerInformation({super.key}); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return ServerInformationWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _ServerInformationState(); } -class ServerInformationWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const ServerInformationWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - }) : super(key: key); - - @override - State createState() => _ServerInformationWidgetState(); -} - -class _ServerInformationWidgetState extends State { +class _ServerInformationState extends State { ServerInfo serverInfo = ServerInfo(loadStatus: LoadStatus.loading); void fetchServerInfo() async { - final result = await Provider.of(context, listen: false).apiClient!.getServerInfo(); - if (mounted) { - if (result['result'] == 'success') { - setState(() { - serverInfo.data = result['data']; - serverInfo.loadStatus = LoadStatus.loaded; - }); - } - else { - setState(() => serverInfo.loadStatus = LoadStatus.error); - } + final result = await Provider.of(context, listen: false).apiClient2!.getServerInfo(); + if (!mounted) return; + if (result.successful == true) { + setState(() { + serverInfo.data = result.content as ServerInfoData; + serverInfo.loadStatus = LoadStatus.loaded; + }); + } + else { + setState(() => serverInfo.loadStatus = LoadStatus.error); } } diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index c3b1337..8d5f384 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -166,7 +166,7 @@ class _SettingsWidgetState extends State { if ( serversProvider.selectedServer != null && statusProvider.serverStatus != null && - serversProvider.apiClient != null + serversProvider.apiClient2 != null ) ...[ SectionLabel(label: AppLocalizations.of(context)!.serverSettings), settingsTile( diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index b5ff9df..8d06a8d 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -8,14 +8,14 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/app_screen.dart'; class BottomNavBar extends StatelessWidget { - const BottomNavBar({Key? key}) : super(key: key); + const BottomNavBar({super.key}); @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - List screens = serversProvider.selectedServer != null && serversProvider.apiClient != null + List screens = serversProvider.selectedServer != null && serversProvider.apiClient2 != null ? screensServerConnected : screensSelectServer; @@ -44,12 +44,12 @@ class BottomNavBar extends StatelessWidget { } } - if ((serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1) { + if ((serversProvider.selectedServer == null || serversProvider.apiClient2 == null) && appConfigProvider.selectedScreen > 1) { appConfigProvider.setSelectedScreen(0); } return NavigationBar( - selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient2 == null) && appConfigProvider.selectedScreen > 1 ? 0 : appConfigProvider.selectedScreen, destinations: screens.map((screen) => NavigationDestination( diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index 8a0a14b..4d6e131 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -62,7 +62,7 @@ class _LayoutState extends State with WidgetsBindingObserver { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - final screens = serversProvider.selectedServer != null + final screens = serversProvider.selectedServer != null && serversProvider.apiClient2 != null ? screensServerConnected : screensSelectServer; @@ -120,26 +120,15 @@ class _LayoutState extends State with WidgetsBindingObserver { ), ], ), - if (serversProvider.selectedServer != null) - ...screensServerConnected.asMap().entries.map( - (s) => DrawerTile( - icon: s.value.icon, - title: translatedName(s.value.name), - isSelected: appConfigProvider.selectedScreen == s.key, - onSelect: () => _goBranch(s.key), - withoutTitle: !_drawerExpanded, - ), - ), - if (serversProvider.selectedServer == null) - ...screensSelectServer.asMap().entries.map( - (s) => DrawerTile( - icon: s.value.icon, - title: translatedName(s.value.name), - isSelected: appConfigProvider.selectedScreen == s.key, - onSelect: () => _goBranch(s.key), - withoutTitle: !_drawerExpanded, - ), + ...screens.asMap().entries.map( + (s) => DrawerTile( + icon: s.value.icon, + title: translatedName(s.value.name), + isSelected: appConfigProvider.selectedScreen == s.key, + onSelect: () => _goBranch(s.key), + withoutTitle: !_drawerExpanded, ), + ), ], ), ), @@ -164,7 +153,7 @@ class _LayoutState extends State with WidgetsBindingObserver { ); } else { - final screens = serversProvider.selectedServer != null && serversProvider.apiClient != null + final screens = serversProvider.selectedServer != null && serversProvider.apiClient2 != null ? screensServerConnected : screensSelectServer; @@ -184,7 +173,7 @@ class _LayoutState extends State with WidgetsBindingObserver { : screens[0].child, ), bottomNavigationBar: NavigationBar( - selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient2 == null) && appConfigProvider.selectedScreen > 1 ? 0 : appConfigProvider.selectedScreen, onDestinationSelected: (s) => _goBranch(s), diff --git a/lib/widgets/navigation_rail.dart b/lib/widgets/navigation_rail.dart index 063993c..2d2e1ef 100644 --- a/lib/widgets/navigation_rail.dart +++ b/lib/widgets/navigation_rail.dart @@ -9,7 +9,7 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class SideNavigationRail extends StatelessWidget { - const SideNavigationRail({Key? key}) : super(key: key); + const SideNavigationRail({super.key}); @override Widget build(BuildContext context) { @@ -46,12 +46,12 @@ class SideNavigationRail extends StatelessWidget { } } - if ((serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1) { + if ((serversProvider.selectedServer == null || serversProvider.apiClient2 == null) && appConfigProvider.selectedScreen > 1) { appConfigProvider.setSelectedScreen(0); } return NavigationRail( - selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient2 == null) && appConfigProvider.selectedScreen > 1 ? 0 : appConfigProvider.selectedScreen, destinations: screens.map((screen) => NavigationRailDestination( diff --git a/lib/widgets/servers_list/server_tile_functions.dart b/lib/widgets/servers_list/server_tile_functions.dart new file mode 100644 index 0000000..e3fa4d6 --- /dev/null +++ b/lib/widgets/servers_list/server_tile_functions.dart @@ -0,0 +1,140 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; +import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; +import 'package:adguard_home_manager/services/auth.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/models/server.dart'; + +EdgeInsets generateMargins({ + required int index, + required int serversListLength +}) { + if (index == 0) { + return const EdgeInsets.only(top: 16, left: 16, right: 8, bottom: 8); + } + if (index == 1) { + return const EdgeInsets.only(top: 16, left: 8, right: 16, bottom: 8); + } + else if (index == serversListLength-1 && (index+1)%2 == 0) { + return const EdgeInsets.only(top: 8, left: 8, right: 16, bottom: 16); + } + else if (index == serversListLength-1 && (index+1)%2 == 1) { + return const EdgeInsets.only(top: 8, left: 16, right: 8, bottom: 16); + } + else { + if ((index+1)%2 == 0) { + return const EdgeInsets.only(top: 8, left: 8, right: 16, bottom: 8); + } + else { + return const EdgeInsets.only(top: 8, left: 16, right: 8, bottom: 8); + } + } +} + +void showDeleteModal({ + required BuildContext context, + required Server server +}) async { + await Future.delayed(const Duration(seconds: 0), () => { + showDialog( + context: context, + builder: (context) => DeleteModal( + serverToDelete: server, + ), + barrierDismissible: false + ) + }); +} + +void openServerModal({ + required BuildContext context, + required double width, + Server? server, +}) async { + await Future.delayed(const Duration(seconds: 0), (() => { + openServerFormModal(context: context, width: width, server: server) + })); +} + +void connectToServer({ + required BuildContext context, + required Server server +}) async { + final ProcessModal process = ProcessModal(context: context); + process.open(AppLocalizations.of(context)!.connecting); + + final result = server.runningOnHa == true + ? await ServerAuth.loginHA(server) + : await ServerAuth.login(server); + + if (result == AuthStatus.success && context.mounted) { + final serversProvider = Provider.of(context, listen: false); + final statusProvider = Provider.of(context, listen: false); + + final ApiClientV2 apiClient2 = ApiClientV2(server: server); + serversProvider.setApiClient2(apiClient2); + serversProvider.setSelectedServer(server); + + statusProvider.setServerStatusLoad(LoadStatus.loading); + final serverStatus = await apiClient2.getServerStatus(); + if (serverStatus.successful == true) { + statusProvider.setServerStatusData( + data: serverStatus.content as ServerStatus + ); + serversProvider.checkServerUpdatesAvailable( + server: server, + ); + statusProvider.setServerStatusLoad(LoadStatus.loaded); + } + else { + statusProvider.setServerStatusLoad(LoadStatus.error); + } + + process.close(); + } + else { + process.close(); + if (!context.mounted) return; + final appConfigProvider = Provider.of(context, listen: false); + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.cannotConnect, + color: Colors.red + ); + } +} + +void setDefaultServer({ + required BuildContext context, + required Server server +}) async { + final serversProvider = Provider.of(context, listen: false); + final result = await serversProvider.setDefaultServer(server); + if (!context.mounted) return; + final appConfigProvider = Provider.of(context, listen: false); + if (result == null) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionDefaultFailed, + color: Colors.red + ); + } +} \ No newline at end of file diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 492a5e8..e67b436 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -104,8 +104,6 @@ class _ServersListItemState extends State with SingleTickerProv : await login(server); if (result['result'] == 'success') { - final ApiClient apiClient = ApiClient(server: server); - serversProvider.setApiClient(apiClient); final ApiClientV2 apiClient2 = ApiClientV2(server: server); serversProvider.setApiClient2(apiClient2); serversProvider.setSelectedServer(server); diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index 0422368..61c2a64 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -4,18 +4,10 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; -import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; +import 'package:adguard_home_manager/widgets/servers_list/server_tile_functions.dart'; -import 'package:adguard_home_manager/models/server_status.dart'; -import 'package:adguard_home_manager/services/api_client.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -26,12 +18,12 @@ class ServersTileItem extends StatefulWidget { final double breakingWidth; const ServersTileItem({ - Key? key, + super.key, required this.server, required this.index, required this.onChange, required this.breakingWidth - }) : super(key: key); + }); @override State createState() => _ServersTileItemState(); @@ -46,332 +38,272 @@ class _ServersTileItemState extends State with SingleTickerProv final width = MediaQuery.of(context).size.width; - void showDeleteModal(Server server) async { - await Future.delayed(const Duration(seconds: 0), () => { - showDialog( - context: context, - builder: (context) => DeleteModal( - serverToDelete: server, - ), - barrierDismissible: false - ) - }); - } - - void openServerModal({Server? server}) async { - await Future.delayed(const Duration(seconds: 0), (() => { - openServerFormModal(context: context, width: width, server: server) - })); - } - - void connectToServer(Server server) async { - final ProcessModal process = ProcessModal(context: context); - process.open(AppLocalizations.of(context)!.connecting); - - final result = server.runningOnHa == true - ? await loginHA(server) - : await login(server); - - if (result['result'] == 'success') { - final ApiClient apiClient = ApiClient(server: server); - serversProvider.setApiClient(apiClient); - final ApiClientV2 apiClient2 = ApiClientV2(server: server); - serversProvider.setApiClient2(apiClient2); - serversProvider.setSelectedServer(server); - - statusProvider.setServerStatusLoad(LoadStatus.loading); - final serverStatus = await apiClient2.getServerStatus(); - if (serverStatus.successful == true) { - statusProvider.setServerStatusData( - data: serverStatus.content as ServerStatus - ); - serversProvider.checkServerUpdatesAvailable( - server: server, - ); - statusProvider.setServerStatusLoad(LoadStatus.loaded); - } - else { - statusProvider.setServerStatusLoad(LoadStatus.error); - } - - process.close(); - } - else { - process.close(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.cannotConnect, - color: Colors.red - ); - } - } - - void setDefaultServer(Server server) async { - final result = await serversProvider.setDefaultServer(server); - if (result == null) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, - color: Colors.green - ); - } - else { - appConfigProvider.addLog( - AppLog( - type: 'set_default_server', - dateTime: DateTime.now(), - message: result.toString() - ) - ); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionDefaultFailed, - color: Colors.red - ); - } - } - - Widget leadingIcon(Server server) { - if (server.defaultServer == true) { - return Stack( - alignment: Alignment.center, - children: [ - Icon( - Icons.storage_rounded, - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? statusProvider.serverStatus != null - ? Colors.green - : Colors.orange - : null, - ), - SizedBox( - width: 25, - height: 25, - child: Stack( - alignment: Alignment.bottomRight, - children: [ - Container( - padding: const EdgeInsets.all(1), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primaryContainer, - borderRadius: BorderRadius.circular(20) - ), - child: Icon( - Icons.star, - color: Theme.of(context).colorScheme.onPrimaryContainer, - size: 10, - ), - ), - ], - ), - ) - ], - ); - } - else { - return Icon( - Icons.storage_rounded, - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? statusProvider.serverStatus != null - ? Colors.green - : Colors.orange - : null, - ); - } - } - - Widget topRow(Server server, int index) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Row( - children: [ - Container( - margin: const EdgeInsets.only(right: 16), - child: leadingIcon(server), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", - textAlign: TextAlign.left, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Column( - children: [ - const SizedBox(height: 3), - Text( - server.name, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ) - ], - ) - ], - ), - ), - ], - ), - ), - ], - ); - } - - Widget bottomRow(Server server, int index) { - return Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - enabled: server.defaultServer == false - ? true - : false, - onTap: server.defaultServer == false - ? (() => setDefaultServer(server)) - : null, - child: SizedBox( - child: Row( - children: [ - const Icon(Icons.star), - const SizedBox(width: 15), - Text( - server.defaultServer == true - ? AppLocalizations.of(context)!.defaultConnection - : AppLocalizations.of(context)!.setDefault, - ) - ], - ), - ) - ), - PopupMenuItem( - onTap: (() => openServerModal(server: server)), - child: Row( - children: [ - const Icon(Icons.edit), - const SizedBox(width: 15), - Text(AppLocalizations.of(context)!.edit) - ], - ) - ), - PopupMenuItem( - onTap: (() => showDeleteModal(server)), - child: Row( - children: [ - const Icon(Icons.delete), - const SizedBox(width: 15), - Text(AppLocalizations.of(context)!.delete) - ], - ) - ), - ] - ), - SizedBox( - child: serversProvider.selectedServer != null && - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null && - serversProvider.selectedServer?.id == server.id - ? Padding( - padding: const EdgeInsets.only(right: 16), - child: Row( - children: [ - Icon( - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null - ? Icons.check - : Icons.warning, - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null - ? Colors.green - : Colors.orange, - ), - const SizedBox(width: 10), - Text( - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null - ? AppLocalizations.of(context)!.connected - : AppLocalizations.of(context)!.selectedDisconnected, - style: TextStyle( - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null - ? Colors.green - : Colors.orange, - fontWeight: FontWeight.w500 - ), - ) - ], - ), - ) - : Container( - margin: const EdgeInsets.only(right: 10), - child: FilledButton.icon( - icon: const Icon(Icons.login), - onPressed: () => connectToServer(server), - label: Text(AppLocalizations.of(context)!.connect), - ), - ), - ) - ], - ) - ], - ); - } - - EdgeInsets generateMargins(int index) { - if (index == 0) { - return const EdgeInsets.only(top: 16, left: 16, right: 8, bottom: 8); - } - if (index == 1) { - return const EdgeInsets.only(top: 16, left: 8, right: 16, bottom: 8); - } - else if (index == serversProvider.serversList.length-1 && (index+1)%2 == 0) { - return const EdgeInsets.only(top: 8, left: 8, right: 16, bottom: 16); - } - else if (index == serversProvider.serversList.length-1 && (index+1)%2 == 1) { - return const EdgeInsets.only(top: 8, left: 16, right: 8, bottom: 16); - } - else { - if ((index+1)%2 == 0) { - return const EdgeInsets.only(top: 8, left: 8, right: 16, bottom: 8); - } - else { - return const EdgeInsets.only(top: 8, left: 16, right: 8, bottom: 8); - } - } - } - return FractionallySizedBox( widthFactor: width > widget.breakingWidth ? 0.5 : 1, child: Card( margin: width > widget.breakingWidth - ? generateMargins(widget.index) + ? generateMargins(index: widget.index, serversListLength: serversProvider.serversList.length) : const EdgeInsets.symmetric(vertical: 8, horizontal: 16), child: Column( children: [ Padding( padding: const EdgeInsets.all(16), - child: topRow(widget.server, widget.index), + child: _TopRow(server: widget.server, index: widget.index) ), Padding( padding: const EdgeInsets.only( left: 8, right: 8, bottom: 16 ), - child: bottomRow(widget.server, widget.index), + child: _BottomRow( + server: widget.server, + connectToServer: (s) => connectToServer(context: context, server: s), + openServerModal: (s) => openServerModal(context: context, server: s, width: width), + setDefaultServer: (s) => setDefaultServer(context: context, server: s), + showDeleteModal: (s) => showDeleteModal(context: context, server: s), + ) ) ], ), ), ); } +} + +class _LeadingIcon extends StatelessWidget { + final Server server; + + const _LeadingIcon({ + required this.server, + }); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + + if (server.defaultServer == true) { + return Stack( + alignment: Alignment.center, + children: [ + Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? statusProvider.serverStatus != null + ? Colors.green + : Colors.orange + : null, + ), + SizedBox( + width: 25, + height: 25, + child: Stack( + alignment: Alignment.bottomRight, + children: [ + Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(20) + ), + child: Icon( + Icons.star, + color: Theme.of(context).colorScheme.onPrimaryContainer, + size: 10, + ), + ), + ], + ), + ) + ], + ); + } + else { + return Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? statusProvider.serverStatus != null + ? Colors.green + : Colors.orange + : null, + ); + } + } +} + +class _TopRow extends StatelessWidget { + final Server server; + final int index; + + const _TopRow({ + required this.server, + required this.index, + }); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 16), + child: _LeadingIcon(server: server), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", + textAlign: TextAlign.left, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Column( + children: [ + const SizedBox(height: 3), + Text( + server.name, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ) + ], + ), + ), + ], + ), + ), + ], + ); + } +} + +class _BottomRow extends StatelessWidget { + final Server server; + final void Function(Server) setDefaultServer; + final void Function(Server) openServerModal; + final void Function(Server) showDeleteModal; + final void Function(Server) connectToServer; + + const _BottomRow({ + required this.server, + required this.setDefaultServer, + required this.openServerModal, + required this.showDeleteModal, + required this.connectToServer, + }); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + PopupMenuButton( + itemBuilder: (context) => [ + PopupMenuItem( + enabled: server.defaultServer == false + ? true + : false, + onTap: server.defaultServer == false + ? (() => setDefaultServer(server)) + : null, + child: SizedBox( + child: Row( + children: [ + const Icon(Icons.star), + const SizedBox(width: 15), + Text( + server.defaultServer == true + ? AppLocalizations.of(context)!.defaultConnection + : AppLocalizations.of(context)!.setDefault, + ) + ], + ), + ) + ), + PopupMenuItem( + onTap: (() => openServerModal(server)), + child: Row( + children: [ + const Icon(Icons.edit), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.edit) + ], + ) + ), + PopupMenuItem( + onTap: (() => showDeleteModal(server)), + child: Row( + children: [ + const Icon(Icons.delete), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.delete) + ], + ) + ), + ] + ), + SizedBox( + child: serversProvider.selectedServer != null && + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null && + serversProvider.selectedServer?.id == server.id + ? Padding( + padding: const EdgeInsets.only(right: 16), + child: Row( + children: [ + Icon( + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null + ? Icons.check + : Icons.warning, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null + ? Colors.green + : Colors.orange, + ), + const SizedBox(width: 10), + Text( + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null + ? AppLocalizations.of(context)!.connected + : AppLocalizations.of(context)!.selectedDisconnected, + style: TextStyle( + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null + ? Colors.green + : Colors.orange, + fontWeight: FontWeight.w500 + ), + ) + ], + ), + ) + : Container( + margin: const EdgeInsets.only(right: 10), + child: FilledButton.icon( + icon: const Icon(Icons.login), + onPressed: () => connectToServer(server), + label: Text(AppLocalizations.of(context)!.connect), + ), + ), + ) + ], + ) + ], + ); + } } \ No newline at end of file From c2af933eb507aedc4b1cb1d50e306c958e2ca990 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 15:00:35 +0100 Subject: [PATCH 394/676] Removed unused import --- lib/widgets/servers_list/servers_tile_item.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index 61c2a64..bf28ade 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -7,7 +7,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/servers_list/server_tile_functions.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -33,8 +32,6 @@ class _ServersTileItemState extends State with SingleTickerProv @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); - final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; From 34bff2f506b99c9fb4d420a8940d4a266ceda3a7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 15:16:20 +0100 Subject: [PATCH 395/676] Improved server version check --- lib/classes/process_modal.dart | 14 +++----- lib/functions/clear_dns_cache.dart | 2 +- lib/providers/status_provider.dart | 6 ++-- lib/screens/clients/added_list.dart | 4 +-- lib/screens/clients/fab.dart | 2 +- lib/screens/clients/search_clients.dart | 4 +-- lib/screens/filters/add_button.dart | 4 +-- .../filters/details/list_details_screen.dart | 4 +-- lib/screens/filters/filters.dart | 8 ++--- lib/screens/filters/list_options_menu.dart | 2 +- .../modals/blocked_services_screen.dart | 2 +- .../filters/selection/selection_screen.dart | 4 +-- .../logs/details/log_details_screen.dart | 2 +- lib/screens/logs/logs_list_appbar.dart | 4 +-- .../access_settings/clients_list.dart | 4 +-- lib/screens/settings/dhcp/dhcp.dart | 6 ++-- lib/screens/settings/dhcp/dhcp_leases.dart | 4 +-- lib/screens/settings/dns/bootstrap_dns.dart | 2 +- lib/screens/settings/dns/cache_config.dart | 2 +- .../settings/dns/dns_server_settings.dart | 2 +- .../settings/dns/private_reverse_servers.dart | 2 +- lib/screens/settings/dns/upstream_dns.dart | 2 +- .../settings/dns_rewrites/dns_rewrites.dart | 6 ++-- .../settings/encryption/encryption.dart | 2 +- .../settings/safe_search_settings.dart | 2 +- .../settings/update_server/update.dart | 2 +- lib/widgets/domain_options.dart | 2 +- .../servers_list/server_tile_functions.dart | 32 +++++++++++++++++-- .../servers_list/servers_list_item.dart | 2 +- 29 files changed, 77 insertions(+), 57 deletions(-) diff --git a/lib/classes/process_modal.dart b/lib/classes/process_modal.dart index 6febebb..ac3db92 100644 --- a/lib/classes/process_modal.dart +++ b/lib/classes/process_modal.dart @@ -1,20 +1,14 @@ +import 'package:adguard_home_manager/config/globals.dart'; import 'package:flutter/material.dart'; import 'package:adguard_home_manager/widgets/process_dialog.dart'; class ProcessModal { - late BuildContext context; - - ProcessModal({ - required this.context - }); - void open(String message) async { await Future.delayed(const Duration(seconds: 0), () => { showDialog( - context: context, - builder: (c) { - context = c; + context: globalNavigatorKey.currentContext!, + builder: (ctx) { return ProcessDialog( message: message, ); @@ -26,6 +20,6 @@ class ProcessModal { } void close() { - Navigator.pop(context); + Navigator.pop(globalNavigatorKey.currentContext!); } } \ No newline at end of file diff --git a/lib/functions/clear_dns_cache.dart b/lib/functions/clear_dns_cache.dart index d0b44cd..4a6fe53 100644 --- a/lib/functions/clear_dns_cache.dart +++ b/lib/functions/clear_dns_cache.dart @@ -12,7 +12,7 @@ import 'package:adguard_home_manager/models/server.dart'; Future clearDnsCache(BuildContext context, Server server) async { final serversProvider = Provider.of(context, listen: false); - final ProcessModal processModal = ProcessModal(context: context); + final ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.clearingDnsCache); final result = await serversProvider.apiClient2!.resetDnsCache(); diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 5fba2dd..0c519f8 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -237,7 +237,8 @@ class StatusProvider with ChangeNotifier { } Future getServerStatus({ - bool? withLoadingIndicator + bool? withLoadingIndicator, + bool? overrideCheckServerVersion }) async { if (withLoadingIndicator == true) { _loadStatus = LoadStatus.loading; @@ -258,7 +259,7 @@ class StatusProvider with ChangeNotifier { referenceVersion: MinimumServerVersion.stable, referenceVersionBeta: MinimumServerVersion.beta ); - if (validVersion == false) { + if (validVersion == false && overrideCheckServerVersion != true) { showDialog( context: globalNavigatorKey.currentContext!, builder: (ctx) => UnsupportedVersionModal( @@ -269,7 +270,6 @@ class StatusProvider with ChangeNotifier { ) ); } - return true; } else { diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 2c93a04..124f32c 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -75,7 +75,7 @@ class _AddedListState extends State { final width = MediaQuery.of(context).size.width; void confirmEditClient(Client client) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingClient); final result = await clientsProvider.editClient(client); @@ -99,7 +99,7 @@ class _AddedListState extends State { } void deleteClient(Client client) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.removingClient); final result = await clientsProvider.deleteClient(client); diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index ce291c2..64fd098 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -25,7 +25,7 @@ class ClientsFab extends StatelessWidget { final width = MediaQuery.of(context).size.width; void confirmAddClient(Client client) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingClient); final result = await clientsProvider.addClient(client); diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index bbc330c..895f458 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -86,7 +86,7 @@ class _SearchClientsState extends State { final width = MediaQuery.of(context).size.width; void deleteClient(Client client) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.removingClient); final result = await clientsProvider.deleteClient(client); @@ -110,7 +110,7 @@ class _SearchClientsState extends State { } void confirmEditClient(Client client) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingClient); final result = await clientsProvider.editClient(client); diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index fbab84c..7dd4d8c 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -32,7 +32,7 @@ class AddFiltersButton extends StatelessWidget { final width = MediaQuery.of(context).size.width; void confirmAddRule(String rule) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingRule); final result = await filteringProvider.addCustomRule(rule); @@ -83,7 +83,7 @@ class AddFiltersButton extends StatelessWidget { } void confirmAddList({required String name, required String url, required String type}) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingList); final result = await filteringProvider.addList(name: name, url: url, type: type); diff --git a/lib/screens/filters/details/list_details_screen.dart b/lib/screens/filters/details/list_details_screen.dart index 8c8199a..b5e305c 100644 --- a/lib/screens/filters/details/list_details_screen.dart +++ b/lib/screens/filters/details/list_details_screen.dart @@ -81,7 +81,7 @@ class _ListDetailsScreenState extends State { required FilteringListActions action, required Filter filterList, }) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open( action == FilteringListActions.edit ? AppLocalizations.of(context)!.savingList @@ -249,7 +249,7 @@ class _ListDetailsScreenState extends State { context: context, builder: (c) => DeleteListModal( onConfirm: () async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.deletingList); final result = await filteringProvider.deleteList( listUrl: list!.url, diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 7953b81..c0a7e20 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -51,7 +51,7 @@ class _FiltersState extends State { final width = MediaQuery.of(context).size.width; void updateLists() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.updatingLists); final result = await filteringProvider.updateLists(); if (!mounted) return; @@ -97,7 +97,7 @@ class _FiltersState extends State { } void enableDisableFiltering() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open( statusProvider.serverStatus!.filteringEnabled == true ? AppLocalizations.of(context)!.disableFiltering @@ -125,7 +125,7 @@ class _FiltersState extends State { } void setUpdateFrequency(int value) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.changingUpdateFrequency); final result = await filteringProvider.changeUpdateFrequency(value); @@ -155,7 +155,7 @@ class _FiltersState extends State { } void removeCustomRule(String rule) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.deletingRule); final result = await filteringProvider.removeCustomRule(rule); diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 853eb7c..2e47d36 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -40,7 +40,7 @@ class ListOptionsMenu extends StatelessWidget { final width = MediaQuery.of(context).size.width; void enableDisable() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open( list.enabled == true ? AppLocalizations.of(context)!.disablingList diff --git a/lib/screens/filters/modals/blocked_services_screen.dart b/lib/screens/filters/modals/blocked_services_screen.dart index cefdda5..6169d0b 100644 --- a/lib/screens/filters/modals/blocked_services_screen.dart +++ b/lib/screens/filters/modals/blocked_services_screen.dart @@ -60,7 +60,7 @@ class _BlockedServicesScreenStateWidget extends State { } void updateBlockedServices() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.updating); final result = await filteringProvider.updateBlockedServices(values); diff --git a/lib/screens/filters/selection/selection_screen.dart b/lib/screens/filters/selection/selection_screen.dart index 108544e..cde1f1d 100644 --- a/lib/screens/filters/selection/selection_screen.dart +++ b/lib/screens/filters/selection/selection_screen.dart @@ -76,7 +76,7 @@ class _SelectionScreenState extends State with TickerProviderSt selectedBlacklists: _selectedBlacklists, onDelete: () async { Navigator.pop(context); - final processModal = ProcessModal(context: context); + final processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.processingLists); final result = await filteringProvider.enableDisableMultipleLists( blacklists: _selectedBlacklists, @@ -107,7 +107,7 @@ class _SelectionScreenState extends State with TickerProviderSt selectedBlacklists: _selectedBlacklists, onDelete: () async { Navigator.pop(context); - final processModal = ProcessModal(context: context); + final processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.deletingLists); final result = await filteringProvider.deleteMultipleLists( blacklists: _selectedBlacklists, diff --git a/lib/screens/logs/details/log_details_screen.dart b/lib/screens/logs/details/log_details_screen.dart index 510c2e2..ff88eaa 100644 --- a/lib/screens/logs/details/log_details_screen.dart +++ b/lib/screens/logs/details/log_details_screen.dart @@ -59,7 +59,7 @@ class LogDetailsScreen extends StatelessWidget { } void blockUnblock(String domain, String newStatus) async { - final ProcessModal processModal = ProcessModal(context: context); + final ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingUserFilters); final rules = await statusProvider.blockUnblockDomain( diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index d2f0ec9..f467d26 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -39,7 +39,7 @@ class LogsListAppBar extends StatelessWidget { final width = MediaQuery.of(context).size.width; void updateConfig(Map data) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.updatingSettings); final result = await serversProvider.apiClient2!.updateQueryLogParameters(data: data); @@ -63,7 +63,7 @@ class LogsListAppBar extends StatelessWidget { } void clearQueries() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.updatingSettings); final result = await serversProvider.apiClient2!.clearLogs(); diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 4dedc24..0b83a4d 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -96,7 +96,7 @@ class _ClientsListState extends State { body['blocked_hosts'] = body['blocked_hosts']!.where((c) => c != client).toList(); } - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.removingClient); final result = await clientsProvider.removeClientList(client, type); @@ -129,7 +129,7 @@ class _ClientsListState extends State { } void confirmAddItem(String item, AccessSettingsList type) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.removingClient); final result = await clientsProvider.addClientList(item, type); diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index dbb4a9a..84a4e76 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -192,7 +192,7 @@ class _DhcpScreenState extends State { final width = MediaQuery.of(context).size.width; void saveSettings() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingSettings); final result = await serversProvider.apiClient2!.saveDhcpConfig( data: { @@ -232,7 +232,7 @@ class _DhcpScreenState extends State { void restoreConfig() async { Future.delayed(const Duration(seconds: 0), () async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.restoringConfig); final result = await serversProvider.apiClient2!.resetDhcpConfig(); if (!mounted) return; @@ -257,7 +257,7 @@ class _DhcpScreenState extends State { void restoreLeases() async { Future.delayed(const Duration(seconds: 0), () async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.restoringLeases); final result = await serversProvider.apiClient2!.restoreAllLeases(); diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index d6f5051..91bd1cf 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -35,7 +35,7 @@ class DhcpLeases extends StatelessWidget { final width = MediaQuery.of(context).size.width; void deleteLease(Lease lease) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.deleting); final result = await dhcpProvider.deleteLease(lease); @@ -59,7 +59,7 @@ class DhcpLeases extends StatelessWidget { } void createLease(Lease lease) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.creating); final result = await dhcpProvider.createLease(lease); diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index a439367..2ae3f4f 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -70,7 +70,7 @@ class _BootstrapDnsScreenState extends State { final width = MediaQuery.of(context).size.width; void saveData() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingConfig); final result = await dnsProvider.saveBootstrapDnsConfig({ diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index 13d1836..7f6f63a 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -73,7 +73,7 @@ class _CacheConfigDnsScreenState extends State { final width = MediaQuery.of(context).size.width; void saveData() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingConfig); final result = await dnsProvider.saveCacheCacheConfig({ diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index 6602af0..777821f 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -103,7 +103,7 @@ class _DnsServerSettingsScreenState extends State { final width = MediaQuery.of(context).size.width; void saveData() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingConfig); final result = await dnsProvider.saveDnsServerConfig({ diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index 98b1cb9..f91c593 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -94,7 +94,7 @@ class _PrivateReverseDnsServersScreenState extends State { } void saveData() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingConfig); final result = await dnsProvider.saveUpstreamDnsConfig({ diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index cd4c8bd..236b107 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -59,7 +59,7 @@ class _DnsRewritesScreenState extends State { final width = MediaQuery.of(context).size.width; void deleteDnsRewrite(RewriteRules rule) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.deleting); final result = await rewriteRulesProvider.deleteDnsRewrite(rule); @@ -83,7 +83,7 @@ class _DnsRewritesScreenState extends State { } void addDnsRewrite(RewriteRules rule, _) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingRewrite); final result = await rewriteRulesProvider.addDnsRewrite(rule); @@ -107,7 +107,7 @@ class _DnsRewritesScreenState extends State { } void updateRewriteRule(RewriteRules newRule, RewriteRules? previousRule) async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.updatingRule); final result = await rewriteRulesProvider.editDnsRewrite(newRule, previousRule!); diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index fc38216..63d9620 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -201,7 +201,7 @@ class _EncryptionSettingsState extends State { final width = MediaQuery.of(context).size.width; void saveData() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingConfig); final result = await serversProvider.apiClient2!.saveEncryptionSettings( diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 9ef8359..4f6713a 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -74,7 +74,7 @@ class _SafeSearchSettingsScreenState extends State { final width = MediaQuery.of(context).size.width; void saveConfig() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingSettings); final result = await statusProvider.updateSafeSearchConfig({ diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index f1c63a8..dd91f6e 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -32,7 +32,7 @@ class UpdateScreen extends StatelessWidget { } void update() async { - ProcessModal processModal = ProcessModal(context: context); + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.requestingUpdate); final result = await serversProvider.apiClient2!.requestUpdateServer(); diff --git a/lib/widgets/domain_options.dart b/lib/widgets/domain_options.dart index 58409d9..3c4bb79 100644 --- a/lib/widgets/domain_options.dart +++ b/lib/widgets/domain_options.dart @@ -39,7 +39,7 @@ class DomainOptions extends StatelessWidget { final appConfigProvider = Provider.of(context); void blockUnblock(String domain, String newStatus) async { - final ProcessModal processModal = ProcessModal(context: context); + final ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingUserFilters); final rules = await statusProvider.blockUnblockDomain( diff --git a/lib/widgets/servers_list/server_tile_functions.dart b/lib/widgets/servers_list/server_tile_functions.dart index e3fa4d6..ec3c92e 100644 --- a/lib/widgets/servers_list/server_tile_functions.dart +++ b/lib/widgets/servers_list/server_tile_functions.dart @@ -2,9 +2,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/add_server/unsupported_version_modal.dart'; import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; +import 'package:adguard_home_manager/config/globals.dart'; +import 'package:adguard_home_manager/config/minimum_server_version.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/server_status.dart'; @@ -71,7 +75,7 @@ void connectToServer({ required BuildContext context, required Server server }) async { - final ProcessModal process = ProcessModal(context: context); + final ProcessModal process = ProcessModal(); process.open(AppLocalizations.of(context)!.connecting); final result = server.runningOnHa == true @@ -84,13 +88,35 @@ void connectToServer({ final ApiClientV2 apiClient2 = ApiClientV2(server: server); serversProvider.setApiClient2(apiClient2); - serversProvider.setSelectedServer(server); statusProvider.setServerStatusLoad(LoadStatus.loading); final serverStatus = await apiClient2.getServerStatus(); if (serverStatus.successful == true) { + final status = serverStatus.content as ServerStatus; + + // Check if server version is supported + final validVersion = serverVersionIsAhead( + currentVersion: status.serverVersion, + referenceVersion: MinimumServerVersion.stable, + referenceVersionBeta: MinimumServerVersion.beta + ); + if (validVersion == false) { + process.close(); + showDialog( + context: globalNavigatorKey.currentContext!, + builder: (ctx) => UnsupportedVersionModal( + serverVersion: status.serverVersion, + onClose: () { + serversProvider.setSelectedServer(null); + } + ) + ); + return; + } + + serversProvider.setSelectedServer(server); statusProvider.setServerStatusData( - data: serverStatus.content as ServerStatus + data: status ); serversProvider.checkServerUpdatesAvailable( server: server, diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index e67b436..d3149c1 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -96,7 +96,7 @@ class _ServersListItemState extends State with SingleTickerProv } void connectToServer(Server server) async { - final ProcessModal process = ProcessModal(context: context); + final ProcessModal process = ProcessModal(); process.open(AppLocalizations.of(context)!.connecting); final result = server.runningOnHa == true From 802f2ca3289afd1138915ec0847d18cda1e6e547 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 20 Nov 2023 15:22:27 +0100 Subject: [PATCH 396/676] Updated turkish translation --- lib/l10n/app_tr.arb | 67 ++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 27b066c..1fdb739 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -65,7 +65,7 @@ "theme": "Tema", "light": "Aydınlık", "dark": "Karanlık", - "systemDefined": "Sistemle uyumlu olsun", + "systemDefined": "Sistemle uyumlu hale getir", "close": "Kapat", "connectedTo": "Bağlandı:", "selectedServer": "Seçili sunucu:", @@ -78,7 +78,7 @@ "helperPath": "Ters proxy kullanıyorsanız", "aboutApp": "Uygulama hakkında", "appVersion": "Uygulama sürümü", - "createdBy": "Yapımcı", + "createdBy": "Geliştirici", "clients": "İstemciler", "allowed": "İzin verildi", "blocked": "Engellendi", @@ -102,9 +102,9 @@ "copyLogsClipboard": "Günlükleri panoya kopyala", "logsCopiedClipboard": "Günlükler panoya kopyalandı", "advancedSettings": "Gelişmiş ayarlar", - "dontCheckCertificate": "SSL sertifikası kontrol edilmesin", + "dontCheckCertificate": "SSL sertifikasını asla kontrol etme", "dontCheckCertificateDescription": "Sunucunun SSL sertifikası doğrulamasını geçersiz kılar", - "advancedSetupDescription": "Gelişmiş seçenekler", + "advancedSetupDescription": "Gelişmiş seçenekleri yönet", "settingsUpdatedSuccessfully": "Ayarlar başarıyla güncellendi.", "cannotUpdateSettings": "Ayarlar güncellenemiyor.", "restartAppTakeEffect": "Uygulamayı yeniden başlat", @@ -135,7 +135,7 @@ "blocklist": "Engelleme Listesi", "request": "İstek", "domain": "Alan adı", - "type": "Tür", + "type": "Tip", "clas": "Sınıf", "response": "Yanıt", "dnsServer": "DNS sunucusu", @@ -174,9 +174,9 @@ "malwarePhishingBlocked": "Engellenen zararlı içerikler", "blockedAdultWebsites": "Engellenen yetişkin içerikler", "generalSettings": "Genel ayarlar", - "generalSettingsDescription": "Çeşitli farklı ayarlar", + "generalSettingsDescription": "Çeşitli farklı ayarları yönet", "hideZeroValues": "Sıfır değerlerini gizle", - "hideZeroValuesDescription": "Ana ekranda, değeri sıfır olan blokları gizle", + "hideZeroValuesDescription": "Ana ekranda, değeri sıfır olan blokları gizler", "webAdminPanel": "Web yönetim paneli", "visitGooglePlay": "Google Play sayfasını ziyaret et", "gitHub": "Kaynak kodlarına GitHub'dan ulaşabilirsiniz", @@ -233,12 +233,12 @@ "noWhiteLists": "Beyaz listeler yok", "addWhitelist": "Beyaz liste ekle", "addBlacklist": "Kara liste ekle", - "urlNotValid": "URL Adresi geçerli değil", - "urlAbsolutePath": "URL adresi veya kesin dosya yolu", + "urlNotValid": "Bağlantı adresi geçerli değil", + "urlAbsolutePath": "Bağlantı adresi veya kesin dosya yolu", "addingList": "Liste ekleniyor...", "listAdded": "Liste başarıyla eklendi. Eklenen öğeler:", "listAlreadyAdded": "Liste zaten eklenmiş", - "listUrlInvalid": "Liste URL adresi geçersiz", + "listUrlInvalid": "Liste bağlantı adresi geçersiz", "listNotAdded": "Liste eklenemedi", "listDetails": "Liste detayları", "listType": "Liste türü", @@ -260,11 +260,11 @@ "deleteListMessage": "Bu listeyi silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.", "serverSettings": "Sunucu ayarları", "serverInformation": "Sunucu bilgisi", - "serverInformationDescription": "Sunucu bilgisi ve durumu", + "serverInformationDescription": "Sunucu bilgisi ve durumunu öğren", "loadingServerInfo": "Sunucu bilgisi yükleniyor...", "serverInfoNotLoaded": "Sunucu bilgisi yüklenemedi.", "dnsAddresses": "DNS adresleri", - "seeDnsAddresses": "DNS adreslerine bak", + "seeDnsAddresses": "DNS adreslerine göz at", "dnsPort": "DNS bağlantı noktası", "httpPort": "HTTP bağlantı noktası", "protectionEnabled": "Koruma etkin mi?", @@ -450,14 +450,14 @@ "enableReverseResolving": "İstemcilerin IP adreslerinin ters çözümlemesini etkinleştir", "enableReverseResolvingDescription": "İstemcilerin IP adreslerini karşılık gelen çözücülere PTR sorguları göndererek IP adreslerini tersine çözümleyerek (yerel istemciler için özel DNS sunucuları, genel IP adresine sahip istemciler için yukarı akış sunucuları) istemcilerin ana bilgisayar adlarını tersine çöz.", "dnsServerSettings": "AdGuard Home DNS sunucusu ayarları", - "limitRequestsSecond": "Saniye başına hız limiti", + "limitRequestsSecond": "Saniye başına sınırlama isteği", "valueNotNumber": "Değer bir sayı değil", "enableEdns": "EDNS istemci alt ağını etkinleştir", - "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı Seçeneği (ECS) ekleyin ve istemciler tarafından gönderilen değerleri sorgu günlüğüne kaydedin", + "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı Seçeneği (ECS) ekleyin ve istemciler tarafından gönderilen değerleri sorgu günlüğüne kaydedin.", "enableDnssec": "DNSSEC'i etkinleştir", - "enableDnssecDescription": "Giden DNS sorguları için DNSSEC özelliğini etkinleştir ve sonucu kontrol edin (DNSSEC etkinleştirilmiş bir çözümleyici gerekli)", + "enableDnssecDescription": "Giden DNS sorguları için DNSSEC özelliğini etkinleştir ve sonucu kontrol edin.(DNSSEC etkinleştirilmiş bir çözümleyici gerekli)", "disableResolvingIpv6": "IPv6 adreslerinin çözümlenmesini devre dışı bırak", - "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını bırakın (AAAA yazın) ve HTTPS yanıtlarından IPv6 ipuçlarını kaldırın", + "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını bırakın (AAAA yazın) ve HTTPS yanıtlarından IPv6 ipuçlarını kaldırın.", "blockingMode": "Engelleme modu", "defaultMode": "Varsayılan", "defaultDescription": "Reklam engelleme tarzı bir kural tarafından engellendiğinde sıfır IP adresi ile yanıt verin (A için 0.0.0.0; :: AAAA için) /etc/hosts tarzı bir kural tarafından engellendiğinde kuralda belirtilen IP adresi ile yanıt verin", @@ -471,9 +471,9 @@ "cacheSize": "Önbellek boyutu", "inBytes": "Bayt olarak", "overrideMinimumTtl": "Minimum kullanım süresini geçersiz kıl", - "overrideMinimumTtlDescription": "DNS yanıtlarını önbelleğe alırken üst sunucudan alınan minimum kullanım süresi değerini ayarlayın (saniye olarak).", + "overrideMinimumTtlDescription": "DNS yanıtlarını önbelleğe alırken üst sunucudan alınan minimum kullanım süresi değerini ayarlayın (saniye olarak)", "overrideMaximumTtl": "Maksimum kullanım süresini geçersiz kıl", - "overrideMaximumTtlDescription": "DNS önbelleğindeki girişler için maksimum kullanım süresi değerini ayarlayın (saniye olarak).", + "overrideMaximumTtlDescription": "DNS önbelleğindeki girişler için maksimum kullanım süresi değerini ayarlayın (saniye olarak)", "optimisticCaching": "İyimser önbelleğe alma", "optimisticCachingDescription": "Girişlerin süresi dolmuş olsa bile Adguard Home'un önbellekten yanıt vermesini sağlayın ve aynı zamanda bunları yenilemeye çalışın.", "loadingDnsConfig": "DNS yapılandırması yükleniyor...", @@ -515,7 +515,7 @@ "pasteCertificateContent": "Sertifika içeriğini yapıştır", "certificatePath": "Sertifika dosya yolu", "certificateContent": "Sertifika içeriği", - "privateKey": "Özel anahtar", + "privateKey": "Özel anahtarlar", "privateKeyFile": "Özel anahtar dosyası belirle", "pastePrivateKey": "Özel anahtar içeriğini yapıştır", "usePreviousKey": "Önceden kaydedilmiş anahtarı kullan", @@ -583,7 +583,7 @@ "dnsCacheCleared": "DNS önbelleği başarıyla temizlendi", "clearingDnsCache": "Önbellek temizleniyor...", "dnsCacheNotCleared": "DNS önbelleği temizlenemedi", - "clientsSelected": "Seçilen istemciler", + "clientsSelected": "Seçilmiş istemci", "invalidDomain": "Geçersiz alan adı", "loadingBlockedServicesList": "Engellenen hizmetler listesi yükleniyor...", "blockedServicesListNotLoaded": "Engellenen hizmetler listesi yüklenemedi", @@ -618,18 +618,18 @@ "copiedClipboard": "Panoya kopyalandı", "seeDetails": "Detayları gör", "listNotAvailable": "Liste mevcut değil", - "copyListUrl": "Liste URL adresini kopyala", - "listUrlCopied": "Panoya kopyalanan URL adresini listeleyin", + "copyListUrl": "Liste bağlantısını kopyala", + "listUrlCopied": "Panoya kopyalanan bağlantı adresini listeleyin", "unsupportedVersion": "Desteklenmeyen sürüm", "unsupprtedVersionMessage": "Sunucu sürümünüz {version} için destek garantisi verilmiyor. Bu uygulamanın bu sunucu sürümüyle çalışmasında bazı sorunlar olabilir. AdGuard Home Yöneticisi, AdGuard Home sunucunun kararlı sürümleriyle çalışacak şekilde tasarlanmıştır. Alfa ve beta sürümleriyle çalışabilir, ancak uyumluluk garanti edilmez ve uygulama bu sürümlerle çalışırken bazı sorunlar yaşayabilir.", "iUnderstand": "Anladım", "appUpdates": "Uygulama güncellemeleri", "usingLatestVersion": "En son sürümü kullanıyorsunuz", "ipLogs": "Günlüklerdeki IP", - "ipLogsDescription": "Günlüklerde istemci adı yerine her zaman IP adresini göster", + "ipLogsDescription": "Günlükler listesinde istemci adı yerine IP adresini göster", "application": "Uygulama", "combinedChart": "Birleştirilmiş grafik", - "combinedChartDescription": "Tüm grafikleri bir araya getir", + "combinedChartDescription": "Tüm grafikleri bir araya getirir", "statistics": "İstatistikler", "errorLoadFilters": "Filtreler yüklenirken hata oluştu.", "clientRemovedSuccessfully": "İstemci başarıyla kaldırıldı.", @@ -669,5 +669,22 @@ "showTopItemsChart": "Öne çıkan öğeler grafiği", "showTopItemsChartDescription": "Varsayılan olarak öne çıkan öğeler bölümünde halka grafiğini gösterir. Sadece mobil görünümü etkiler.", "openMenu": "Menüyü genişlet", - "closeMenu": "Menüyü daralt" + "closeMenu": "Menüyü daralt", + "openListUrl": "Liste bağlantısını aç", + "selectionMode": "Seçim modu", + "enableDisableSelected": "Seçili öğeleri etkinleştir veya devre dışı bırak", + "deleteSelected": "Seçili öğeleri sil", + "deleteSelectedLists": "Seçili listeleri sil", + "allSelectedListsDeletedSuccessfully": "Seçilen tüm listeler başarıyla silindi.", + "deletionResult": "Silinme sonucu", + "deletingLists": "Listeler siliniyor...", + "failedElements": "Başarısız öğeler", + "processingLists": "Listeler işleniyor...", + "enableDisableResult": "Sonucu etkinleştir veya devre dışı bırak", + "selectedListsEnabledDisabledSuccessfully": "Seçilen tüm listeler başarıyla etkinleştirildi veya devre dışı bırakıldı", + "sslWarning": "Kendinden imzalı bir sertifika ile HTTPS bağlantısı kullanıyorsanız, Ayarlar > Gelişmiş ayarlar bölümünde \"SSL sertifikasını kontrol etme\" seçeneğini etkinleştirdiğinizden emin olun.", + "unsupportedServerVersion": "Desteklenmeyen sunucu sürümü", + "unsupportedServerVersionMessage": "AdGuard Home sunucu sürümünüz çok eski ve AdGuard Home Manager tarafından desteklenmiyor. Bu uygulamayı kullanmak için AdGuard Home sunucunuzu daha yeni bir sürüme yükseltmeniz gerekecektir.", + "yourVersion": "Yüklü sürüm: {version}", + "minimumRequiredVersion": "Gerekli minimum sürüm: {version}" } From ed9293fb70c61119eec1a39ad07aa136511ff9e6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Nov 2023 11:10:39 +0100 Subject: [PATCH 397/676] Small improvements and refactor --- devtools_options.yaml | 1 + .../filters/selection/selection_screen.dart | 27 +- .../servers_list/servers_list_item.dart | 555 ++++++++---------- 3 files changed, 274 insertions(+), 309 deletions(-) create mode 100644 devtools_options.yaml diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..7e7e7f6 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1 @@ +extensions: diff --git a/lib/screens/filters/selection/selection_screen.dart b/lib/screens/filters/selection/selection_screen.dart index cde1f1d..11539b2 100644 --- a/lib/screens/filters/selection/selection_screen.dart +++ b/lib/screens/filters/selection/selection_screen.dart @@ -339,19 +339,28 @@ class _Tab extends StatelessWidget { Text(text), const SizedBox(width: 8), Container( - width: 18, - height: 18, + height: 22, + padding: const EdgeInsets.symmetric( + horizontal: 2 + ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Theme.of(context).colorScheme.primaryContainer ), - child: Text( - quantity.toString(), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w700, - color: Theme.of(context).colorScheme.onPrimaryContainer + child: ConstrainedBox( + constraints: const BoxConstraints( + minWidth: 18 + ), + child: Center( + child: Text( + quantity.toString(), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + color: Theme.of(context).colorScheme.onPrimaryContainer + ), + ), ), ), ) diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index d3149c1..47ca6fe 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -5,18 +5,9 @@ import 'package:expandable/expandable.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; -import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; +import 'package:adguard_home_manager/widgets/servers_list/server_tile_functions.dart'; -import 'package:adguard_home_manager/models/server_status.dart'; -import 'package:adguard_home_manager/services/api_client.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/models/app_log.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -27,12 +18,12 @@ class ServersListItem extends StatefulWidget { final void Function(int) onChange; const ServersListItem({ - Key? key, + super.key, required this.expandableController, required this.server, required this.index, required this.onChange - }) : super(key: key); + }); @override State createState() => _ServersListItemState(); @@ -71,293 +62,8 @@ class _ServersListItemState extends State with SingleTickerProv @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - final width = MediaQuery.of(context).size.width; - void showDeleteModal(Server server) async { - await Future.delayed(const Duration(seconds: 0), () => { - showDialog( - context: context, - builder: (context) => DeleteModal( - serverToDelete: server, - ), - barrierDismissible: false - ) - }); - } - - void openServerModal({Server? server}) async { - await Future.delayed(const Duration(seconds: 0), (() => { - openServerFormModal(context: context, width: width, server: server) - })); - } - - void connectToServer(Server server) async { - final ProcessModal process = ProcessModal(); - process.open(AppLocalizations.of(context)!.connecting); - - final result = server.runningOnHa == true - ? await loginHA(server) - : await login(server); - - if (result['result'] == 'success') { - final ApiClientV2 apiClient2 = ApiClientV2(server: server); - serversProvider.setApiClient2(apiClient2); - serversProvider.setSelectedServer(server); - - statusProvider.setServerStatusLoad(LoadStatus.loading); - final serverStatus = await apiClient2.getServerStatus(); - if (serverStatus.successful == true) { - statusProvider.setServerStatusData( - data: serverStatus.content as ServerStatus - ); - serversProvider.checkServerUpdatesAvailable( - server: server, - ); - statusProvider.setServerStatusLoad(LoadStatus.loaded); - } - - process.close(); - } - else { - process.close(); - appConfigProvider.addLog(result['log']); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.cannotConnect, - color: Colors.red - ); - } - } - - void setDefaultServer(Server server) async { - final result = await serversProvider.setDefaultServer(server); - if (result == null) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, - color: Colors.green - ); - } - else { - appConfigProvider.addLog( - AppLog( - type: 'set_default_server', - dateTime: DateTime.now(), - message: result.toString() - ) - ); - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionDefaultFailed, - color: Colors.red - ); - } - } - - Widget leadingIcon(Server server) { - if (server.defaultServer == true) { - return Stack( - alignment: Alignment.center, - children: [ - Icon( - Icons.storage_rounded, - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? statusProvider.serverStatus != null - ? Colors.green - : Colors.orange - : null, - ), - SizedBox( - width: 25, - height: 25, - child: Stack( - alignment: Alignment.bottomRight, - children: [ - Container( - padding: const EdgeInsets.all(1), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primaryContainer, - borderRadius: BorderRadius.circular(20) - ), - child: Icon( - Icons.star, - color: Theme.of(context).colorScheme.onPrimaryContainer, - size: 10, - ), - ), - ], - ), - ) - ], - ); - } - else { - return Icon( - Icons.storage_rounded, - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? statusProvider.serverStatus != null - ? Colors.green - : Colors.orange - : null, - ); - } - } - - Widget topRow(Server server, int index) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Row( - children: [ - Container( - margin: const EdgeInsets.only(right: 16), - child: leadingIcon(server), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Column( - children: [ - const SizedBox(height: 3), - Text( - server.name, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ) - ], - ) - ], - ), - ), - ], - ), - ), - RotationTransition( - turns: animation, - child: const Icon(Icons.keyboard_arrow_down_rounded), - ), - ], - ); - } - - Widget bottomRow(Server server, int index) { - return Column( - children: [ - const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - PopupMenuButton( - // color: Theme.of(context).dialogBackgroundColor, - itemBuilder: (context) => [ - PopupMenuItem( - enabled: server.defaultServer == false - ? true - : false, - onTap: server.defaultServer == false - ? (() => setDefaultServer(server)) - : null, - child: SizedBox( - child: Row( - children: [ - const Icon(Icons.star), - const SizedBox(width: 15), - Text( - server.defaultServer == true - ? AppLocalizations.of(context)!.defaultConnection - : AppLocalizations.of(context)!.setDefault, - ) - ], - ), - ) - ), - PopupMenuItem( - onTap: (() => openServerModal(server: server)), - child: Row( - children: [ - const Icon(Icons.edit), - const SizedBox(width: 15), - Text(AppLocalizations.of(context)!.edit) - ], - ) - ), - PopupMenuItem( - onTap: (() => showDeleteModal(server)), - child: Row( - children: [ - const Icon(Icons.delete), - const SizedBox(width: 15), - Text(AppLocalizations.of(context)!.delete) - ], - ) - ), - ] - ), - SizedBox( - child: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? Container( - margin: const EdgeInsets.only(right: 12), - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), - decoration: BoxDecoration( - color: statusProvider.serverStatus != null - ? Colors.green - : Colors.orange, - borderRadius: BorderRadius.circular(30) - ), - child: Row( - children: [ - Icon( - statusProvider.serverStatus != null - ? Icons.check - : Icons.warning, - color: Colors.white, - ), - const SizedBox(width: 10), - Text( - statusProvider.serverStatus != null - ? AppLocalizations.of(context)!.connected - : AppLocalizations.of(context)!.selectedDisconnected, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ) - ], - ), - ) - : Container( - margin: const EdgeInsets.only(right: 10), - child: TextButton( - onPressed: () => connectToServer(server), - child: Text(AppLocalizations.of(context)!.connect), - ), - ), - ) - ], - ) - ], - ); - } - return Container( decoration: BoxDecoration( border: Border( @@ -378,7 +84,7 @@ class _ServersListItemState extends State with SingleTickerProv onTap: () => widget.onChange(widget.index), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: topRow(widget.server, widget.index), + child: _TopRow(server: widget.server, animation: animation) ), ), ), @@ -390,8 +96,14 @@ class _ServersListItemState extends State with SingleTickerProv padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Column( children: [ - topRow(widget.server, widget.index), - bottomRow(widget.server, widget.index) + _TopRow(server: widget.server, animation: animation), + _BottomRow( + server: widget.server, + connectToServer: (s) => connectToServer(context: context, server: s), + openServerModal: (s) => openServerModal(context: context, server: s, width: width), + setDefaultServer: (s) => setDefaultServer(context: context, server: s), + showDeleteModal: (s) => showDeleteModal(context: context, server: s), + ) ], ), ), @@ -403,4 +115,247 @@ class _ServersListItemState extends State with SingleTickerProv ), ); } +} + +class _TopRow extends StatelessWidget { + final Server server; + final Animation animation; + + const _TopRow({ + required this.server, + required this.animation, + }); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 16), + child: _LeadingIcon(server: server), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Column( + children: [ + const SizedBox(height: 3), + Text( + server.name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ) + ], + ), + ), + ], + ), + ), + RotationTransition( + turns: animation, + child: const Icon(Icons.keyboard_arrow_down_rounded), + ), + ], + ); + } +} + +class _LeadingIcon extends StatelessWidget { + final Server server; + + const _LeadingIcon({ + required this.server, + }); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + + if (server.defaultServer == true) { + return Stack( + alignment: Alignment.center, + children: [ + Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? statusProvider.serverStatus != null + ? Colors.green + : Colors.orange + : null, + ), + SizedBox( + width: 25, + height: 25, + child: Stack( + alignment: Alignment.bottomRight, + children: [ + Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(20) + ), + child: Icon( + Icons.star, + color: Theme.of(context).colorScheme.onPrimaryContainer, + size: 10, + ), + ), + ], + ), + ) + ], + ); + } + else { + return Icon( + Icons.storage_rounded, + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? statusProvider.serverStatus != null + ? Colors.green + : Colors.orange + : null, + ); + } + } +} + +class _BottomRow extends StatelessWidget { + final Server server; + final void Function(Server) setDefaultServer; + final void Function(Server) openServerModal; + final void Function(Server) showDeleteModal; + final void Function(Server) connectToServer; + + const _BottomRow({ + required this.server, + required this.setDefaultServer, + required this.openServerModal, + required this.showDeleteModal, + required this.connectToServer, + }); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + + return Column( + children: [ + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + PopupMenuButton( + // color: Theme.of(context).dialogBackgroundColor, + itemBuilder: (context) => [ + PopupMenuItem( + enabled: server.defaultServer == false + ? true + : false, + onTap: server.defaultServer == false + ? (() => setDefaultServer(server)) + : null, + child: SizedBox( + child: Row( + children: [ + const Icon(Icons.star), + const SizedBox(width: 15), + Text( + server.defaultServer == true + ? AppLocalizations.of(context)!.defaultConnection + : AppLocalizations.of(context)!.setDefault, + ) + ], + ), + ) + ), + PopupMenuItem( + onTap: (() => openServerModal(server)), + child: Row( + children: [ + const Icon(Icons.edit), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.edit) + ], + ) + ), + PopupMenuItem( + onTap: (() => showDeleteModal(server)), + child: Row( + children: [ + const Icon(Icons.delete), + const SizedBox(width: 15), + Text(AppLocalizations.of(context)!.delete) + ], + ) + ), + ] + ), + SizedBox( + child: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id + ? Container( + margin: const EdgeInsets.only(right: 12), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + decoration: BoxDecoration( + color: statusProvider.serverStatus != null + ? Colors.green + : Colors.orange, + borderRadius: BorderRadius.circular(30) + ), + child: Row( + children: [ + Icon( + statusProvider.serverStatus != null + ? Icons.check + : Icons.warning, + color: Colors.white, + ), + const SizedBox(width: 10), + Text( + statusProvider.serverStatus != null + ? AppLocalizations.of(context)!.connected + : AppLocalizations.of(context)!.selectedDisconnected, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w500 + ), + ) + ], + ), + ) + : Container( + margin: const EdgeInsets.only(right: 10), + child: TextButton( + onPressed: () => connectToServer(server), + child: Text(AppLocalizations.of(context)!.connect), + ), + ), + ) + ], + ) + ], + ); + } } \ No newline at end of file From 1ea1a016c128461dcb5694838265ed8e688bf8f1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Nov 2023 13:34:32 +0000 Subject: [PATCH 398/676] Updated Windows stuff --- windows/flutter/CMakeLists.txt | 7 ++++++- windows/innosetup_installer_builder.iss | 18 +++++++++--------- windows/runner/flutter_window.cpp | 5 +++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt index 930d207..903f489 100644 --- a/windows/flutter/CMakeLists.txt +++ b/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index b7a348d..92a4b72 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -37,15 +37,15 @@ Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl" Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked [Files] -Source: "..\build\windows\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\runner\Release\dynamic_color_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\runner\Release\window_size_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "..\build\windows\x64\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\dynamic_color_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\window_size_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index b25e363..955ee30 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -31,6 +31,11 @@ bool FlutterWindow::OnCreate() { this->Show(); }); + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } From 75376c1873691b6781c282e482baf2c394c76a58 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 01:05:18 +0100 Subject: [PATCH 399/676] Fixes and improvements --- lib/functions/check_app_updates.dart | 4 +- lib/providers/servers_provider.dart | 7 ++- .../clients/client/logs_list_client.dart | 47 +++++++------- lib/services/api_client.dart | 13 ++-- lib/services/external_requests.dart | 62 ++++++------------- lib/widgets/layout.dart | 2 + pubspec.lock | 2 +- pubspec.yaml | 1 + 8 files changed, 60 insertions(+), 78 deletions(-) diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart index 7ab8352..e002556 100644 --- a/lib/functions/check_app_updates.dart +++ b/lib/functions/check_app_updates.dart @@ -14,7 +14,7 @@ Future checkAppUpdates({ }) async { var result = isBeta ? await ExternalRequests.getReleasesGitHub() - : await ExternalRequests.getLatestReleaseGitHub(); + : await ExternalRequests.getReleaseData(); if (result.successful == true) { late GitHubRelease gitHubRelease; @@ -30,7 +30,7 @@ Future checkAppUpdates({ gitHubRelease: gitHubRelease, isBeta: isBeta ); - +print(update); if (update == true) { setUpdateAvailable(gitHubRelease); diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index a8f1003..2cc634a 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; +import 'package:adguard_home_manager/models/github_release.dart'; import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/services/external_requests.dart'; import 'package:adguard_home_manager/models/server.dart'; @@ -188,9 +189,9 @@ class ServersProvider with ChangeNotifier { final result = await client!.checkServerUpdates(); if (result.successful == true) { UpdateAvailableData data = UpdateAvailableData.fromJson(result.content); - final gitHubResult = await ExternalRequests.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); + final gitHubResult = await ExternalRequests.getReleaseData(releaseTag: data.newVersion ?? data.currentVersion); if (gitHubResult.successful == true) { - data.changelog = gitHubResult.content; + data.changelog = (gitHubResult.content as GitHubRelease).body; } setUpdateAvailableData(data); setUpdateAvailableLoadStatus(LoadStatus.loaded, true); @@ -262,7 +263,7 @@ class ServersProvider with ChangeNotifier { if (result.successful == true) { UpdateAvailableData data = UpdateAvailableData.fromJsonUpdate(result.content); if (data.currentVersion == data.newVersion) { - final gitHubResult = await ExternalRequests.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); + final gitHubResult = await ExternalRequests.getReleaseData(releaseTag: data.newVersion ?? data.currentVersion); if (gitHubResult.successful == true) { data.changelog = gitHubResult.content; } diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index 422c80c..bd4d2af 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -8,6 +8,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; import 'package:adguard_home_manager/screens/logs/details/log_details_screen.dart'; +import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -21,13 +22,13 @@ class LogsListClient extends StatefulWidget { final bool splitView; const LogsListClient({ - Key? key, + super.key, required this.ip, this.name, required this.serversProvider, required this.appConfigProvider, required this.splitView, - }) : super(key: key); + }); @override State createState() => _LogsListClientState(); @@ -74,32 +75,28 @@ class _LogsListClientState extends State { ) ); - final result = await cancelableRequest?.value; + final result = await cancelableRequest?.value as ApiResponse; + if (!mounted) return; - if (result != null) { - if (loadingMore != null && loadingMore == true && mounted) { - setState(() => isLoadingMore = false); - } + if (loadingMore != null && loadingMore == true && mounted) { + setState(() => isLoadingMore = false); + } - if (mounted) { - if (result['result'] == 'success') { - setState(() => offset = inOffset != null ? inOffset+logsQuantity : offset+logsQuantity); - if (loadingMore != null && loadingMore == true && logsData != null) { - LogsData newLogsData = result['data']; - newLogsData.data = [...logsData!.data, ...result['data'].data]; - setState(() => logsData = newLogsData); - } - else { - LogsData newLogsData = result['data']; - setState(() => logsData = newLogsData); - } - setState(() => loadStatus = 1); - } - else { - setState(() => loadStatus = 2); - widget.appConfigProvider.addLog(result['log']); - } + if (result.successful == true) { + setState(() => offset = inOffset != null ? inOffset+logsQuantity : offset+logsQuantity); + if (loadingMore != null && loadingMore == true && logsData != null) { + LogsData newLogsData = result.content; + newLogsData.data = [...logsData!.data, ...result.content.data]; + setState(() => logsData = newLogsData); } + else { + LogsData newLogsData = result.content; + setState(() => logsData = newLogsData); + } + setState(() => loadStatus = 1); + } + else { + setState(() => loadStatus = 2); } } diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index a957fc3..d8ef244 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -689,10 +689,15 @@ class ApiClientV2 { server: server, body: data, ); - return ApiResponse( - successful: result.successful, - content: result.body != null ? jsonDecode(result.body!) : null - ); + try { + return ApiResponse( + successful: result.successful, + content: result.body != null ? jsonDecode(result.body!) : null + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } } Future saveEncryptionSettings({ diff --git a/lib/services/external_requests.dart b/lib/services/external_requests.dart index b63b6fb..bd467fb 100644 --- a/lib/services/external_requests.dart +++ b/lib/services/external_requests.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'dart:io'; +import 'package:http/http.dart' as http; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:adguard_home_manager/models/github_release.dart'; @@ -8,72 +8,48 @@ import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/services/api_client.dart'; class ExternalRequests { - static Future getUpdateChangelog({ - required String releaseTag - }) async { - try { - HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse("${Urls.adGuardHomeReleasesTags}/$releaseTag")); - HttpClientResponse response = await request.close(); - String reply = await response.transform(utf8.decoder).join(); - httpClient.close(); - if (response.statusCode == 200) { - return ApiResponse( - successful: true, - content: jsonDecode(reply)['body'], - statusCode: response.statusCode - ); - } - else { - return const ApiResponse(successful: false); - } - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } - } - static Future getReleasesGitHub() async { try { - HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getReleasesGitHub)); - HttpClientResponse response = await request.close(); - String reply = await response.transform(utf8.decoder).join(); - httpClient.close(); + final response = await http.get(Uri.parse(Urls.getReleasesGitHub)); if (response.statusCode == 200) { return ApiResponse( successful: true, - content: List.from(jsonDecode(reply).map((entry) => GitHubRelease.fromJson(entry))) + content: List.from( + jsonDecode(response.body).map((entry) => GitHubRelease.fromJson(entry)) + ) ); } else { return const ApiResponse(successful: false); } - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + } catch (e) { return const ApiResponse(successful: false); } } - static Future getLatestReleaseGitHub() async { + static Future getReleaseData({ + // If releaseTag is null gets latest release + String? releaseTag + }) async { try { - HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getLatestReleaseGitHub)); - HttpClientResponse response = await request.close(); - String reply = await response.transform(utf8.decoder).join(); - httpClient.close(); + final response = await http.get( + Uri.parse( + releaseTag != null + ? "${Urls.adGuardHomeReleasesTags}/$releaseTag" + : Urls.getLatestReleaseGitHub + ) + ); if (response.statusCode == 200) { return ApiResponse( successful: true, - content: GitHubRelease.fromJson(jsonDecode(reply)), + content: GitHubRelease.fromJson(jsonDecode(response.body)), statusCode: response.statusCode ); } else { return const ApiResponse(successful: false); } - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + } catch (e) { return const ApiResponse(successful: false); } } diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index 4d6e131..9a42415 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; @@ -36,6 +37,7 @@ class _LayoutState extends State with WidgetsBindingObserver { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { + if (kDebugMode) return; // Don't check for app updates on debug mode final appConfigProvider = Provider.of(context, listen: false); final result = await checkAppUpdates( currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, diff --git a/pubspec.lock b/pubspec.lock index b32374c..0582275 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -319,7 +319,7 @@ packages: source: hosted version: "0.15.4" http: - dependency: transitive + dependency: "direct main" description: name: http sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" diff --git a/pubspec.yaml b/pubspec.yaml index 482ca92..bc0da25 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -75,6 +75,7 @@ dependencies: flutter_reorderable_list: ^1.3.1 pie_chart: ^5.4.0 segmented_button_slide: ^1.0.4 + http: ^1.1.0 dev_dependencies: flutter_test: From 2301848b254c37b838cd32f3ba147ab0881cf02a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 01:27:26 +0100 Subject: [PATCH 400/676] Updated workflow --- .github/workflows/release-beta.yaml | 32 ++++++++++++++--------------- pubspec.yaml | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 472e119..b46f9c6 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -2,19 +2,7 @@ name: Compile and release beta build on: workflow_dispatch: - inputs: - version: - description: "Version" - required: true - default: "1.0.0" - beta-number: - description: "Beta number" - required: true - default: "1" - number: - description: "Build number" - required: true - default: "1" + jobs: build-android: name: Build Android .apk and .aab @@ -22,7 +10,6 @@ jobs: env: ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release ANDROID_APK_RELEASE_PATH: build/app/outputs/apk/release - VERSION_NAME: ${{ github.event.inputs.version }}-beta.${{ github.event.inputs.beta-number }} steps: - uses: actions/checkout@v3 with: @@ -33,8 +20,21 @@ jobs: run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Update version in YAML - run: sed -i 's/99.99.99+99/${{ env.VERSION_NAME }}+${{ github.event.inputs.number }}/g' pubspec.yaml + - name: Read pubspec.yaml + uses: pietrobolcato/action-read-yaml@1.0.0 + id: read_pubspec + with: + config: ${{ github.workspace }}/pubspec.yaml + - name: Save version on env variable + run: | + version="${{ steps.read_pubspec.outputs['version'] }}" + echo ${version} + split=$((${version//+// })) + echo ${spliy} + name=${split[0]} + number=${split[1]} + echo "VERSION_NAME=$(echo ${name}_\(${number}\))" + echo "VERSION_NAME=$(echo ${name}_\(${number}\))" >> $GITHUB_ENV - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties diff --git a/pubspec.yaml b/pubspec.yaml index bc0da25..9ade92d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 99.99.99+99 +version: 2.11.1+106 environment: sdk: '>=2.18.1 <3.0.0' From da5b1f84da84287f2f83c990d9a27a6f805dd0da Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 01:30:58 +0100 Subject: [PATCH 401/676] Updated workflow --- .github/workflows/release-beta.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index b46f9c6..45170d6 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -21,13 +21,14 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: pietrobolcato/action-read-yaml@1.0.0 + uses: jbutcher5/read-yaml@1.6 id: read_pubspec with: - config: ${{ github.workspace }}/pubspec.yaml + file: './pubspec.yaml' + key-path: '["version"]' - name: Save version on env variable run: | - version="${{ steps.read_pubspec.outputs['version'] }}" + version="${{ steps.read_pubspec.outputs.data }}" echo ${version} split=$((${version//+// })) echo ${spliy} From fbee4f61650f1689d95c1bb07a956238ccec015d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 01:33:08 +0100 Subject: [PATCH 402/676] Updated workflow --- .github/workflows/release-beta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 45170d6..53bddeb 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -30,7 +30,7 @@ jobs: run: | version="${{ steps.read_pubspec.outputs.data }}" echo ${version} - split=$((${version//+// })) + split=$((${version//+/ })) echo ${spliy} name=${split[0]} number=${split[1]} From 8f4f0645ef67a74c626fcf2532d788d7aa4354a4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 01:35:23 +0100 Subject: [PATCH 403/676] Updated workflow --- .github/workflows/release-beta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 53bddeb..e169850 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -31,7 +31,7 @@ jobs: version="${{ steps.read_pubspec.outputs.data }}" echo ${version} split=$((${version//+/ })) - echo ${spliy} + echo "${split[0]}__${split[1]}" name=${split[0]} number=${split[1]} echo "VERSION_NAME=$(echo ${name}_\(${number}\))" From 9ffc4b1181eb924cdd5555e5c4d923d6837d7e16 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 01:41:19 +0100 Subject: [PATCH 404/676] Updated workflow --- .github/workflows/release-beta.yaml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index e169850..aa6c497 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -26,14 +26,16 @@ jobs: with: file: './pubspec.yaml' key-path: '["version"]' + - uses: winterjung/split@v2 + id: split + with: + msg: "${{ steps.read_pubspec.outputs.data }}" + separator: "+" - name: Save version on env variable - run: | - version="${{ steps.read_pubspec.outputs.data }}" - echo ${version} - split=$((${version//+/ })) - echo "${split[0]}__${split[1]}" - name=${split[0]} - number=${split[1]} + run: | + echo "${{ steps.split.outputs._0 }}__${{ steps.split.outputs._1 }}" + name=${{ steps.split.outputs._0 }} + number=${{ steps.split.outputs._1 }} echo "VERSION_NAME=$(echo ${name}_\(${number}\))" echo "VERSION_NAME=$(echo ${name}_\(${number}\))" >> $GITHUB_ENV - name: Update KeyStore password in gradle properties From 3da4fcf0c84ce8c9f559de5c326bb19eb972dff3 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 01:48:20 +0100 Subject: [PATCH 405/676] Updated workflow --- .github/workflows/release-beta.yaml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index aa6c497..a6b7cd5 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -26,18 +26,15 @@ jobs: with: file: './pubspec.yaml' key-path: '["version"]' - - uses: winterjung/split@v2 - id: split + - name: Split version string + uses: winterjung/split@v2 + id: splitted_version with: msg: "${{ steps.read_pubspec.outputs.data }}" separator: "+" - name: Save version on env variable run: | - echo "${{ steps.split.outputs._0 }}__${{ steps.split.outputs._1 }}" - name=${{ steps.split.outputs._0 }} - number=${{ steps.split.outputs._1 }} - echo "VERSION_NAME=$(echo ${name}_\(${number}\))" - echo "VERSION_NAME=$(echo ${name}_\(${number}\))" >> $GITHUB_ENV + echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }}" >> $GITHUB_ENV - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties From 14a62c36efb09f6642c0ab9f829203a636d969be Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 01:50:34 +0100 Subject: [PATCH 406/676] Updated workflow --- .github/workflows/release-beta.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index a6b7cd5..71b74a5 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -33,8 +33,7 @@ jobs: msg: "${{ steps.read_pubspec.outputs.data }}" separator: "+" - name: Save version on env variable - run: | - echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }}" >> $GITHUB_ENV + run: echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties From 1321d14cdba4ca241e2fb2f8243e34ea5ba9e828 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 01:58:07 +0100 Subject: [PATCH 407/676] Updated workflow --- .github/workflows/release-beta.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 71b74a5..845e6e4 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -2,6 +2,8 @@ name: Compile and release beta build on: workflow_dispatch: + branches: + - beta jobs: build-android: From b2795d71c9572581fd73ca4ee64002fcd581e27d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 02:15:10 +0100 Subject: [PATCH 408/676] Updated workflows --- .github/workflows/release-beta.yaml | 14 ++- .github/workflows/release-stable.yaml | 135 ++++++++++++++++++-------- 2 files changed, 105 insertions(+), 44 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 845e6e4..36d43d6 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -35,7 +35,10 @@ jobs: msg: "${{ steps.read_pubspec.outputs.data }}" separator: "+" - name: Save version on env variable - run: echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV + run: | + echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV + echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" + echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties @@ -70,8 +73,9 @@ jobs: name: Release beta build to GitHub runs-on: ubuntu-latest needs: [build-android] - env: - VERSION_NAME: ${{ github.event.inputs.version }}-beta.${{ github.event.inputs.beta-number }} + env: + VERSION_NAME: ${{ needs.build-android.outputs.version_name }} + VERSION_NUMBER: ${{ needs.build-android.outputs.version_number }} steps: - uses: actions/checkout@v3 with: @@ -88,7 +92,7 @@ jobs: with: artifacts: "releases/*" token: ${{ secrets.GH_TOKEN }} - tag: '${{ env.VERSION_NAME }}_(${{ github.event.inputs.number }})' + tag: '${{ env.VERSION_NAME }}_(${{ env.VERSION_NUMBER }})' name: v${{ env.VERSION_NAME }} draft: true prerelease: true @@ -98,7 +102,7 @@ jobs: runs-on: ubuntu-latest needs: [build-android] env: - VERSION_NAME: ${{ github.event.inputs.version }}-beta.${{ github.event.inputs.beta-number }} + VERSION_NAME: ${{ needs.build-android.outputs.version_name }} steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index b8d2b73..18da011 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -2,15 +2,8 @@ name: Compile and release production build on: workflow_dispatch: - inputs: - version: - description: "Version" - required: true - default: "1.0.0" - number: - description: "Build number" - required: true - default: "1" + branches: + - master jobs: build-android: name: Build Android .apk and .aab @@ -26,8 +19,23 @@ jobs: run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Update version in YAML - run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml + - name: Read pubspec.yaml + uses: jbutcher5/read-yaml@1.6 + id: read_pubspec + with: + file: './pubspec.yaml' + key-path: '["version"]' + - name: Split version string + uses: winterjung/split@v2 + id: splitted_version + with: + msg: "${{ steps.read_pubspec.outputs.data }}" + separator: "+" + - name: Save version on env variable + run: | + echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV + echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" + echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties @@ -44,20 +52,20 @@ jobs: - run: flutter build apk --release - run: flutter build appbundle --release - name: Rename apk - run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - name: Rename aab - run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - name: Copy apk to project root - run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - name: Copy aab to project root - run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - name: Upload artifact uses: actions/upload-artifact@v3 with: name: android path: | - AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab - AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab + AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk build-macos: name: Build macOS .dmg runs-on: macos-latest @@ -67,8 +75,23 @@ jobs: - uses: actions/checkout@v3 - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Update version in YAML - run: sed -i '' 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml + - name: Read pubspec.yaml + uses: jbutcher5/read-yaml@1.6 + id: read_pubspec + with: + file: './pubspec.yaml' + key-path: '["version"]' + - name: Split version string + uses: winterjung/split@v2 + id: splitted_version + with: + msg: "${{ steps.read_pubspec.outputs.data }}" + separator: "+" + - name: Save version on env variable + run: | + echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV + echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" + echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" - uses: subosito/flutter-action@v2 with: channel: "stable" @@ -96,14 +119,14 @@ jobs: - name: Generate symbolic link to Applications dir run: ln -s /Applications $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager - name: Generate dmg - run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg - name: Copy dmg to project root - run: cp $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + run: cp $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg - name: Upload artifact uses: actions/upload-artifact@v3 with: name: macos - path: AdGuardHomeManager_${{ github.event.inputs.version }}_macOS_Universal.dmg + path: AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg build-linux: name: Build Linux .tar.gz and .deb runs-on: ubuntu-latest @@ -111,10 +134,25 @@ jobs: - uses: actions/checkout@v3 - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Update version in pubspec.yaml - run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml + - name: Read pubspec.yaml + uses: jbutcher5/read-yaml@1.6 + id: read_pubspec + with: + file: './pubspec.yaml' + key-path: '["version"]' + - name: Split version string + uses: winterjung/split@v2 + id: splitted_version + with: + msg: "${{ steps.read_pubspec.outputs.data }}" + separator: "+" + - name: Save version on env variable + run: | + echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV + echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" + echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" - name: Update version in debian.yaml - run: sed -i 's//${{ github.event.inputs.version }}/g' debian/debian.yaml + run: sed -i 's//${{ env.VERSION_NAME }}/g' debian/debian.yaml - name: Update dependencies list run: sudo apt-get update - name: Install dependencies @@ -130,7 +168,7 @@ jobs: - name: Generate .deb package run: flutter_to_debian - name: Move .deb package to project root - run: mv debian/packages/AdGuardHomeManager_${{ github.event.inputs.version }}_amd64.deb AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb + run: mv debian/packages/AdGuardHomeManager_${{ env.VERSION_NAME }}_amd64.deb AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux_amd64.deb - name: Generate .tar.gz package uses: a7ul/tar-action@v1.1.3 id: compress @@ -141,14 +179,14 @@ jobs: ./data ./lib ./AdGuardHomeManager - outPath: AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz + outPath: AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux.tar.gz - name: Upload artifact uses: actions/upload-artifact@v3 with: name: linux path: | - AdGuardHomeManager_${{ github.event.inputs.version }}_Linux_amd64.deb - AdGuardHomeManager_${{ github.event.inputs.version }}_Linux.tar.gz + AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux_amd64.deb + AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux.tar.gz build-windows: name: Build Windows installer runs-on: windows-latest @@ -158,13 +196,27 @@ jobs: shell: pwsh run: | [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - - name: Update version in pubspec.yaml - shell: bash - run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml + - name: Read pubspec.yaml + uses: jbutcher5/read-yaml@1.6 + id: read_pubspec + with: + file: './pubspec.yaml' + key-path: '["version"]' + - name: Split version string + uses: winterjung/split@v2 + id: splitted_version + with: + msg: "${{ steps.read_pubspec.outputs.data }}" + separator: "+" + - name: Save version on env variable + run: | + echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV + echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" + echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" - name: Update version in innosetup config file shell: pwsh run: | - (Get-Content windows/innosetup_installer_builder.iss) -replace '', '${{ github.event.inputs.version }}' | Out-File -encoding ASCII windows/innosetup_installer_builder.iss + (Get-Content windows/innosetup_installer_builder.iss) -replace '', '${{ env.VERSION_NAME }}' | Out-File -encoding ASCII windows/innosetup_installer_builder.iss - uses: subosito/flutter-action@v2 with: channel: "stable" @@ -174,16 +226,19 @@ jobs: - name: Build installer witn innosetup run: iscc /Q windows/innosetup_installer_builder.iss - name: Move installer file to root directory - run: move build/windows/aghm_installer.exe AdGuardHomeManager_${{ github.event.inputs.version }}_Windows_x64.exe + run: move build/windows/aghm_installer.exe AdGuardHomeManager_${{ env.VERSION_NAME }}_Windows_x64.exe - name: Upload artifact uses: actions/upload-artifact@v3 with: name: windows - path: AdGuardHomeManager_${{ github.event.inputs.version }}_Windows_x64.exe + path: AdGuardHomeManager_${{ env.VERSION_NAME }}_Windows_x64.exe release-builds-github: name: Release builds to GitHub runs-on: ubuntu-latest needs: [build-android, build-macos, build-linux, build-windows] + env: + VERSION_NAME: ${{ needs.build-android.outputs.version_name }} + VERSION_NUMBER: ${{ needs.build-android.outputs.version_number }} steps: - uses: actions/checkout@v3 - name: Create builds directory @@ -213,8 +268,8 @@ jobs: with: artifacts: "releases/*" token: ${{ secrets.GH_TOKEN }} - tag: '${{ github.event.inputs.version }}_(${{ github.event.inputs.number }})' - name: v${{ github.event.inputs.version }} + tag: '${{ env.VERSION_NAME }}_(${{ env.VERSION_NUMBER }})' + name: v${{ env.VERSION_NAME }} draft: true prerelease: false commit: ${{ github.sha }} @@ -222,6 +277,8 @@ jobs: name: Release Android build to the Google Play Store runs-on: ubuntu-latest needs: [build-android, build-macos, build-linux, build-windows] + env: + VERSION_NAME: ${{ needs.build-android.outputs.version_name }} steps: - uses: actions/checkout@v3 - name: Download Android artifacts @@ -233,7 +290,7 @@ jobs: with: serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} packageName: com.jgeek00.adguard_home_manager - releaseFiles: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + releaseFiles: AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab track: production status: draft - releaseName: ${{ github.event.inputs.version }} \ No newline at end of file + releaseName: ${{ env.VERSION_NAME }} \ No newline at end of file From 42cfe4b4a6a065a4531a8b9514c6671d6b997bf5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 02:25:02 +0100 Subject: [PATCH 409/676] Updated workflow --- .github/workflows/release-beta.yaml | 15 +++---- .github/workflows/release-stable.yaml | 61 +++++++++++---------------- 2 files changed, 31 insertions(+), 45 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 36d43d6..93b09b1 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -28,17 +28,14 @@ jobs: with: file: './pubspec.yaml' key-path: '["version"]' - - name: Split version string - uses: winterjung/split@v2 - id: splitted_version - with: - msg: "${{ steps.read_pubspec.outputs.data }}" - separator: "+" - name: Save version on env variable run: | - echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV - echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" - echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT + echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 18da011..6611233 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -25,17 +25,14 @@ jobs: with: file: './pubspec.yaml' key-path: '["version"]' - - name: Split version string - uses: winterjung/split@v2 - id: splitted_version - with: - msg: "${{ steps.read_pubspec.outputs.data }}" - separator: "+" - name: Save version on env variable run: | - echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV - echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" - echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT + echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties @@ -81,17 +78,14 @@ jobs: with: file: './pubspec.yaml' key-path: '["version"]' - - name: Split version string - uses: winterjung/split@v2 - id: splitted_version - with: - msg: "${{ steps.read_pubspec.outputs.data }}" - separator: "+" - name: Save version on env variable run: | - echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV - echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" - echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT + echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT - uses: subosito/flutter-action@v2 with: channel: "stable" @@ -140,17 +134,14 @@ jobs: with: file: './pubspec.yaml' key-path: '["version"]' - - name: Split version string - uses: winterjung/split@v2 - id: splitted_version - with: - msg: "${{ steps.read_pubspec.outputs.data }}" - separator: "+" - name: Save version on env variable run: | - echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV - echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" - echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT + echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT - name: Update version in debian.yaml run: sed -i 's//${{ env.VERSION_NAME }}/g' debian/debian.yaml - name: Update dependencies list @@ -202,17 +193,15 @@ jobs: with: file: './pubspec.yaml' key-path: '["version"]' - - name: Split version string - uses: winterjung/split@v2 - id: splitted_version - with: - msg: "${{ steps.read_pubspec.outputs.data }}" - separator: "+" - name: Save version on env variable + shell: bash run: | - echo "VERSION_NAME=$(echo ${{ steps.splitted_version.outputs._0 }})" >> $GITHUB_ENV - echo "::set-output name=version_name::${{ steps.splitted_version.outputs._0 }}" - echo "::set-output name=version_number::${{ steps.splitted_version.outputs._1 }}" + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT + echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT - name: Update version in innosetup config file shell: pwsh run: | From 3adbc769027451dc7dae678ab44b0819476669ea Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 02:43:48 +0100 Subject: [PATCH 410/676] Updated workflows --- .github/workflows/release-beta.yaml | 14 ++++++---- .github/workflows/release-stable.yaml | 38 +++++++++++++++++++-------- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 93b09b1..792353e 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -12,6 +12,9 @@ jobs: env: ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release ANDROID_APK_RELEASE_PATH: build/app/outputs/apk/release + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} steps: - uses: actions/checkout@v3 with: @@ -29,13 +32,14 @@ jobs: file: './pubspec.yaml' key-path: '["version"]' - name: Save version on env variable + id: save_version run: | version=${{ steps.read_pubspec.outputs.data }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT - echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties @@ -71,8 +75,8 @@ jobs: runs-on: ubuntu-latest needs: [build-android] env: - VERSION_NAME: ${{ needs.build-android.outputs.version_name }} - VERSION_NUMBER: ${{ needs.build-android.outputs.version_number }} + VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} + VERSION_NUMBER: ${{ needs.build-android.outputs.VERSION_NUMBER }} steps: - uses: actions/checkout@v3 with: @@ -99,7 +103,7 @@ jobs: runs-on: ubuntu-latest needs: [build-android] env: - VERSION_NAME: ${{ needs.build-android.outputs.version_name }} + VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 6611233..f5a4ee6 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -11,6 +11,9 @@ jobs: env: ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release ANDROID_APK_RELEASE_PATH: build/app/outputs/apk/release + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} steps: - uses: actions/checkout@v3 - name: Decode android/app/keystore.jks @@ -26,13 +29,14 @@ jobs: file: './pubspec.yaml' key-path: '["version"]' - name: Save version on env variable + id: save_version run: | version=${{ steps.read_pubspec.outputs.data }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT - echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - name: Update KeyStore password in gradle properties run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - name: Update KeyStore key password in gradle properties @@ -68,6 +72,9 @@ jobs: runs-on: macos-latest env: MACOS_APP_RELEASE_PATH: build/macos/Build/Products/Release + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} steps: - uses: actions/checkout@v3 - name: Decode .env @@ -79,13 +86,14 @@ jobs: file: './pubspec.yaml' key-path: '["version"]' - name: Save version on env variable + id: save_version run: | version=${{ steps.read_pubspec.outputs.data }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT - echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - uses: subosito/flutter-action@v2 with: channel: "stable" @@ -124,6 +132,9 @@ jobs: build-linux: name: Build Linux .tar.gz and .deb runs-on: ubuntu-latest + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} steps: - uses: actions/checkout@v3 - name: Decode .env @@ -135,13 +146,14 @@ jobs: file: './pubspec.yaml' key-path: '["version"]' - name: Save version on env variable + id: save_version run: | version=${{ steps.read_pubspec.outputs.data }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT - echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - name: Update version in debian.yaml run: sed -i 's//${{ env.VERSION_NAME }}/g' debian/debian.yaml - name: Update dependencies list @@ -181,6 +193,9 @@ jobs: build-windows: name: Build Windows installer runs-on: windows-latest + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} steps: - uses: actions/checkout@v3 - name: Decode .env @@ -195,13 +210,14 @@ jobs: key-path: '["version"]' - name: Save version on env variable shell: bash + id: save_version run: | version=${{ steps.read_pubspec.outputs.data }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_OUTPUT - echo "VERSION_NUMBER=$(echo ${split[1]})" >> $GITHUB_OUTPUT + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - name: Update version in innosetup config file shell: pwsh run: | @@ -226,8 +242,8 @@ jobs: runs-on: ubuntu-latest needs: [build-android, build-macos, build-linux, build-windows] env: - VERSION_NAME: ${{ needs.build-android.outputs.version_name }} - VERSION_NUMBER: ${{ needs.build-android.outputs.version_number }} + VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} + VERSION_NUMBER: ${{ needs.build-android.outputs.VERSION_NUMBER }} steps: - uses: actions/checkout@v3 - name: Create builds directory @@ -267,7 +283,7 @@ jobs: runs-on: ubuntu-latest needs: [build-android, build-macos, build-linux, build-windows] env: - VERSION_NAME: ${{ needs.build-android.outputs.version_name }} + VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} steps: - uses: actions/checkout@v3 - name: Download Android artifacts From fa6b95d7684d3bdf1ad4e0de3fcc78ebab6aa2c8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 03:08:34 +0100 Subject: [PATCH 411/676] Removed import --- lib/services/external_requests.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/services/external_requests.dart b/lib/services/external_requests.dart index bd467fb..5f6ca58 100644 --- a/lib/services/external_requests.dart +++ b/lib/services/external_requests.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'package:http/http.dart' as http; -import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:adguard_home_manager/models/github_release.dart'; import 'package:adguard_home_manager/constants/urls.dart'; From d2c1c9431b7671611fbcdc2fe28c53425096cec6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 03:14:02 +0100 Subject: [PATCH 412/676] Updated workflow --- .github/workflows/release-beta.yaml | 6 +++--- .github/workflows/release-stable.yaml | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 792353e..5eb2f0a 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -26,11 +26,11 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: jbutcher5/read-yaml@1.6 + uses: christian-ci/action-yaml-github-output@v2 id: read_pubspec with: - file: './pubspec.yaml' - key-path: '["version"]' + file_path: './pubspec.yaml' + main_key: version - name: Save version on env variable id: save_version run: | diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index f5a4ee6..754384b 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -23,11 +23,11 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: jbutcher5/read-yaml@1.6 + uses: christian-ci/action-yaml-github-output@v2 id: read_pubspec with: - file: './pubspec.yaml' - key-path: '["version"]' + file_path: './pubspec.yaml' + main_key: version - name: Save version on env variable id: save_version run: | @@ -80,11 +80,11 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: jbutcher5/read-yaml@1.6 + uses: christian-ci/action-yaml-github-output@v2 id: read_pubspec with: - file: './pubspec.yaml' - key-path: '["version"]' + file_path: './pubspec.yaml' + main_key: version - name: Save version on env variable id: save_version run: | @@ -140,11 +140,11 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: jbutcher5/read-yaml@1.6 + uses: christian-ci/action-yaml-github-output@v2 id: read_pubspec with: - file: './pubspec.yaml' - key-path: '["version"]' + file_path: './pubspec.yaml' + main_key: version - name: Save version on env variable id: save_version run: | @@ -203,11 +203,11 @@ jobs: run: | [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Read pubspec.yaml - uses: jbutcher5/read-yaml@1.6 + uses: christian-ci/action-yaml-github-output@v2 id: read_pubspec with: - file: './pubspec.yaml' - key-path: '["version"]' + file_path: './pubspec.yaml' + main_key: version - name: Save version on env variable shell: bash id: save_version From 2d4733b658711f939b3303dad44b5952695335b0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 03:16:32 +0100 Subject: [PATCH 413/676] Updated workflow --- .github/workflows/release-beta.yaml | 2 +- .github/workflows/release-stable.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 5eb2f0a..3d5ef3d 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -29,7 +29,7 @@ jobs: uses: christian-ci/action-yaml-github-output@v2 id: read_pubspec with: - file_path: './pubspec.yaml' + file_path: ./pubspec.yaml main_key: version - name: Save version on env variable id: save_version diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 754384b..9c5ed04 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -26,7 +26,7 @@ jobs: uses: christian-ci/action-yaml-github-output@v2 id: read_pubspec with: - file_path: './pubspec.yaml' + file_path: ./pubspec.yaml main_key: version - name: Save version on env variable id: save_version From 70c41a5b7946d06f63025ac321a7c33b6a4f9d16 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 03:25:11 +0100 Subject: [PATCH 414/676] Updated workflow --- .github/workflows/release-beta.yaml | 6 +++--- .github/workflows/release-stable.yaml | 28 +++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 3d5ef3d..8f72ac4 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -26,11 +26,11 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: christian-ci/action-yaml-github-output@v2 + uses: adore-me/read-yaml@v1.0.0 id: read_pubspec with: - file_path: ./pubspec.yaml - main_key: version + file: './pubspec.yaml' + key-path: '["version"]' - name: Save version on env variable id: save_version run: | diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 9c5ed04..f1b41c9 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -22,12 +22,12 @@ jobs: run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Read pubspec.yaml - uses: christian-ci/action-yaml-github-output@v2 + - name: Read pubspec.yaml + uses: adore-me/read-yaml@v1.0.0 id: read_pubspec with: - file_path: ./pubspec.yaml - main_key: version + file: './pubspec.yaml' + key-path: '["version"]' - name: Save version on env variable id: save_version run: | @@ -80,11 +80,11 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: christian-ci/action-yaml-github-output@v2 + uses: adore-me/read-yaml@v1.0.0 id: read_pubspec with: - file_path: './pubspec.yaml' - main_key: version + file: './pubspec.yaml' + key-path: '["version"]' - name: Save version on env variable id: save_version run: | @@ -139,12 +139,12 @@ jobs: - uses: actions/checkout@v3 - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Read pubspec.yaml - uses: christian-ci/action-yaml-github-output@v2 + - name: Read pubspec.yaml + uses: adore-me/read-yaml@v1.0.0 id: read_pubspec with: - file_path: './pubspec.yaml' - main_key: version + file: './pubspec.yaml' + key-path: '["version"]' - name: Save version on env variable id: save_version run: | @@ -203,11 +203,11 @@ jobs: run: | [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Read pubspec.yaml - uses: christian-ci/action-yaml-github-output@v2 + uses: adore-me/read-yaml@v1.0.0 id: read_pubspec with: - file_path: './pubspec.yaml' - main_key: version + file: './pubspec.yaml' + key-path: '["version"]' - name: Save version on env variable shell: bash id: save_version From 2f32e3d3e7ecd65f81d3745c521d3056b7b4dcf7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 03:26:47 +0100 Subject: [PATCH 415/676] Updated workflow --- .github/workflows/release-stable.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index f1b41c9..2d8f0e8 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -4,6 +4,7 @@ on: workflow_dispatch: branches: - master + jobs: build-android: name: Build Android .apk and .aab @@ -22,7 +23,7 @@ jobs: run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Read pubspec.yaml + - name: Read pubspec.yaml uses: adore-me/read-yaml@v1.0.0 id: read_pubspec with: @@ -139,7 +140,7 @@ jobs: - uses: actions/checkout@v3 - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Read pubspec.yaml + - name: Read pubspec.yaml uses: adore-me/read-yaml@v1.0.0 id: read_pubspec with: From 791182d9c40a7c08ac5dc8b9874b080324066d4f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 23 Nov 2023 10:29:21 +0100 Subject: [PATCH 416/676] Fix format exception getServerStatus --- lib/services/api_client.dart | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index d8ef244..d99ab7c 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -59,24 +59,30 @@ class ApiClientV2 { HttpRequestClient.get(urlPath: "/parental/status", server: server), HttpRequestClient.get(urlPath: "/clients", server: server), ]); - if ( results.map((e) => e.successful).every((e) => e == true) && results.map((e) => e.body).every((e) => e != null) ) { - final Map mappedData = { - 'stats': jsonDecode(results[0].body!), - 'clients': jsonDecode(results[6].body!)['clients'], - 'status': jsonDecode(results[1].body!), - 'filtering': jsonDecode(results[2].body!), - 'safeSearch': jsonDecode(results[3].body!), - 'safeBrowsingEnabled': jsonDecode(results[4].body!), - 'parentalControlEnabled': jsonDecode(results[5].body!), - }; - return ApiResponse( - successful: true, - content: ServerStatus.fromJson(mappedData) - ); + try { + final Map mappedData = { + 'stats': jsonDecode(results[0].body!), + 'clients': jsonDecode(results[6].body!)['clients'], + 'status': jsonDecode(results[1].body!), + 'filtering': jsonDecode(results[2].body!), + 'safeSearch': jsonDecode(results[3].body!), + 'safeBrowsingEnabled': jsonDecode(results[4].body!), + 'parentalControlEnabled': jsonDecode(results[5].body!), + }; + return ApiResponse( + successful: true, + content: ServerStatus.fromJson(mappedData) + ); + } on FormatException { + return const ApiResponse(successful: false); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } } else { return const ApiResponse(successful: false); From d43f7596626c3866c3f5b76af1a5f447f240efd4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Nov 2023 00:30:57 +0100 Subject: [PATCH 417/676] Bug fix --- lib/classes/http_client.dart | 32 ++++++++++++++++++++++------- lib/providers/servers_provider.dart | 2 +- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/classes/http_client.dart b/lib/classes/http_client.dart index f14b839..c641b48 100644 --- a/lib/classes/http_client.dart +++ b/lib/classes/http_client.dart @@ -6,7 +6,7 @@ import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:adguard_home_manager/models/server.dart'; -enum ExceptionType { socket, timeout, handshake, unknown } +enum ExceptionType { socket, timeout, handshake, http, unknown } class HttpResponse { final bool successful; @@ -73,8 +73,14 @@ class HttpRequestClient { statusCode: null, exception: ExceptionType.handshake ); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + } on HttpException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.http + ); + } catch (e) { return const HttpResponse( successful: false, body: null, @@ -123,6 +129,13 @@ class HttpRequestClient { statusCode: null, exception: ExceptionType.timeout ); + } on HttpException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.http + ); } on HandshakeException { return const HttpResponse( successful: false, @@ -130,8 +143,7 @@ class HttpRequestClient { statusCode: null, exception: ExceptionType.handshake ); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + } catch (e) { return const HttpResponse( successful: false, body: null, @@ -180,6 +192,13 @@ class HttpRequestClient { statusCode: null, exception: ExceptionType.timeout ); + } on HttpException { + return const HttpResponse( + successful: false, + body: null, + statusCode: null, + exception: ExceptionType.http + ); } on HandshakeException { return const HttpResponse( successful: false, @@ -187,8 +206,7 @@ class HttpRequestClient { statusCode: null, exception: ExceptionType.handshake ); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + } catch (e) { return const HttpResponse( successful: false, body: null, diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 2cc634a..55d6363 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -265,7 +265,7 @@ class ServersProvider with ChangeNotifier { if (data.currentVersion == data.newVersion) { final gitHubResult = await ExternalRequests.getReleaseData(releaseTag: data.newVersion ?? data.currentVersion); if (gitHubResult.successful == true) { - data.changelog = gitHubResult.content; + data.changelog = (gitHubResult.content as GitHubRelease).body; } setUpdateAvailableData(data); timer.cancel(); From 019fed0f6b438d2ed7ba137408399e4d06915aeb Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Nov 2023 01:26:44 +0100 Subject: [PATCH 418/676] Bug fix --- lib/models/encryption.dart | 118 ++++++++++++++++++ .../settings/encryption/encryption.dart | 33 +++-- lib/services/api_client.dart | 4 +- 3 files changed, 137 insertions(+), 18 deletions(-) diff --git a/lib/models/encryption.dart b/lib/models/encryption.dart index 8f8a3a0..8a384c8 100644 --- a/lib/models/encryption.dart +++ b/lib/models/encryption.dart @@ -122,3 +122,121 @@ class EncryptionData { "private_key_saved": privateKeySaved, }; } + + + +EncyptionValidation encyptionValidationFromJson(String str) => EncyptionValidation.fromJson(json.decode(str)); + +String encyptionValidationToJson(EncyptionValidation data) => json.encode(data.toJson()); + +class EncyptionValidation { + final String? subject; + final String? issuer; + final String? keyType; + final DateTime? notBefore; + final DateTime? notAfter; + final String? warningValidation; + final List? dnsNames; + final bool? validCert; + final bool? validChain; + final bool? validKey; + final bool? validPair; + final bool? enabled; + final String? serverName; + final bool? forceHttps; + final int? portHttps; + final int? portDnsOverTls; + final int? portDnsOverQuic; + final int? portDnscrypt; + final String? dnscryptConfigFile; + final bool? allowUnencryptedDoh; + final String? certificateChain; + final String? privateKey; + final String? certificatePath; + final String? privateKeyPath; + final bool? privateKeySaved; + + EncyptionValidation({ + this.subject, + this.issuer, + this.keyType, + this.notBefore, + this.notAfter, + this.warningValidation, + this.dnsNames, + this.validCert, + this.validChain, + this.validKey, + this.validPair, + this.enabled, + this.serverName, + this.forceHttps, + this.portHttps, + this.portDnsOverTls, + this.portDnsOverQuic, + this.portDnscrypt, + this.dnscryptConfigFile, + this.allowUnencryptedDoh, + this.certificateChain, + this.privateKey, + this.certificatePath, + this.privateKeyPath, + this.privateKeySaved, + }); + + factory EncyptionValidation.fromJson(Map json) => EncyptionValidation( + subject: json["subject"], + issuer: json["issuer"], + keyType: json["key_type"], + notBefore: json["not_before"] == null ? null : DateTime.parse(json["not_before"]), + notAfter: json["not_after"] == null ? null : DateTime.parse(json["not_after"]), + warningValidation: json["warning_validation"], + dnsNames: json["dns_names"] == null ? [] : List.from(json["dns_names"]!.map((x) => x)), + validCert: json["valid_cert"], + validChain: json["valid_chain"], + validKey: json["valid_key"], + validPair: json["valid_pair"], + enabled: json["enabled"], + serverName: json["server_name"], + forceHttps: json["force_https"], + portHttps: json["port_https"], + portDnsOverTls: json["port_dns_over_tls"], + portDnsOverQuic: json["port_dns_over_quic"], + portDnscrypt: json["port_dnscrypt"], + dnscryptConfigFile: json["dnscrypt_config_file"], + allowUnencryptedDoh: json["allow_unencrypted_doh"], + certificateChain: json["certificate_chain"], + privateKey: json["private_key"], + certificatePath: json["certificate_path"], + privateKeyPath: json["private_key_path"], + privateKeySaved: json["private_key_saved"], + ); + + Map toJson() => { + "subject": subject, + "issuer": issuer, + "key_type": keyType, + "not_before": notBefore?.toIso8601String(), + "not_after": notAfter?.toIso8601String(), + "warning_validation": warningValidation, + "dns_names": dnsNames == null ? [] : List.from(dnsNames!.map((x) => x)), + "valid_cert": validCert, + "valid_chain": validChain, + "valid_key": validKey, + "valid_pair": validPair, + "enabled": enabled, + "server_name": serverName, + "force_https": forceHttps, + "port_https": portHttps, + "port_dns_over_tls": portDnsOverTls, + "port_dns_over_quic": portDnsOverQuic, + "port_dnscrypt": portDnscrypt, + "dnscrypt_config_file": dnscryptConfigFile, + "allow_unencrypted_doh": allowUnencryptedDoh, + "certificate_chain": certificateChain, + "private_key": privateKey, + "certificate_path": certificatePath, + "private_key_path": privateKeyPath, + "private_key_saved": privateKeySaved, + }; +} diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 63d9620..abf1735 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -138,23 +138,22 @@ class _EncryptionSettingsState extends State { } ); - if (mounted) { - if (result.successful == true) { - setState(() { - if (result.content['warning_validation'] != null && result.content['warning_validation'] != '') { - certKeyValidApi = 2; - validDataError = result.content['warning_validation']; - } - else { - certKeyValidApi = 1; - validDataError = null; - } - certKeyValid = result.content; - }); - } - else { - setState(() => certKeyValidApi = 2); - } + if (!mounted) return; + if (result.successful == true) { + final data = result.content as EncyptionValidation; + setState(() { + if (data.warningValidation != null && data.warningValidation != '') { + certKeyValidApi = 2; + validDataError = data.warningValidation; + } + else { + certKeyValidApi = 1; + validDataError = null; + } + certKeyValid = result.content; + }); + } + else { } } diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index d99ab7c..ba56a9c 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -698,7 +698,9 @@ class ApiClientV2 { try { return ApiResponse( successful: result.successful, - content: result.body != null ? jsonDecode(result.body!) : null + content: result.body != null + ? EncyptionValidation.fromJson(jsonDecode(result.body!)) + : null ); } catch (e, stackTrace) { Sentry.captureException(e, stackTrace: stackTrace); From 22a957a12007458254e84c35812a478185f6719e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Nov 2023 01:28:33 +0100 Subject: [PATCH 419/676] Removed unused import --- lib/classes/http_client.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/classes/http_client.dart b/lib/classes/http_client.dart index c641b48..d64e1d1 100644 --- a/lib/classes/http_client.dart +++ b/lib/classes/http_client.dart @@ -2,8 +2,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:sentry_flutter/sentry_flutter.dart'; - import 'package:adguard_home_manager/models/server.dart'; enum ExceptionType { socket, timeout, handshake, http, unknown } From 1c858c0491effec8a6269c32b2c4a848849a8f20 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Nov 2023 01:29:10 +0100 Subject: [PATCH 420/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 9ade92d..183b144 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.11.1+106 +version: 2.11.2+107 environment: sdk: '>=2.18.1 <3.0.0' From eb866e1ebe2afd8f562d2a3960569bb31b409f99 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Nov 2023 01:58:38 +0100 Subject: [PATCH 421/676] Fixed encryption settings --- .../settings/encryption/encryption.dart | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index abf1735..a618dbe 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -72,7 +72,7 @@ class _EncryptionSettingsState extends State { String? validDataError; int certKeyValidApi = 0; - Map? certKeyValid; + EncyptionValidation? certKeyValid; bool formEdited = false; @@ -150,7 +150,7 @@ class _EncryptionSettingsState extends State { certKeyValidApi = 1; validDataError = null; } - certKeyValid = result.content; + certKeyValid = data; }); } else { @@ -475,40 +475,40 @@ class _EncryptionSettingsState extends State { ), if (certKeyValid != null && (certificateContentController.text != '' || certificatePathController.text != '')) ...[ const SizedBox(height: 20), - if (certKeyValid!['valid_chain'] != null) ...[ + if (certKeyValid!.validChain != null) ...[ Status( - valid: certKeyValid!['valid_chain'], - label: certKeyValid!['valid_chain'] == true + valid: certKeyValid!.validChain ?? false, + label: certKeyValid!.validChain == true ? AppLocalizations.of(context)!.validCertificateChain : AppLocalizations.of(context)!.invalidCertificateChain, ), const SizedBox(height: 10), ], - if (certKeyValid!['subject'] != null) ...[ + if (certKeyValid!.subject != null) ...[ Status( valid: true, - label: "${AppLocalizations.of(context)!.subject}: ${certKeyValid!['subject']}" + label: "${AppLocalizations.of(context)!.subject}: ${certKeyValid?.subject}" ), const SizedBox(height: 10), ], - if (certKeyValid!['issuer'] != null) ...[ + if (certKeyValid!.issuer != null) ...[ Status( valid: true, - label: "${AppLocalizations.of(context)!.issuer}: ${certKeyValid!['issuer']}" + label: "${AppLocalizations.of(context)!.issuer}: ${certKeyValid?.issuer}" ), const SizedBox(height: 10), ], - if (certKeyValid!['not_after'] != null) ...[ + if (certKeyValid!.notAfter != null) ...[ Status( valid: true, - label: "${AppLocalizations.of(context)!.expirationDate}: ${certKeyValid!['not_after']}" + label: "${AppLocalizations.of(context)!.expirationDate}: ${certKeyValid?.notAfter}" ), const SizedBox(height: 10), ], - if (certKeyValid!['dns_names'] != null) ...[ + if (certKeyValid!.dnsNames != null) ...[ Status( valid: true, - label: "${AppLocalizations.of(context)!.hostNames}: ${certKeyValid!['dns_names'].join(', ')}" + label: "${AppLocalizations.of(context)!.hostNames}: ${certKeyValid?.dnsNames?.join(', ')}" ), const SizedBox(height: 10), ], @@ -586,26 +586,26 @@ class _EncryptionSettingsState extends State { ), const SizedBox(height: 20), if (certKeyValid != null && (privateKeyPathController.text != '' || pastePrivateKeyController.text != '' || usePreviouslySavedKey == true)) ...[ - if (certKeyValid!['valid_key'] != null) ...[ + if (certKeyValid!.validKey != null) ...[ Status( - valid: certKeyValid!['valid_key'], - label: certKeyValid!['valid_key'] == true + valid: certKeyValid!.validKey ?? false, + label: certKeyValid!.validKey == true ? AppLocalizations.of(context)!.validPrivateKey : AppLocalizations.of(context)!.invalidPrivateKey, ), const SizedBox(height: 10) ], - if (certKeyValid!['valid_pair'] != null && certKeyValid!['valid_pair'] == false) ...[ + if (certKeyValid!.validPair != null && certKeyValid!.validPair == false) ...[ Status( valid: false, label: AppLocalizations.of(context)!.keysNotMatch, ), const SizedBox(height: 10) ], - if (certKeyValid!['key_type'] != null) ...[ + if (certKeyValid!.keyType != null) ...[ Status( valid: true, - label: "${AppLocalizations.of(context)!.keyType}: ${certKeyValid!['key_type']}" + label: "${AppLocalizations.of(context)!.keyType}: ${certKeyValid!.keyType}" ), const SizedBox(height: 10), ], From 002fca4e3f8f79f137e441838f7d5880abbbd9c6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Nov 2023 01:59:06 +0100 Subject: [PATCH 422/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 183b144..c52eb16 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.11.2+107 +version: 2.11.3+108 environment: sdk: '>=2.18.1 <3.0.0' From 8dc9539a3a8a6f468e6b3fd57bbe93edd504c549 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 24 Nov 2023 20:44:56 +0100 Subject: [PATCH 423/676] Bug fixes --- lib/models/encryption.dart | 19 ++++++--- lib/screens/filters/filters_list.dart | 2 +- .../settings/encryption/encryption.dart | 42 ++++++++++++------- lib/services/api_client.dart | 15 +++++-- 4 files changed, 52 insertions(+), 26 deletions(-) diff --git a/lib/models/encryption.dart b/lib/models/encryption.dart index 8a384c8..1315868 100644 --- a/lib/models/encryption.dart +++ b/lib/models/encryption.dart @@ -124,12 +124,19 @@ class EncryptionData { } +class EncryptionValidationResult { + final bool isObject; + final EncryptionValidation? encryptionValidation; + final String? message; -EncyptionValidation encyptionValidationFromJson(String str) => EncyptionValidation.fromJson(json.decode(str)); + const EncryptionValidationResult({ + required this.isObject, + this.encryptionValidation, + this.message + }); +} -String encyptionValidationToJson(EncyptionValidation data) => json.encode(data.toJson()); - -class EncyptionValidation { +class EncryptionValidation { final String? subject; final String? issuer; final String? keyType; @@ -156,7 +163,7 @@ class EncyptionValidation { final String? privateKeyPath; final bool? privateKeySaved; - EncyptionValidation({ + EncryptionValidation({ this.subject, this.issuer, this.keyType, @@ -184,7 +191,7 @@ class EncyptionValidation { this.privateKeySaved, }); - factory EncyptionValidation.fromJson(Map json) => EncyptionValidation( + factory EncryptionValidation.fromJson(Map json) => EncryptionValidation( subject: json["subject"], issuer: json["issuer"], keyType: json["key_type"], diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index 5c93fb0..f4cca03 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -172,7 +172,7 @@ class _FiltersListState extends State { loadStatus: widget.loadStatus, onRefresh: () async { final result = await filteringProvider.fetchFilters(); - if (result == false) { + if (result == false && mounted) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index a618dbe..f47a63d 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -72,7 +72,8 @@ class _EncryptionSettingsState extends State { String? validDataError; int certKeyValidApi = 0; - EncyptionValidation? certKeyValid; + EncryptionValidation? certKeyValid; + String? encryptionResultMessage; bool formEdited = false; @@ -140,20 +141,27 @@ class _EncryptionSettingsState extends State { if (!mounted) return; if (result.successful == true) { - final data = result.content as EncyptionValidation; - setState(() { - if (data.warningValidation != null && data.warningValidation != '') { + final data = result.content as EncryptionValidationResult; + if (data.isObject == true) { + final object = data.encryptionValidation!; + setState(() { + if (object.warningValidation != null && object.warningValidation != '') { + certKeyValidApi = 2; + validDataError = object.warningValidation; + } + else { + certKeyValidApi = 1; + validDataError = null; + } + certKeyValid = object; + }); + } + else { + setState(() { + encryptionResultMessage = data.message; certKeyValidApi = 2; - validDataError = data.warningValidation; - } - else { - certKeyValidApi = 1; - validDataError = null; - } - certKeyValid = data; - }); - } - else { + }); + } } } @@ -253,11 +261,13 @@ class _EncryptionSettingsState extends State { centerTitle: false, actions: [ IconButton( - onPressed: certKeyValidApi == 2 && validDataError != null + onPressed: certKeyValidApi == 2 && (validDataError != null || encryptionResultMessage != null) ? () => { showDialog( context: context, - builder: (context) => EncryptionErrorModal(error: validDataError!) + builder: (context) => EncryptionErrorModal( + error: validDataError ?? encryptionResultMessage ?? AppLocalizations.of(context)!.unknownError + ) ) } : null, icon: generateStatus(context, appConfigProvider, localValidationValid, certKeyValidApi, formEdited), diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index ba56a9c..66ac615 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -698,9 +698,18 @@ class ApiClientV2 { try { return ApiResponse( successful: result.successful, - content: result.body != null - ? EncyptionValidation.fromJson(jsonDecode(result.body!)) - : null + content: result.body != null ? EncryptionValidationResult( + isObject: false, + encryptionValidation: EncryptionValidation.fromJson(jsonDecode(result.body!)) + ) : null + ); + } on FormatException { + return ApiResponse( + successful: result.successful, + content: result.body != null ? EncryptionValidationResult( + isObject: false, + message: result.body + ) : null ); } catch (e, stackTrace) { Sentry.captureException(e, stackTrace: stackTrace); From 28229311c0b575a1833d374c37e3cc1da5157a5b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 25 Nov 2023 19:02:36 +0100 Subject: [PATCH 424/676] Updated libraries --- pubspec.lock | 34 +++++++++++++++++++++------------- pubspec.yaml | 10 +++++----- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 0582275..274cfb3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.8" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880" + url: "https://pub.dev" + source: hosted + version: "2.0.2" archive: dependency: transitive description: @@ -133,10 +141,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "7035152271ff67b072a211152846e9f1259cf1be41e34cd3e0b5463d2d6b8419" + sha256: "0042cb3b2a76413ea5f8a2b40cec2a33e01d0c937e91f0f7c211fde4f7739ba6" url: "https://pub.dev" source: hosted - version: "9.1.0" + version: "9.1.1" device_info_plus_platform_interface: dependency: transitive description: @@ -197,10 +205,10 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: "6b9eb2b3017241d05c482c01f668dd05cc909ec9a0114fdd49acd958ff2432fa" + sha256: "5a74434cc83bf64346efb562f1a06eefaf1bcb530dc3d96a104f631a1eff8d79" url: "https://pub.dev" source: hosted - version: "0.64.0" + version: "0.65.0" flutter: dependency: "direct main" description: flutter @@ -263,10 +271,10 @@ packages: dependency: "direct dev" description: name: flutter_native_splash - sha256: d93394f22f73e810bda59e11ebe83329c5511d6460b6b7509c4e1f3c92d6d625 + sha256: c4d899312b36e7454bedfd0a4740275837b99e532d81c8477579d8183db1de6c url: "https://pub.dev" source: hosted - version: "2.3.5" + version: "2.3.6" flutter_reorderable_list: dependency: "direct main" description: @@ -426,10 +434,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017" + sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79" url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "5.0.1" package_info_plus_platform_interface: dependency: transitive description: @@ -514,18 +522,18 @@ packages: dependency: transitive description: name: sentry - sha256: e8040183ea1a0323999bce69786ed8429b1b89fbe5815a504d5bb7493a6464cc + sha256: e7ded42974bac5f69e4ca4ddc57d30499dd79381838f24b7e8fd9aa4139e7b79 url: "https://pub.dev" source: hosted - version: "7.13.1" + version: "7.13.2" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "843e317e605e5860e30ae431e9b8724c54f1a8567c9ad495e04595926bf22376" + sha256: d6f55ec7a1f681784165021f749007712a72ff57eadf91e963331b6ae326f089 url: "https://pub.dev" source: hosted - version: "7.13.1" + version: "7.13.2" sky_engine: dependency: transitive description: flutter @@ -813,5 +821,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" + dart: ">=3.2.0 <4.0.0" flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index c52eb16..d4f6f8e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,14 +41,14 @@ dependencies: intl: any provider: ^6.1.1 sqflite: ^2.3.0 - package_info_plus: ^4.2.0 + package_info_plus: ^5.0.1 flutter_displaymode: ^0.6.0 dynamic_color: ^1.6.8 animations: ^2.0.8 - device_info_plus: ^9.1.0 + device_info_plus: ^9.1.1 uuid: ^4.2.1 expandable: ^5.0.1 - fl_chart: ^0.64.0 + fl_chart: ^0.65.0 flutter_web_browser: ^0.17.1 flutter_svg: ^2.0.9 percent_indicator: ^4.2.3 @@ -70,7 +70,7 @@ dependencies: url_launcher: ^6.1.11 contextmenu: ^3.0.0 async: ^2.11.0 - sentry_flutter: ^7.13.1 + sentry_flutter: ^7.13.2 flutter_dotenv: ^5.1.0 flutter_reorderable_list: ^1.3.1 pie_chart: ^5.4.0 @@ -88,7 +88,7 @@ dev_dependencies: # rules and activating additional ones. flutter_lints: ^3.0.1 flutter_launcher_icons: ^0.13.1 - flutter_native_splash: ^2.2.10+1 + flutter_native_splash: ^2.3.6 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From 07bd3dcb9ad5173f96be019cda8a1f78b8073635 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 25 Nov 2023 19:03:26 +0100 Subject: [PATCH 425/676] Added top upstreams and average processing time --- lib/config/home_top_items_default_order.dart | 4 +- lib/constants/enums.dart | 2 +- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/models/dns_statistics.dart | 8 + lib/providers/app_config_provider.dart | 13 +- lib/providers/status_provider.dart | 2 +- lib/screens/home/home.dart | 47 +++- lib/screens/home/top_items/row_item.dart | 21 +- .../top_items/top_item_expansion_panel.dart | 193 ++++++++++++++++ lib/screens/home/top_items/top_items.dart | 208 ++++++++---------- .../reorderable_top_items_home.dart | 53 +++-- lib/screens/top_items/top_items.dart | 29 ++- lib/screens/top_items/top_items_modal.dart | 29 ++- lib/widgets/domain_options.dart | 12 +- 15 files changed, 441 insertions(+), 188 deletions(-) create mode 100644 lib/screens/home/top_items/top_item_expansion_panel.dart diff --git a/lib/config/home_top_items_default_order.dart b/lib/config/home_top_items_default_order.dart index 5220987..a5a23f0 100644 --- a/lib/config/home_top_items_default_order.dart +++ b/lib/config/home_top_items_default_order.dart @@ -5,7 +5,9 @@ import 'package:adguard_home_manager/constants/enums.dart'; final List homeTopItemsDefaultOrder = [ HomeTopItems.queriedDomains, HomeTopItems.blockedDomains, - HomeTopItems.recurrentClients + HomeTopItems.recurrentClients, + HomeTopItems.topUpstreams, + HomeTopItems.avgUpstreamResponseTime ]; final String homeTopItemsDefaultOrderString = jsonEncode( diff --git a/lib/constants/enums.dart b/lib/constants/enums.dart index fed648e..f54e665 100644 --- a/lib/constants/enums.dart +++ b/lib/constants/enums.dart @@ -1,2 +1,2 @@ enum LoadStatus { loading, loaded, error } -enum HomeTopItems { queriedDomains, blockedDomains, recurrentClients } \ No newline at end of file +enum HomeTopItems { queriedDomains, blockedDomains, recurrentClients, topUpstreams, avgUpstreamResponseTime } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 7c126ba..b9ba629 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -686,5 +686,7 @@ "unsupportedServerVersion": "Unsupported server version", "unsupportedServerVersionMessage": "Your AdGuard Home server version is too old and is not supported by AdGuard Home Manager. You will need to upgrade your AdGuard Home server to a newer version to use this application.", "yourVersion": "Your version: {version}", - "minimumRequiredVersion": "Minimum required version: {version}" + "minimumRequiredVersion": "Minimum required version: {version}", + "topUpstreams": "Top upstreams", + "averageUpstreamResponseTime": "Average upstream response time" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 9033460..0e1566c 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -686,5 +686,7 @@ "unsupportedServerVersion": "Versión del servidor no soportada", "unsupportedServerVersionMessage": "La versión de tu servidor AdGuard Home es demasiado antigua y no está soportada por AdGuard Home Manager. Necesitarás actualizar tu servidor AdGuard Home a una versión más actual para utilizar esta aplicación.", "yourVersion": "Tu versión: {version}", - "minimumRequiredVersion": "Versión mínima requerida: {version}" + "minimumRequiredVersion": "Versión mínima requerida: {version}", + "topUpstreams": "DNS de subida más frecuentes", + "averageUpstreamResponseTime": "Tiempo promedio de respuesta upstream" } \ No newline at end of file diff --git a/lib/models/dns_statistics.dart b/lib/models/dns_statistics.dart index 45993bd..f279886 100644 --- a/lib/models/dns_statistics.dart +++ b/lib/models/dns_statistics.dart @@ -9,6 +9,8 @@ class DnsStatistics { final List> topQueriedDomains; final List> topClients; final List> topBlockedDomains; + final List>? topUpstreamResponses; + final List>? topUpstreamsAvgTime; final List dnsQueries; final List blockedFiltering; final List replacedSafebrowsing; @@ -25,6 +27,8 @@ class DnsStatistics { required this.topQueriedDomains, required this.topClients, required this.topBlockedDomains, + required this.topUpstreamResponses, + required this.topUpstreamsAvgTime, required this.dnsQueries, required this.blockedFiltering, required this.replacedSafebrowsing, @@ -42,6 +46,8 @@ class DnsStatistics { topQueriedDomains: List>.from(json["top_queried_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), topClients: List>.from(json["top_clients"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), topBlockedDomains: List>.from(json["top_blocked_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), + topUpstreamResponses: json["top_upstreams_responses"] != null ? List>.from(json["top_upstreams_responses"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : null, + topUpstreamsAvgTime: json["top_upstreams_avg_time"] != null ? List>.from(json["top_upstreams_avg_time"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : null, dnsQueries: List.from(json["dns_queries"].map((x) => x)), blockedFiltering: List.from(json["blocked_filtering"].map((x) => x)), replacedSafebrowsing: List.from(json["replaced_safebrowsing"].map((x) => x)), @@ -59,6 +65,8 @@ class DnsStatistics { "top_queried_domains": List.from(topQueriedDomains.map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), "top_clients": List.from(topClients.map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), "top_blocked_domains": List.from(topBlockedDomains.map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), + "top_upstreams_responses": topUpstreamResponses != null ? List.from(topUpstreamResponses!.map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : null, + "top_upstreams_avg_time": topUpstreamsAvgTime != null ? List.from(topUpstreamsAvgTime!.map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : null, "dns_queries": List.from(dnsQueries.map((x) => x)), "blocked_filtering": List.from(blockedFiltering.map((x) => x)), "replaced_safebrowsing": List.from(replacedSafebrowsing.map((x) => x)), diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 16e855f..d44b5af 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -449,7 +449,7 @@ class AppConfigProvider with ChangeNotifier { _showTopItemsChart = dbData['showTopItemsChart']; if (dbData['homeTopItemsOrder'] != null) { try { - _homeTopItemsOrder = List.from( + final itemsOrder = List.from( List.from(jsonDecode(dbData['homeTopItemsOrder'])).map((e) { switch (e) { case 'queriedDomains': @@ -461,11 +461,22 @@ class AppConfigProvider with ChangeNotifier { case 'recurrentClients': return HomeTopItems.recurrentClients; + case 'topUpstreams': + return HomeTopItems.topUpstreams; + + case 'avgUpstreamResponseTime': + return HomeTopItems.avgUpstreamResponseTime; + default: return null; } }).where((e) => e != null).toList() ); + final missingItems = homeTopItemsDefaultOrder.where((e) => !itemsOrder.contains(e)); + _homeTopItemsOrder = [ + ...itemsOrder, + ...missingItems + ]; } catch (e) { Sentry.captureException(e); _homeTopItemsOrder = homeTopItemsDefaultOrder; diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart index 0c519f8..527749f 100644 --- a/lib/providers/status_provider.dart +++ b/lib/providers/status_provider.dart @@ -237,7 +237,7 @@ class StatusProvider with ChangeNotifier { } Future getServerStatus({ - bool? withLoadingIndicator, + bool? withLoadingIndicator = true, bool? overrideCheckServerVersion }) async { if (withLoadingIndicator == true) { diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 343d065..ec48e54 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -32,8 +32,11 @@ class _HomeState extends State { late bool isVisible; @override - initState(){ - Provider.of(context, listen: false).getServerStatus(); + initState() { + final statusProvider = Provider.of(context, listen: false); + statusProvider.getServerStatus( + withLoadingIndicator: statusProvider.serverStatus != null ? false : true + ); super.initState(); @@ -239,9 +242,9 @@ class TopItemsLists extends StatelessWidget { final List order; const TopItemsLists({ - Key? key, + super.key, required this.order, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -266,8 +269,7 @@ class TopItemsLists extends StatelessWidget { children: [ TopItems( label: AppLocalizations.of(context)!.topQueriedDomains, - data: statusProvider.serverStatus!.stats.topQueriedDomains, - type: 'topQueriedDomains', + type: HomeTopItems.queriedDomains, ), if (item.key < order.length - 1) ...bottom ], @@ -278,8 +280,7 @@ class TopItemsLists extends StatelessWidget { children: [ TopItems( label: AppLocalizations.of(context)!.topBlockedDomains, - data: statusProvider.serverStatus!.stats.topBlockedDomains, - type: 'topBlockedDomains', + type: HomeTopItems.blockedDomains, ), if (item.key < order.length - 1) ...bottom ], @@ -290,13 +291,37 @@ class TopItemsLists extends StatelessWidget { children: [ TopItems( label: AppLocalizations.of(context)!.topClients, - data: statusProvider.serverStatus!.stats.topClients, - type: 'topClients', - clients: true, + type: HomeTopItems.recurrentClients, ), if (item.key < order.length - 1) ...bottom ], ); + + case HomeTopItems.topUpstreams: + return statusProvider.serverStatus!.stats.topUpstreamResponses != null + ? Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.topUpstreams, + type: HomeTopItems.topUpstreams, + ), + if (item.key < order.length - 1) ...bottom + ], + ) + : const SizedBox(); + + case HomeTopItems.avgUpstreamResponseTime: + return statusProvider.serverStatus!.stats.topUpstreamsAvgTime != null + ? Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.averageUpstreamResponseTime, + type: HomeTopItems.avgUpstreamResponseTime, + ), + if (item.key < order.length - 1) ...bottom + ], + ) + : const SizedBox(); default: return const SizedBox(); diff --git a/lib/screens/home/top_items/row_item.dart b/lib/screens/home/top_items/row_item.dart index dbbd6d4..4e3c184 100644 --- a/lib/screens/home/top_items/row_item.dart +++ b/lib/screens/home/top_items/row_item.dart @@ -4,28 +4,31 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/domain_options.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; class RowItem extends StatefulWidget { - final String type; + final HomeTopItems type; final Color chartColor; final String domain; final String number; final bool clients; final bool showColor; + final String? unit; const RowItem({ - Key? key, + super.key, required this.type, required this.chartColor, required this.domain, required this.number, required this.clients, required this.showColor, - }) : super(key: key); + this.unit, + }); @override State createState() => _RowItemState(); @@ -93,10 +96,10 @@ class _RowItemState extends State with TickerProviderStateMixin { color: Colors.transparent, child: DomainOptions( item: widget.domain, - isClient: widget.type == 'topClients', - isBlocked: widget.type == 'topBlockedDomains', + isDomain: widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains, + isBlocked: widget.type == HomeTopItems.blockedDomains, onTap: () { - if (widget.type == 'topQueriedDomains' || widget.type == 'topBlockedDomains') { + if (widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains) { logsProvider.setSearchText(widget.domain); logsProvider.setSelectedClients(null); logsProvider.setAppliedFilters( @@ -108,7 +111,7 @@ class _RowItemState extends State with TickerProviderStateMixin { ); appConfigProvider.setSelectedScreen(2); } - else if (widget.type == 'topClients') { + else if (widget.type == HomeTopItems.recurrentClients) { logsProvider.setSearchText(null); logsProvider.setSelectedClients([widget.domain]); logsProvider.setAppliedFilters( @@ -195,10 +198,10 @@ class OthersRowItem extends StatefulWidget { final bool showColor; const OthersRowItem({ - Key? key, + super.key, required this.items, required this.showColor, - }) : super(key: key); + }); @override State createState() => _OthersRowItemState(); diff --git a/lib/screens/home/top_items/top_item_expansion_panel.dart b/lib/screens/home/top_items/top_item_expansion_panel.dart new file mode 100644 index 0000000..eb62d01 --- /dev/null +++ b/lib/screens/home/top_items/top_item_expansion_panel.dart @@ -0,0 +1,193 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; +import 'package:adguard_home_manager/screens/home/top_items/row_item.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; + +class TopItemExpansionPanel extends StatefulWidget { + final HomeTopItems type; + final String label; + final List> data; + final Map chartData; + final bool withChart; + + const TopItemExpansionPanel({ + super.key, + required this.type, + required this.label, + required this.data, + required this.chartData, + required this.withChart + }); + + @override + State createState() => _TopItemExpansionPanelState(); +} + +class _TopItemExpansionPanelState extends State { + bool _showChart = true; + + final colors = [ + Colors.red, + Colors.green, + Colors.blue, + Colors.orange, + Colors.teal, + Colors.grey + ]; + + @override + Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + + if (widget.withChart == true) { + return Column( + children: [ + ExpansionPanelList( + expandedHeaderPadding: const EdgeInsets.all(0), + elevation: 0, + expansionCallback: (_, isExpanded) => setState(() => _showChart = isExpanded), + animationDuration: const Duration(milliseconds: 250), + children: [ + ExpansionPanel( + headerBuilder: (context, isExpanded) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: width <= 700 + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.center, + children: [ + Flexible( + child: Text( + widget.label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ), + ], + ), + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Column( + children: [ + SizedBox( + height: 150, + child: CustomPieChart( + data: widget.chartData, + colors: colors + ) + ), + const SizedBox(height: 16), + ], + ), + ), + isExpanded: _showChart + ), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 8), + child: _ItemsList( + colors: colors, + data: widget.data, + clients: widget.type == HomeTopItems.recurrentClients, + type: widget.type, + showChart: _showChart, + unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, + ), + ), + if (widget.type != HomeTopItems.avgUpstreamResponseTime) OthersRowItem( + items: widget.data, + showColor: _showChart, + ), + const SizedBox(height: 16), + ], + ); + } + else { + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 18), + child: Row( + mainAxisAlignment: width <= 700 + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.center, + children: [ + Flexible( + child: Text( + widget.label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16), + child: _ItemsList( + colors: colors, + data: widget.data, + clients: widget.type == HomeTopItems.recurrentClients, + type: widget.type, + showChart: false, + unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, + ), + ), + if (widget.type != HomeTopItems.avgUpstreamResponseTime) OthersRowItem( + items: widget.data, + showColor: false, + ), + const SizedBox(height: 16), + ], + ); + } + } +} + +class _ItemsList extends StatelessWidget { + final List colors; + final List> data; + final bool? clients; + final HomeTopItems type; + final bool showChart; + final String? unit; + + const _ItemsList({ + required this.colors, + required this.data, + required this.clients, + required this.type, + required this.showChart, + this.unit, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: data.sublist( + 0, data.length > 5 ? 5 : data.length + ).asMap().entries.map((e) => RowItem( + clients: clients ?? false, + domain: e.value.keys.toList()[0], + number: e.value.values.toList()[0].runtimeType == double + ? "${e.value.values.toList()[0].toStringAsFixed(2)}${unit != null ? ' $unit' : ''}" + : "${e.value.values.toList()[0].toString()}${unit != null ? ' $unit' : ''}", + type: type, + chartColor: colors[e.key], + showColor: showChart, + )).toList() + ); + } +} \ No newline at end of file diff --git a/lib/screens/home/top_items/top_items.dart b/lib/screens/home/top_items/top_items.dart index 5fd6435..6276d74 100644 --- a/lib/screens/home/top_items/top_items.dart +++ b/lib/screens/home/top_items/top_items.dart @@ -7,26 +7,24 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/home/top_items/row_item.dart'; -import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; +import 'package:adguard_home_manager/screens/home/top_items/top_item_expansion_panel.dart'; import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; +import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class TopItems extends StatefulWidget { - final String type; + final HomeTopItems type; final String label; - final List> data; - final bool? clients; const TopItems({ - Key? key, + super.key, required this.type, required this.label, - required this.data, - this.clients - }) : super(key: key); + }); @override State createState() => _TopItemsState(); @@ -58,31 +56,41 @@ class _TopItemsState extends State { List> generateData() { switch (widget.type) { - case 'topQueriedDomains': + case HomeTopItems.queriedDomains: return statusProvider.serverStatus!.stats.topQueriedDomains; - case 'topBlockedDomains': + case HomeTopItems.blockedDomains: return statusProvider.serverStatus!.stats.topBlockedDomains; - case 'topClients': + case HomeTopItems.recurrentClients: return statusProvider.serverStatus!.stats.topClients; + case HomeTopItems.topUpstreams: + return statusProvider.serverStatus!.stats.topUpstreamResponses ?? []; + + case HomeTopItems.avgUpstreamResponseTime: + return statusProvider.serverStatus!.stats.topUpstreamsAvgTime ?? []; + default: return []; } } + final data = generateData(); + + final withChart = widget.type != HomeTopItems.avgUpstreamResponseTime; + Map chartData() { Map values = {}; - widget.data.sublist(0, widget.data.length > 5 ? 5 : widget.data.length).forEach((element) { + data.sublist(0, data.length > 5 ? 5 : data.length).forEach((element) { values = { ...values, element.keys.first: element.values.first.toDouble() }; }); - if (widget.data.length > 5) { + if (data.length > 5) { final int rest = List.from( - widget.data.sublist(5, widget.data.length).map((e) => e.values.first.toInt()) + data.sublist(5, data.length).map((e) => e.values.first.toInt()) ).reduce((a, b) => a + b); values = { ...values, @@ -109,108 +117,71 @@ class _TopItemsState extends State { return SizedBox( child: Column( children: [ - if (widget.data.isEmpty) noItems, - if (widget.data.isNotEmpty && width > 700) Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - flex: 1, - child: ConstrainedBox( - constraints: const BoxConstraints( - maxHeight: 250 - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: CustomPieChart( - data: chartData(), - colors: colors - ) - ), - ) - ), - Expanded( - flex: 2, - child: Column( - children: [ - ItemsList( - colors: colors, - data: widget.data, - clients: widget.clients, - type: widget.type, - showChart: _showChart - ), - OthersRowItem( - items: widget.data, - showColor: true, - ) - ] - ), - ) - ], - ), - if (widget.data.isNotEmpty && width <= 700) ...[ - ExpansionPanelList( - expandedHeaderPadding: const EdgeInsets.all(0), - elevation: 0, - expansionCallback: (_, isExpanded) => setState(() => _showChart = isExpanded), - animationDuration: const Duration(milliseconds: 250), + if (data.isEmpty) noItems, + if (data.isNotEmpty && width > 700) Padding( + padding: EdgeInsets.only(bottom: withChart == false ? 16 : 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - ExpansionPanel( - headerBuilder: (context, isExpanded) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisAlignment: width <= 700 - ? MainAxisAlignment.spaceBetween - : MainAxisAlignment.center, - children: [ - Text( + if (withChart == true) Expanded( + flex: 1, + child: ConstrainedBox( + constraints: const BoxConstraints( + maxHeight: 250 + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: CustomPieChart( + data: chartData(), + colors: colors + ) + ), + ) + ), + Expanded( + flex: 2, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 8, + bottom: 16 + ), + child: Text( widget.label, - style: TextStyle( + style: const TextStyle( fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface + fontWeight: FontWeight.w500 ), ), - ], - ), + ), + _ItemsList( + colors: colors, + data: data, + clients: widget.type == HomeTopItems.recurrentClients, + type: widget.type, + showChart: withChart == true ? _showChart : false, + unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, + ), + if (withChart == true) OthersRowItem( + items: data, + showColor: true, + ) + ] ), - body: Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Column( - children: [ - SizedBox( - height: 150, - child: CustomPieChart( - data: chartData(), - colors: colors - ) - ), - const SizedBox(height: 16), - ], - ), - ), - isExpanded: _showChart - ), + ) ], ), - Padding( - padding: const EdgeInsets.only(top: 8), - child: ItemsList( - colors: colors, - data: widget.data, - clients: widget.clients, - type: widget.type, - showChart: _showChart - ), - ), - OthersRowItem( - items: widget.data, - showColor: _showChart, - ), - const SizedBox(height: 16), - ], + ), + if (data.isNotEmpty && width <= 700) TopItemExpansionPanel( + type: widget.type, + label: widget.label, + data: data, + chartData: chartData(), + withChart: withChart + ), - if (widget.data.length > 5) ...[ + if (data.length > 5) ...[ Padding( padding: const EdgeInsets.only(right: 20), child: Row( @@ -225,8 +196,10 @@ class _TopItemsState extends State { builder: (context) => TopItemsModal( type: widget.type, title: widget.label, - isClient: widget.clients, + isClient: widget.type == HomeTopItems.recurrentClients, data: generateData(), + withProgressBar: widget.type != HomeTopItems.avgUpstreamResponseTime, + unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, ) ) } @@ -236,8 +209,10 @@ class _TopItemsState extends State { builder: (context) => TopItemsScreen( type: widget.type, title: widget.label, - isClient: widget.clients, + isClient: widget.type == HomeTopItems.recurrentClients, data: generateData(), + withProgressBar: widget.type != HomeTopItems.avgUpstreamResponseTime, + unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, ) ) ) @@ -266,21 +241,22 @@ class _TopItemsState extends State { } } -class ItemsList extends StatelessWidget { +class _ItemsList extends StatelessWidget { final List colors; final List> data; final bool? clients; - final String type; + final HomeTopItems type; final bool showChart; + final String? unit; - const ItemsList({ - Key? key, + const _ItemsList({ required this.colors, required this.data, required this.clients, required this.type, required this.showChart, - }) : super(key: key); + this.unit, + }); @override Widget build(BuildContext context) { @@ -290,7 +266,9 @@ class ItemsList extends StatelessWidget { ).asMap().entries.map((e) => RowItem( clients: clients ?? false, domain: e.value.keys.toList()[0], - number: e.value.values.toList()[0].toString(), + number: e.value.values.toList()[0].runtimeType == double + ? "${e.value.values.toList()[0].toStringAsFixed(2)}${unit != null ? ' $unit' : ''}" + : "${e.value.values.toList()[0].toString()}${unit != null ? ' $unit' : ''}", type: type, chartColor: colors[e.key], showColor: showChart, diff --git a/lib/screens/settings/general_settings/reorderable_top_items_home.dart b/lib/screens/settings/general_settings/reorderable_top_items_home.dart index b649ff5..2b7bfe1 100644 --- a/lib/screens/settings/general_settings/reorderable_top_items_home.dart +++ b/lib/screens/settings/general_settings/reorderable_top_items_home.dart @@ -1,6 +1,5 @@ // ignore_for_file: use_build_context_synchronously -import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -9,15 +8,16 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class ItemData { +class _ItemData { final HomeTopItems title; final Key key; - const ItemData({ + const _ItemData({ required this.title, required this.key }); @@ -29,7 +29,7 @@ enum DraggingMode { } class ReorderableTopItemsHome extends StatefulWidget { - const ReorderableTopItemsHome({Key? key}) : super(key: key); + const ReorderableTopItemsHome({super.key}); @override State createState() => _ReorderableTopItemsHomeState(); @@ -38,10 +38,10 @@ class ReorderableTopItemsHome extends StatefulWidget { class _ReorderableTopItemsHomeState extends State { List homeTopItemsList = []; List persistHomeTopItemsList = []; - List renderItems = []; + List<_ItemData> renderItems = []; int _indexOfKey(Key key) { - return renderItems.indexWhere((ItemData d) => d.key == key); + return renderItems.indexWhere((_ItemData d) => d.key == key); } bool _reorderCallback(Key item, Key newPosition) { @@ -79,7 +79,7 @@ class _ReorderableTopItemsHomeState extends State { homeTopItemsList = appConfigProvider.homeTopItemsOrder; persistHomeTopItemsList = appConfigProvider.homeTopItemsOrder; renderItems = appConfigProvider.homeTopItemsOrder.asMap().entries.map( - (e) => ItemData( + (e) => _ItemData( key: ValueKey(e.key), title: e.value, ) @@ -117,16 +117,31 @@ class _ReorderableTopItemsHomeState extends State { padding: const EdgeInsets.all(16) ); + case HomeTopItems.topUpstreams: + return CustomListTile( + title: AppLocalizations.of(context)!.topUpstreams, + icon: Icons.upload_file_rounded, + padding: const EdgeInsets.all(16) + ); + + case HomeTopItems.avgUpstreamResponseTime: + return CustomListTile( + title: AppLocalizations.of(context)!.averageUpstreamResponseTime, + icon: Icons.timer_rounded, + padding: const EdgeInsets.all(16) + ); + default: return const SizedBox(); } } - Future onWillPopScope() async { + Future onWillPopScope(bool popInvoked) async { if (!listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList)) { - showDialog( + await showDialog( context: context, - builder: (dialogContext) => AlertDialog( + useRootNavigator: false, + builder: (ctx) => AlertDialog( title: Text(AppLocalizations.of(context)!.discardChanges), content: Text(AppLocalizations.of(context)!.discardChangesDescription), actions: [ @@ -135,14 +150,14 @@ class _ReorderableTopItemsHomeState extends State { children: [ TextButton( onPressed: () { - Navigator.pop(dialogContext); + Navigator.pop(context); Navigator.pop(context); }, child: Text(AppLocalizations.of(context)!.confirm) ), const SizedBox(width: 8), TextButton( - onPressed: () => Navigator.pop(dialogContext), + onPressed: () => Navigator.pop(context), child: Text(AppLocalizations.of(context)!.cancel) ), ], @@ -175,8 +190,9 @@ class _ReorderableTopItemsHomeState extends State { } } - return WillPopScope( - onWillPop: onWillPopScope, + return PopScope( + canPop: listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList), + onPopInvoked: onWillPopScope, child: Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.topItemsOrder), @@ -219,7 +235,7 @@ class _ReorderableTopItemsHomeState extends State { child: ListView.builder( itemBuilder: (context, index) => reorderable_list_library.ReorderableItem( key: renderItems[index].key, - childBuilder: (context, state) => Item( + childBuilder: (context, state) => _Item( tileWidget: tile(renderItems[index].title), isFirst: index == 0, isLast: index == renderItems.length - 1, @@ -237,19 +253,18 @@ class _ReorderableTopItemsHomeState extends State { } } -class Item extends StatelessWidget { +class _Item extends StatelessWidget { final Widget tileWidget; final bool isFirst; final bool isLast; final reorderable_list_library.ReorderableItemState state; - const Item({ - Key? key, + const _Item({ required this.tileWidget, required this.isFirst, required this.isLast, required this.state, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 26b84d5..66ca288 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -10,6 +10,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/domain_options.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; @@ -18,18 +19,22 @@ import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class TopItemsScreen extends StatefulWidget { - final String type; + final HomeTopItems type; final String title; final bool? isClient; final List> data; + final bool withProgressBar; + final String? unit; const TopItemsScreen({ - Key? key, + super.key, required this.type, required this.title, this.isClient, required this.data, - }) : super(key: key); + required this.withProgressBar, + this.unit, + }); @override State createState() => _TopItemsScreenState(); @@ -60,9 +65,9 @@ class _TopItemsScreenState extends State { final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); - int total = 0; + double total = 0; for (var element in data) { - total = total + int.parse(element.values.toList()[0].toString()); + total = total + double.parse(element.values.toList()[0].toString()); } return Scaffold( @@ -154,10 +159,10 @@ class _TopItemsScreenState extends State { return DomainOptions( item: screenData[index].keys.toList()[0], - isBlocked: widget.type == 'topBlockedDomains', - isClient: widget.type == 'topClients', + isBlocked: widget.type == HomeTopItems.blockedDomains, + isDomain: widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains, onTap: () { - if (widget.type == 'topQueriedDomains' || widget.type == 'topBlockedDomains') { + if (widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains) { logsProvider.setSearchText(screenData[index].keys.toList()[0]); logsProvider.setSelectedClients(null); logsProvider.setAppliedFilters( @@ -170,7 +175,7 @@ class _TopItemsScreenState extends State { appConfigProvider.setSelectedScreen(2); Navigator.pop(context); } - else if (widget.type == 'topClients') { + else if (widget.type == HomeTopItems.recurrentClients) { logsProvider.setSearchText(null); logsProvider.setSelectedClients([screenData[index].keys.toList()[0]]); logsProvider.setAppliedFilters( @@ -187,7 +192,9 @@ class _TopItemsScreenState extends State { child: CustomListTile( title: screenData[index].keys.toList()[0], trailing: Text( - screenData[index].values.toList()[0].toString(), + screenData[index].values.toList()[0].runtimeType == double + ? "${screenData[index].values.toList()[0].toStringAsFixed(2)}${widget.unit != null ? ' ${widget.unit}' : ''}" + : "${screenData[index].values.toList()[0].toString()}${widget.unit != null ? ' ${widget.unit}' : ''}", style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant ), @@ -205,7 +212,7 @@ class _TopItemsScreenState extends State { ), const SizedBox(height: 5), ], - Row( + if (widget.withProgressBar == true) Row( children: [ SizedBox( width: 50, diff --git a/lib/screens/top_items/top_items_modal.dart b/lib/screens/top_items/top_items_modal.dart index 845459a..1325c79 100644 --- a/lib/screens/top_items/top_items_modal.dart +++ b/lib/screens/top_items/top_items_modal.dart @@ -10,6 +10,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/domain_options.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; @@ -17,18 +18,22 @@ import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class TopItemsModal extends StatefulWidget { - final String type; + final HomeTopItems type; final String title; final bool? isClient; final List> data; + final bool withProgressBar; + final String? unit; const TopItemsModal({ - Key? key, + super.key, required this.type, required this.title, this.isClient, required this.data, - }) : super(key: key); + required this.withProgressBar, + this.unit, + }); @override State createState() => _TopItemsModalState(); @@ -59,9 +64,9 @@ class _TopItemsModalState extends State { final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); - int total = 0; + double total = 0; for (var element in data) { - total = total + int.parse(element.values.toList()[0].toString()); + total = total + double.parse(element.values.toList()[0].toString()); } return Dialog( @@ -129,11 +134,11 @@ class _TopItemsModalState extends State { } return DomainOptions( - isBlocked: widget.type == 'topBlockedDomains', - isClient: widget.type == 'topClients', + isBlocked: widget.type == HomeTopItems.blockedDomains, + isDomain: widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains, item: screenData[index].keys.toList()[0], onTap: () { - if (widget.type == 'topQueriedDomains' || widget.type == 'topBlockedDomains') { + if (widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains) { logsProvider.setSearchText(screenData[index].keys.toList()[0]); logsProvider.setSelectedClients(null); logsProvider.setAppliedFilters( @@ -146,7 +151,7 @@ class _TopItemsModalState extends State { appConfigProvider.setSelectedScreen(2); Navigator.pop(context); } - else if (widget.type == 'topClients') { + else if (widget.type == HomeTopItems.recurrentClients) { logsProvider.setSearchText(null); logsProvider.setSelectedClients([screenData[index].keys.toList()[0]]); logsProvider.setAppliedFilters( @@ -163,7 +168,9 @@ class _TopItemsModalState extends State { child: CustomListTile( title: screenData[index].keys.toList()[0], trailing: Text( - screenData[index].values.toList()[0].toString(), + screenData[index].values.toList()[0].runtimeType == double + ? "${screenData[index].values.toList()[0].toStringAsFixed(2)}${widget.unit != null ? ' ${widget.unit}' : ''}" + : "${screenData[index].values.toList()[0].toString()}${widget.unit != null ? ' ${widget.unit}' : ''}", style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant ), @@ -181,7 +188,7 @@ class _TopItemsModalState extends State { ), const SizedBox(height: 5), ], - Row( + if (widget.withProgressBar == true) Row( children: [ SizedBox( width: 50, diff --git a/lib/widgets/domain_options.dart b/lib/widgets/domain_options.dart index 3c4bb79..703f63f 100644 --- a/lib/widgets/domain_options.dart +++ b/lib/widgets/domain_options.dart @@ -17,21 +17,21 @@ import 'package:adguard_home_manager/models/menu_option.dart'; class DomainOptions extends StatelessWidget { final bool isBlocked; - final bool? isClient; + final bool? isDomain; final String? item; final Widget child; final void Function() onTap; final BorderRadius? borderRadius; const DomainOptions({ - Key? key, + super.key, required this.isBlocked, - this.isClient, + this.isDomain, required this.item, required this.child, required this.onTap, this.borderRadius - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -80,12 +80,12 @@ class DomainOptions extends StatelessWidget { List generateOptions() { return [ - if (isClient != true && isBlocked == true) MenuOption( + if (isDomain == true && isBlocked == true) MenuOption( title: AppLocalizations.of(context)!.unblock, icon: Icons.check, action: () => blockUnblock(item!, 'unblock') ), - if (isClient != true && isBlocked == false) MenuOption( + if (isDomain == true && isBlocked == false) MenuOption( title: AppLocalizations.of(context)!.block, icon: Icons.block, action: () => blockUnblock(item!, 'block') From bc8aa3b670713409d591d320c48a254908fbf4d0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 25 Nov 2023 19:14:00 +0100 Subject: [PATCH 426/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index d4f6f8e..e311cd9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.11.3+108 +version: 2.12.0-beta.1+109 environment: sdk: '>=2.18.1 <3.0.0' From 63d57245a7b6e3153aec9325b3ee0a6e8482eeef Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 26 Nov 2023 05:21:35 +0100 Subject: [PATCH 427/676] Improved top items lists, improved menus and fixed units --- lib/models/menu_option.dart | 2 +- .../clients/client/active_client_tile.dart | 80 ++---- .../clients/client/added_client_tile.dart | 116 ++++----- lib/screens/clients/clients.dart | 58 +++-- lib/screens/clients/clients_lists.dart | 4 +- .../filters/filters_triple_column.dart | 2 +- lib/screens/filters/list_options_menu.dart | 8 +- lib/screens/home/home.dart | 97 +------ lib/screens/home/top_items/row_item.dart | 46 +--- .../top_items/top_item_expansion_panel.dart | 193 -------------- lib/screens/home/top_items/top_items.dart | 216 ++++++++++++---- .../home/top_items/top_items_lists.dart | 239 ++++++++++++++++++ lib/screens/logs/log_tile.dart | 93 ++++++- lib/screens/logs/logs.dart | 3 +- lib/screens/top_items/top_items.dart | 59 ++--- lib/screens/top_items/top_items_modal.dart | 61 ++--- lib/widgets/domain_options.dart | 136 ---------- lib/widgets/options_menu.dart | 63 +++++ lib/widgets/options_modal.dart | 4 +- 19 files changed, 713 insertions(+), 767 deletions(-) delete mode 100644 lib/screens/home/top_items/top_item_expansion_panel.dart create mode 100644 lib/screens/home/top_items/top_items_lists.dart delete mode 100644 lib/widgets/domain_options.dart create mode 100644 lib/widgets/options_menu.dart diff --git a/lib/models/menu_option.dart b/lib/models/menu_option.dart index e898514..b89f8d9 100644 --- a/lib/models/menu_option.dart +++ b/lib/models/menu_option.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; class MenuOption { final IconData? icon; final String title; - final void Function() action; + final void Function(dynamic) action; final bool? disabled; const MenuOption({ diff --git a/lib/screens/clients/client/active_client_tile.dart b/lib/screens/clients/client/active_client_tile.dart index 26cb30f..76c928c 100644 --- a/lib/screens/clients/client/active_client_tile.dart +++ b/lib/screens/clients/client/active_client_tile.dart @@ -1,9 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:contextmenu/contextmenu.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; @@ -16,54 +15,29 @@ class ActiveClientTile extends StatelessWidget { final AutoClient? selectedClient; const ActiveClientTile({ - Key? key, + super.key, required this.client, required this.onTap, required this.splitView, this.selectedClient - }) : super(key: key); + }); @override Widget build(BuildContext context) { - void openOptionsModal() { - showDialog( - context: context, - builder: (context) => OptionsModal( - options: [ - MenuOption( - title: AppLocalizations.of(context)!.copyClipboard, - icon: Icons.copy_rounded, - action: () { - copyToClipboard( - value: client.name != '' - ? client.name! - : client.ip, - successMessage: AppLocalizations.of(context)!.copiedClipboard, - ); - }, - ) - ] - ), - ); - } - if (splitView == true) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), - child: ContextMenuArea( - builder: (context) => [ - CustomListTile( - title: AppLocalizations.of(context)!.copyClipboard, + child: OptionsMenu( + options: [ + MenuOption( icon: Icons.copy_rounded, - onTap: () { - copyToClipboard( - value: client.name != '' - ? client.name! - : client.ip, - successMessage: AppLocalizations.of(context)!.copiedClipboard, - ); - Navigator.pop(context); - }, + title: AppLocalizations.of(context)!.copyClipboard, + action: (_) => copyToClipboard( + value: client.name != '' + ? client.name! + : client.ip, + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ) ) ], child: Material( @@ -72,10 +46,6 @@ class ActiveClientTile extends StatelessWidget { child: InkWell( borderRadius: BorderRadius.circular(28), onTap: () => onTap(client), - onLongPress: () { - Navigator.pop(context); - openOptionsModal(); - }, child: Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), @@ -128,20 +98,17 @@ class ActiveClientTile extends StatelessWidget { ); } else { - return ContextMenuArea( - builder: (context) => [ - CustomListTile( - title: AppLocalizations.of(context)!.copyClipboard, + return OptionsMenu( + options: [ + MenuOption( icon: Icons.copy_rounded, - onTap: () { - copyToClipboard( - value: client.name != '' - ? client.name! - : client.ip, - successMessage: AppLocalizations.of(context)!.copiedClipboard, - ); - Navigator.pop(context); - }, + title: AppLocalizations.of(context)!.copyClipboard, + action: (_) => copyToClipboard( + value: client.name != '' + ? client.name! + : client.ip, + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ) ) ], child: CustomListTile( @@ -158,7 +125,6 @@ class ActiveClientTile extends StatelessWidget { ), ), onTap: () => onTap(client), - onLongPress: openOptionsModal, ), ); } diff --git a/lib/screens/clients/client/added_client_tile.dart b/lib/screens/clients/client/added_client_tile.dart index 53a481a..a33578f 100644 --- a/lib/screens/clients/client/added_client_tile.dart +++ b/lib/screens/clients/client/added_client_tile.dart @@ -1,15 +1,16 @@ import 'package:flutter/material.dart'; -import 'package:contextmenu/contextmenu.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class AddedClientTile extends StatelessWidget { +class AddedClientTile extends StatefulWidget { final Client client; final void Function(Client) onTap; final void Function(Client) onLongPress; @@ -29,60 +30,48 @@ class AddedClientTile extends StatelessWidget { required this.splitView, }); + @override + State createState() => _AddedClientTileState(); +} + +class _AddedClientTileState extends State { + bool _isHover = false; + @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - if (splitView == true) { + if (widget.splitView == true) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: Material( color: Colors.transparent, borderRadius: BorderRadius.circular(28), - child: ContextMenuArea( - builder: (context) => [ - if (onEdit != null) CustomListTile( - title: AppLocalizations.of(context)!.edit, - icon: Icons.edit_rounded, - onTap: () { - Navigator.pop(context); - onEdit!(client); - } - ), - CustomListTile( - title: AppLocalizations.of(context)!.delete, - icon: Icons.delete_rounded, - onTap: () { - Navigator.pop(context); - onDelete(client); - } - ), - CustomListTile( - title: AppLocalizations.of(context)!.copyClipboard, + child: OptionsMenu( + options: [ + MenuOption( icon: Icons.copy_rounded, - onTap: () { - copyToClipboard( - value: client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), - successMessage: AppLocalizations.of(context)!.copiedClipboard, - ); - Navigator.pop(context); - } + title: AppLocalizations.of(context)!.copyClipboard, + action: (_) => copyToClipboard( + value: widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ) ), ], child: InkWell( borderRadius: BorderRadius.circular(28), - onTap: () => onTap(client), - onLongPress: () => onLongPress(client), + onTap: () => widget.onTap(widget.client), + onHover: (v) => setState(() => _isHover = v), child: Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( borderRadius: BorderRadius.circular(28), - color: client == selectedClient + color: widget.client == widget.selectedClient ? Theme.of(context).colorScheme.primaryContainer : null ), - child: Row( + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( @@ -94,7 +83,7 @@ class AddedClientTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, @@ -107,7 +96,7 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.filter_list_rounded, size: 19, - color: client.filteringEnabled == true + color: widget.client.filteringEnabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -119,7 +108,7 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.vpn_lock_rounded, size: 18, - color: client.safebrowsingEnabled == true + color: widget.client.safebrowsingEnabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -131,7 +120,7 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.block, size: 18, - color: client.parentalEnabled == true + color: widget.client.parentalEnabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -143,7 +132,7 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.search_rounded, size: 19, - color: client.safeSearch != null && client.safeSearch!.enabled == true + color: widget.client.safeSearch != null && widget.client.safeSearch!.enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -159,6 +148,14 @@ class AddedClientTile extends StatelessWidget { ], ), ), + if (widget.onEdit != null && _isHover == true) ...[ + const SizedBox(width: 8), + IconButton( + onPressed: () => widget.onEdit!(widget.client), + icon: const Icon(Icons.file_open_rounded), + tooltip: AppLocalizations.of(context)!.seeDetails, + ) + ] ], ) ), @@ -168,37 +165,30 @@ class AddedClientTile extends StatelessWidget { ); } else { - return ContextMenuArea( - builder: (context) => [ - if (onEdit != null) CustomListTile( + return OptionsMenu( + options: [ + if (widget.onEdit != null) MenuOption( title: AppLocalizations.of(context)!.seeDetails, icon: Icons.file_open_rounded, - onTap: () { - Navigator.pop(context); - onEdit!(client); - } + action: (_) => widget.onEdit!(widget.client) ), - CustomListTile( - title: AppLocalizations.of(context)!.copyClipboard, + MenuOption( icon: Icons.copy_rounded, - onTap: () { - copyToClipboard( - value: client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), - successMessage: AppLocalizations.of(context)!.copiedClipboard, - ); - Navigator.pop(context); - } + title: AppLocalizations.of(context)!.copyClipboard, + action: (_) => copyToClipboard( + value: widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ) ), ], child: CustomListTile( - onLongPress: () => onLongPress(client), - onTap: () => onTap(client), - title: client.name, + onTap: () => widget.onTap(widget.client), + title: widget.client.name, subtitleWidget: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), style: TextStyle( color: Theme.of(context).listTileTheme.textColor ), @@ -209,7 +199,7 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.filter_list_rounded, size: 19, - color: client.filteringEnabled == true + color: widget.client.filteringEnabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -221,7 +211,7 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.vpn_lock_rounded, size: 18, - color: client.safebrowsingEnabled == true + color: widget.client.safebrowsingEnabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -233,7 +223,7 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.block, size: 18, - color: client.parentalEnabled == true + color: widget.client.parentalEnabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -245,7 +235,7 @@ class AddedClientTile extends StatelessWidget { Icon( Icons.search_rounded, size: 19, - color: client.safeSearch != null && client.safeSearch!.enabled == true + color: widget.client.safeSearch != null && widget.client.safeSearch!.enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 80393a8..3d494ae 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -7,7 +7,7 @@ import 'package:adguard_home_manager/screens/clients/clients_lists.dart'; import 'package:adguard_home_manager/models/clients.dart'; class Clients extends StatefulWidget { - const Clients({Key? key}) : super(key: key); + const Clients({super.key}); @override State createState() => _ClientsState(); @@ -20,36 +20,38 @@ class _ClientsState extends State with TickerProviderStateMixin { @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - if (constraints.maxWidth > 1000) { - return SplitView.material( - hideDivider: true, - flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), - placeholder: Center( - child: Padding( - padding: const EdgeInsets.all(24), - child: Text( - AppLocalizations.of(context)!.selectClientLeftColumn, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant + return Scaffold( + body: LayoutBuilder( + builder: (context, constraints) { + if (constraints.maxWidth > 1000) { + return SplitView.material( + hideDivider: true, + flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), + placeholder: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Text( + AppLocalizations.of(context)!.selectClientLeftColumn, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), ), ), ), - ), - child: const ClientsLists( - splitView: true, - ) - ); - } - else { - return const ClientsLists( - splitView: false, - ); - } - }, + child: const ClientsLists( + splitView: true, + ) + ); + } + else { + return const ClientsLists( + splitView: false, + ); + } + }, + ), ); } } \ No newline at end of file diff --git a/lib/screens/clients/clients_lists.dart b/lib/screens/clients/clients_lists.dart index 0e518ce..bdc56b8 100644 --- a/lib/screens/clients/clients_lists.dart +++ b/lib/screens/clients/clients_lists.dart @@ -18,9 +18,9 @@ class ClientsLists extends StatefulWidget { final bool splitView; const ClientsLists({ - Key? key, + super.key, required this.splitView, - }) : super(key: key); + }); @override State createState() => _ClientsListsState(); diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 6ecdd8f..2042068 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -290,7 +290,7 @@ class FiltersTripleColumn extends StatelessWidget { MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: () => copyToClipboard( + action: (_) => copyToClipboard( value: filteringProvider.filtering!.userRules[index], successMessage: AppLocalizations.of(context)!.copiedClipboard, ) diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 2e47d36..f4337a1 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -155,12 +155,12 @@ class ListOptionsMenu extends StatelessWidget { icon: list.enabled == true ? Icons.gpp_bad_rounded : Icons.verified_user_rounded, - action: enableDisable + action: (_) => enableDisable() ), MenuOption( title: AppLocalizations.of(context)!.copyListUrl, icon: Icons.copy_rounded, - action: () => copyToClipboard( + action: (_) => copyToClipboard( value: list.url, successMessage: AppLocalizations.of(context)!.listUrlCopied ) @@ -168,12 +168,12 @@ class ListOptionsMenu extends StatelessWidget { MenuOption( title: AppLocalizations.of(context)!.openListUrl, icon: Icons.open_in_browser_rounded, - action: () => openUrl(list.url) + action: (_) => openUrl(list.url) ), MenuOption( title: AppLocalizations.of(context)!.selectionMode, icon: Icons.check_rounded, - action: openSelectionMode + action: (_) => openSelectionMode() ), ] ) diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index ec48e54..9e5de00 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -8,10 +8,10 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/home/server_status.dart'; +import 'package:adguard_home_manager/screens/home/top_items/top_items_lists.dart'; import 'package:adguard_home_manager/screens/home/combined_chart.dart'; import 'package:adguard_home_manager/screens/home/appbar.dart'; import 'package:adguard_home_manager/screens/home/fab.dart'; -import 'package:adguard_home_manager/screens/home/top_items/top_items.dart'; import 'package:adguard_home_manager/screens/home/chart.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; @@ -21,7 +21,7 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; class Home extends StatefulWidget { - const Home({Key? key}) : super(key: key); + const Home({super.key}); @override State createState() => _HomeState(); @@ -236,97 +236,4 @@ class _HomeState extends State { ), ); } -} - -class TopItemsLists extends StatelessWidget { - final List order; - - const TopItemsLists({ - super.key, - required this.order, - }); - - @override - Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - - List bottom = [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Divider( - thickness: 1, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), - ), - ), - const SizedBox(height: 16), - ]; - - return Column( - children: order.asMap().entries.map((item) { - switch (item.value) { - case HomeTopItems.queriedDomains: - return Column( - children: [ - TopItems( - label: AppLocalizations.of(context)!.topQueriedDomains, - type: HomeTopItems.queriedDomains, - ), - if (item.key < order.length - 1) ...bottom - ], - ); - - case HomeTopItems.blockedDomains: - return Column( - children: [ - TopItems( - label: AppLocalizations.of(context)!.topBlockedDomains, - type: HomeTopItems.blockedDomains, - ), - if (item.key < order.length - 1) ...bottom - ], - ); - - case HomeTopItems.recurrentClients: - return Column( - children: [ - TopItems( - label: AppLocalizations.of(context)!.topClients, - type: HomeTopItems.recurrentClients, - ), - if (item.key < order.length - 1) ...bottom - ], - ); - - case HomeTopItems.topUpstreams: - return statusProvider.serverStatus!.stats.topUpstreamResponses != null - ? Column( - children: [ - TopItems( - label: AppLocalizations.of(context)!.topUpstreams, - type: HomeTopItems.topUpstreams, - ), - if (item.key < order.length - 1) ...bottom - ], - ) - : const SizedBox(); - - case HomeTopItems.avgUpstreamResponseTime: - return statusProvider.serverStatus!.stats.topUpstreamsAvgTime != null - ? Column( - children: [ - TopItems( - label: AppLocalizations.of(context)!.averageUpstreamResponseTime, - type: HomeTopItems.avgUpstreamResponseTime, - ), - if (item.key < order.length - 1) ...bottom - ], - ) - : const SizedBox(); - - default: - return const SizedBox(); - } - }).toList(), - ); - } } \ No newline at end of file diff --git a/lib/screens/home/top_items/row_item.dart b/lib/screens/home/top_items/row_item.dart index 4e3c184..569d30c 100644 --- a/lib/screens/home/top_items/row_item.dart +++ b/lib/screens/home/top_items/row_item.dart @@ -2,12 +2,10 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/domain_options.dart'; +import 'package:adguard_home_manager/widgets/options_menu.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; class RowItem extends StatefulWidget { @@ -18,6 +16,8 @@ class RowItem extends StatefulWidget { final bool clients; final bool showColor; final String? unit; + final List options; + final void Function(dynamic)? onTapEntry; const RowItem({ super.key, @@ -27,6 +27,8 @@ class RowItem extends StatefulWidget { required this.number, required this.clients, required this.showColor, + required this.options, + this.onTapEntry, this.unit, }); @@ -80,8 +82,6 @@ class _RowItemState extends State with TickerProviderStateMixin { @override Widget build(BuildContext context) { final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); String? name; if (widget.clients == true) { @@ -94,36 +94,10 @@ class _RowItemState extends State with TickerProviderStateMixin { return Material( color: Colors.transparent, - child: DomainOptions( - item: widget.domain, - isDomain: widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains, - isBlocked: widget.type == HomeTopItems.blockedDomains, - onTap: () { - if (widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains) { - logsProvider.setSearchText(widget.domain); - logsProvider.setSelectedClients(null); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: widget.domain, - clients: null - ) - ); - appConfigProvider.setSelectedScreen(2); - } - else if (widget.type == HomeTopItems.recurrentClients) { - logsProvider.setSearchText(null); - logsProvider.setSelectedClients([widget.domain]); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: null, - clients: [widget.domain] - ) - ); - appConfigProvider.setSelectedScreen(2); - } - }, + child: OptionsMenu( + value: widget.domain, + options: widget.options, + onTap: widget.onTapEntry, child: Padding( padding: const EdgeInsets.symmetric( horizontal: 20, diff --git a/lib/screens/home/top_items/top_item_expansion_panel.dart b/lib/screens/home/top_items/top_item_expansion_panel.dart deleted file mode 100644 index eb62d01..0000000 --- a/lib/screens/home/top_items/top_item_expansion_panel.dart +++ /dev/null @@ -1,193 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; -import 'package:adguard_home_manager/screens/home/top_items/row_item.dart'; - -import 'package:adguard_home_manager/constants/enums.dart'; - -class TopItemExpansionPanel extends StatefulWidget { - final HomeTopItems type; - final String label; - final List> data; - final Map chartData; - final bool withChart; - - const TopItemExpansionPanel({ - super.key, - required this.type, - required this.label, - required this.data, - required this.chartData, - required this.withChart - }); - - @override - State createState() => _TopItemExpansionPanelState(); -} - -class _TopItemExpansionPanelState extends State { - bool _showChart = true; - - final colors = [ - Colors.red, - Colors.green, - Colors.blue, - Colors.orange, - Colors.teal, - Colors.grey - ]; - - @override - Widget build(BuildContext context) { - final width = MediaQuery.of(context).size.width; - - if (widget.withChart == true) { - return Column( - children: [ - ExpansionPanelList( - expandedHeaderPadding: const EdgeInsets.all(0), - elevation: 0, - expansionCallback: (_, isExpanded) => setState(() => _showChart = isExpanded), - animationDuration: const Duration(milliseconds: 250), - children: [ - ExpansionPanel( - headerBuilder: (context, isExpanded) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( - mainAxisAlignment: width <= 700 - ? MainAxisAlignment.spaceBetween - : MainAxisAlignment.center, - children: [ - Flexible( - child: Text( - widget.label, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - ], - ), - ), - body: Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Column( - children: [ - SizedBox( - height: 150, - child: CustomPieChart( - data: widget.chartData, - colors: colors - ) - ), - const SizedBox(height: 16), - ], - ), - ), - isExpanded: _showChart - ), - ], - ), - Padding( - padding: const EdgeInsets.only(top: 8), - child: _ItemsList( - colors: colors, - data: widget.data, - clients: widget.type == HomeTopItems.recurrentClients, - type: widget.type, - showChart: _showChart, - unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, - ), - ), - if (widget.type != HomeTopItems.avgUpstreamResponseTime) OthersRowItem( - items: widget.data, - showColor: _showChart, - ), - const SizedBox(height: 16), - ], - ); - } - else { - return Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 18), - child: Row( - mainAxisAlignment: width <= 700 - ? MainAxisAlignment.spaceBetween - : MainAxisAlignment.center, - children: [ - Flexible( - child: Text( - widget.label, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top: 16), - child: _ItemsList( - colors: colors, - data: widget.data, - clients: widget.type == HomeTopItems.recurrentClients, - type: widget.type, - showChart: false, - unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, - ), - ), - if (widget.type != HomeTopItems.avgUpstreamResponseTime) OthersRowItem( - items: widget.data, - showColor: false, - ), - const SizedBox(height: 16), - ], - ); - } - } -} - -class _ItemsList extends StatelessWidget { - final List colors; - final List> data; - final bool? clients; - final HomeTopItems type; - final bool showChart; - final String? unit; - - const _ItemsList({ - required this.colors, - required this.data, - required this.clients, - required this.type, - required this.showChart, - this.unit, - }); - - @override - Widget build(BuildContext context) { - return Column( - children: data.sublist( - 0, data.length > 5 ? 5 : data.length - ).asMap().entries.map((e) => RowItem( - clients: clients ?? false, - domain: e.value.keys.toList()[0], - number: e.value.values.toList()[0].runtimeType == double - ? "${e.value.values.toList()[0].toStringAsFixed(2)}${unit != null ? ' $unit' : ''}" - : "${e.value.values.toList()[0].toString()}${unit != null ? ' $unit' : ''}", - type: type, - chartColor: colors[e.key], - showColor: showChart, - )).toList() - ); - } -} \ No newline at end of file diff --git a/lib/screens/home/top_items/top_items.dart b/lib/screens/home/top_items/top_items.dart index 6276d74..00fa63c 100644 --- a/lib/screens/home/top_items/top_items.dart +++ b/lib/screens/home/top_items/top_items.dart @@ -7,23 +7,34 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/home/top_items/row_item.dart'; -import 'package:adguard_home_manager/screens/home/top_items/top_item_expansion_panel.dart'; import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class TopItems extends StatefulWidget { final HomeTopItems type; final String label; + final List> data; + final bool withChart; + final bool withProgressBar; + final String Function(dynamic) buildValue; + final List menuOptions; + final void Function(dynamic)? onTapEntry; const TopItems({ super.key, required this.type, required this.label, + required this.data, + required this.withChart, + required this.withProgressBar, + required this.buildValue, + required this.menuOptions, + this.onTapEntry, }); @override @@ -50,47 +61,21 @@ class _TopItemsState extends State { @override Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - final width = MediaQuery.of(context).size.width; - List> generateData() { - switch (widget.type) { - case HomeTopItems.queriedDomains: - return statusProvider.serverStatus!.stats.topQueriedDomains; - - case HomeTopItems.blockedDomains: - return statusProvider.serverStatus!.stats.topBlockedDomains; - - case HomeTopItems.recurrentClients: - return statusProvider.serverStatus!.stats.topClients; - - case HomeTopItems.topUpstreams: - return statusProvider.serverStatus!.stats.topUpstreamResponses ?? []; - - case HomeTopItems.avgUpstreamResponseTime: - return statusProvider.serverStatus!.stats.topUpstreamsAvgTime ?? []; - - default: - return []; - } - } - - final data = generateData(); - final withChart = widget.type != HomeTopItems.avgUpstreamResponseTime; Map chartData() { Map values = {}; - data.sublist(0, data.length > 5 ? 5 : data.length).forEach((element) { + widget.data.sublist(0, widget.data.length > 5 ? 5 : widget.data.length).forEach((element) { values = { ...values, element.keys.first: element.values.first.toDouble() }; }); - if (data.length > 5) { + if (widget.data.length > 5) { final int rest = List.from( - data.sublist(5, data.length).map((e) => e.values.first.toInt()) + widget.data.sublist(5, widget.data.length).map((e) => e.values.first.toInt()) ).reduce((a, b) => a + b); values = { ...values, @@ -117,8 +102,8 @@ class _TopItemsState extends State { return SizedBox( child: Column( children: [ - if (data.isEmpty) noItems, - if (data.isNotEmpty && width > 700) Padding( + if (widget.data.isEmpty) noItems, + if (widget.data.isNotEmpty && width > 700) Padding( padding: EdgeInsets.only(bottom: withChart == false ? 16 : 0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, @@ -157,14 +142,16 @@ class _TopItemsState extends State { ), _ItemsList( colors: colors, - data: data, + data: widget.data, clients: widget.type == HomeTopItems.recurrentClients, type: widget.type, showChart: withChart == true ? _showChart : false, - unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, + buildValue: widget.buildValue, + menuOptions: widget.menuOptions, + onTapEntry: widget.onTapEntry, ), if (withChart == true) OthersRowItem( - items: data, + items: widget.data, showColor: true, ) ] @@ -173,15 +160,128 @@ class _TopItemsState extends State { ], ), ), - if (data.isNotEmpty && width <= 700) TopItemExpansionPanel( - type: widget.type, - label: widget.label, - data: data, - chartData: chartData(), - withChart: withChart + if (widget.data.isNotEmpty && width <= 700) Builder( + builder: (context) { + if (widget.withChart == true) { + return Column( + children: [ + ExpansionPanelList( + expandedHeaderPadding: const EdgeInsets.all(0), + elevation: 0, + expansionCallback: (_, isExpanded) => setState(() => _showChart = isExpanded), + animationDuration: const Duration(milliseconds: 250), + children: [ + ExpansionPanel( + headerBuilder: (context, isExpanded) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: width <= 700 + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.center, + children: [ + Flexible( + child: Text( + widget.label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ), + ], + ), + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Column( + children: [ + SizedBox( + height: 150, + child: CustomPieChart( + data: chartData(), + colors: colors + ) + ), + const SizedBox(height: 16), + ], + ), + ), + isExpanded: _showChart + ), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 8), + child: _ItemsList( + colors: colors, + data: widget.data, + clients: widget.type == HomeTopItems.recurrentClients, + type: widget.type, + showChart: _showChart, + buildValue: widget.buildValue, + menuOptions: widget.menuOptions, + onTapEntry: widget.onTapEntry, + ), + ), + if (widget.withChart == true) OthersRowItem( + items: widget.data, + showColor: _showChart, + ), + const SizedBox(height: 16), + ], + ); + } + else { + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 18), + child: Row( + mainAxisAlignment: width <= 700 + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.center, + children: [ + Flexible( + child: Text( + widget.label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16), + child: _ItemsList( + colors: colors, + data: widget.data, + clients: widget.type == HomeTopItems.recurrentClients, + type: widget.type, + showChart: false, + buildValue: widget.buildValue, + menuOptions: widget.menuOptions, + onTapEntry: widget.onTapEntry, + ), + ), + if (widget.withChart == true) OthersRowItem( + items: widget.data, + showColor: false, + ), + const SizedBox(height: 16), + ], + ); + } + }, ), - if (data.length > 5) ...[ + if (widget.data.length > 5) ...[ Padding( padding: const EdgeInsets.only(right: 20), child: Row( @@ -197,9 +297,11 @@ class _TopItemsState extends State { type: widget.type, title: widget.label, isClient: widget.type == HomeTopItems.recurrentClients, - data: generateData(), - withProgressBar: widget.type != HomeTopItems.avgUpstreamResponseTime, - unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, + data: widget.data, + withProgressBar: widget.withProgressBar, + buildValue: widget.buildValue, + options: widget.menuOptions, + onTapEntry: widget.onTapEntry, ) ) } @@ -210,9 +312,11 @@ class _TopItemsState extends State { type: widget.type, title: widget.label, isClient: widget.type == HomeTopItems.recurrentClients, - data: generateData(), - withProgressBar: widget.type != HomeTopItems.avgUpstreamResponseTime, - unit: widget.type == HomeTopItems.avgUpstreamResponseTime ? 'ms' : null, + data: widget.data, + withProgressBar: widget.withProgressBar, + buildValue: widget.buildValue, + menuOptions: widget.menuOptions, + onTapEntry: widget.onTapEntry, ) ) ) @@ -247,7 +351,9 @@ class _ItemsList extends StatelessWidget { final bool? clients; final HomeTopItems type; final bool showChart; - final String? unit; + final String Function(dynamic) buildValue; + final List menuOptions; + final void Function(dynamic)? onTapEntry; const _ItemsList({ required this.colors, @@ -255,7 +361,9 @@ class _ItemsList extends StatelessWidget { required this.clients, required this.type, required this.showChart, - this.unit, + required this.buildValue, + required this.menuOptions, + this.onTapEntry, }); @override @@ -266,12 +374,12 @@ class _ItemsList extends StatelessWidget { ).asMap().entries.map((e) => RowItem( clients: clients ?? false, domain: e.value.keys.toList()[0], - number: e.value.values.toList()[0].runtimeType == double - ? "${e.value.values.toList()[0].toStringAsFixed(2)}${unit != null ? ' $unit' : ''}" - : "${e.value.values.toList()[0].toString()}${unit != null ? ' $unit' : ''}", + number: buildValue(e.value.values.toList()[0]), type: type, chartColor: colors[e.key], showColor: showChart, + options: menuOptions, + onTapEntry: onTapEntry, )).toList() ); } diff --git a/lib/screens/home/top_items/top_items_lists.dart b/lib/screens/home/top_items/top_items_lists.dart new file mode 100644 index 0000000..2f8820d --- /dev/null +++ b/lib/screens/home/top_items/top_items_lists.dart @@ -0,0 +1,239 @@ +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/home/top_items/top_items.dart'; + +import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/logs_provider.dart'; +import 'package:adguard_home_manager/functions/copy_clipboard.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; + +class TopItemsLists extends StatelessWidget { + final List order; + + const TopItemsLists({ + super.key, + required this.order, + }); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + final logsProvider = Provider.of(context); + + List bottom = [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Divider( + thickness: 1, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.2), + ), + ), + const SizedBox(height: 16), + ]; + + void filterDomainLogs({required String value}) { + logsProvider.setSearchText(value); + logsProvider.setSelectedClients(null); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: value, + clients: null + ) + ); + appConfigProvider.setSelectedScreen(2); + } + + void filterClientLogs({required String value}) { + logsProvider.setSearchText(null); + logsProvider.setSelectedClients([value]); + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: 'all', + searchText: null, + clients: [value] + ) + ); + appConfigProvider.setSelectedScreen(2); + } + + void blockUnblock({required String domain, required String newStatus}) async { + final ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.savingUserFilters); + + final rules = await statusProvider.blockUnblockDomain( + domain: domain, + newStatus: newStatus + ); + + processModal.close(); + + if (!context.mounted) return; + if (rules == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, + color: Colors.red + ); + } + } + + void copyValueClipboard(value) { + copyToClipboard(value: value, successMessage: AppLocalizations.of(context)!.copiedClipboard); + } + + return Column( + children: order.asMap().entries.map((item) { + switch (item.value) { + case HomeTopItems.queriedDomains: + return Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.topQueriedDomains, + type: HomeTopItems.queriedDomains, + data: statusProvider.serverStatus?.stats.topQueriedDomains ?? [], + withChart: true, + withProgressBar: true, + buildValue: (v) => v.toString(), + menuOptions: [ + MenuOption( + title: AppLocalizations.of(context)!.blockDomain, + icon: Icons.block_rounded, + action: (v) => blockUnblock(domain: v.toString(), newStatus: 'block') + ), + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: copyValueClipboard + ), + ], + onTapEntry: (v) => filterDomainLogs(value: v.toString()), + ), + if (item.key < order.length - 1) ...bottom + ], + ); + + case HomeTopItems.blockedDomains: + return Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.topBlockedDomains, + type: HomeTopItems.blockedDomains, + data: statusProvider.serverStatus?.stats.topBlockedDomains ?? [], + withChart: true, + withProgressBar: true, + buildValue: (v) => v.toString(), + menuOptions: [ + MenuOption( + title: AppLocalizations.of(context)!.unblockDomain, + icon: Icons.check_rounded, + action: (v) => blockUnblock(domain: v, newStatus: 'unblock') + ), + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: copyValueClipboard + ) + ], + onTapEntry: (v) => filterDomainLogs(value: v), + ), + if (item.key < order.length - 1) ...bottom + ], + ); + + case HomeTopItems.recurrentClients: + return Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.topClients, + type: HomeTopItems.recurrentClients, + data: statusProvider.serverStatus?.stats.topClients ?? [], + withChart: true, + withProgressBar: true, + buildValue: (v) => v.toString(), + menuOptions: [ + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: copyValueClipboard + ) + ], + onTapEntry: (v) => filterClientLogs(value: v), + ), + if (item.key < order.length - 1) ...bottom + ], + ); + + case HomeTopItems.topUpstreams: + return statusProvider.serverStatus!.stats.topUpstreamResponses != null + ? Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.topUpstreams, + type: HomeTopItems.topUpstreams, + data: statusProvider.serverStatus?.stats.topUpstreamResponses ?? [], + withChart: true, + withProgressBar: true, + buildValue: (v) => v.toString(), + menuOptions: [ + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: copyValueClipboard + ) + ], + ), + if (item.key < order.length - 1) ...bottom + ], + ) + : const SizedBox(); + + case HomeTopItems.avgUpstreamResponseTime: + return statusProvider.serverStatus!.stats.topUpstreamsAvgTime != null + ? Column( + children: [ + TopItems( + label: AppLocalizations.of(context)!.averageUpstreamResponseTime, + type: HomeTopItems.avgUpstreamResponseTime, + data: statusProvider.serverStatus?.stats.topUpstreamsAvgTime ?? [], + withChart: false, + withProgressBar: false, + buildValue: (v) => "${doubleFormat(v*1000, Platform.localeName)} ms", + menuOptions: [ + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: copyValueClipboard + ) + ], + ), + if (item.key < order.length - 1) ...bottom + ], + ) + : const SizedBox(); + + default: + return const SizedBox(); + } + }).toList(), + ); + } +} \ No newline at end of file diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 14c5262..95981e8 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -2,9 +2,15 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/domain_options.dart'; +import 'package:adguard_home_manager/widgets/options_menu.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/functions/copy_clipboard.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; import 'package:adguard_home_manager/models/logs.dart'; @@ -20,7 +26,7 @@ class LogTile extends StatelessWidget { final bool twoColumns; const LogTile({ - Key? key, + super.key, required this.log, required this.length, required this.index, @@ -28,11 +34,12 @@ class LogTile extends StatelessWidget { required this.onLogTap, this.useAlwaysNormalTile, required this.twoColumns, - }) : super(key: key); + }); @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); + final statusProvider = Provider.of(context); Widget logStatusWidget({ required IconData icon, @@ -83,16 +90,63 @@ class LogTile extends StatelessWidget { } } + void blockUnblock({required String domain, required String newStatus}) async { + final ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.savingUserFilters); + + final rules = await statusProvider.blockUnblockDomain( + domain: domain, + newStatus: newStatus + ); + + processModal.close(); + + if (!context.mounted) return; + if (rules == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, + color: Colors.red + ); + } + } + + final domainBlocked = isDomainBlocked(log.reason); + if (twoColumns && !(useAlwaysNormalTile == true)) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: InkWell( borderRadius: BorderRadius.circular(28), - child: DomainOptions( - onTap: () => onLogTap(log), + child: OptionsMenu( + onTap: (_) => onLogTap(log), borderRadius: BorderRadius.circular(28), - item: log.question.name, - isBlocked: isDomainBlocked(log.reason), + options: [ + if (log.question.name != null) MenuOption( + title: domainBlocked == true + ? AppLocalizations.of(context)!.unblockDomain + : AppLocalizations.of(context)!.blockDomain, + icon: domainBlocked == true + ? Icons.check_rounded + : Icons.block_rounded, + action: (_) => blockUnblock( + domain: log.question.name!, + newStatus: domainBlocked == true ? 'unblock' : 'block' + ) + ), + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: (v) => copyToClipboard(value: v, successMessage: AppLocalizations.of(context)!.copiedClipboard) + ) + ], child: Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), @@ -250,10 +304,27 @@ class LogTile extends StatelessWidget { else { return Material( color: Colors.transparent, - child: DomainOptions( - onTap: () => onLogTap(log), - item: log.question.name, - isBlocked: isDomainBlocked(log.reason), + child: OptionsMenu( + onTap: (_) => onLogTap(log), + options: [ + if (log.question.name != null) MenuOption( + title: domainBlocked == true + ? AppLocalizations.of(context)!.unblockDomain + : AppLocalizations.of(context)!.blockDomain, + icon: domainBlocked == true + ? Icons.check_rounded + : Icons.block_rounded, + action: (_) => blockUnblock( + domain: log.question.name!, + newStatus: domainBlocked == true ? 'unblock' : 'block' + ) + ), + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: (v) => copyToClipboard(value: v, successMessage: AppLocalizations.of(context)!.copiedClipboard) + ) + ], child: Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index c1510c3..757c949 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -1,11 +1,12 @@ // ignore_for_file: use_build_context_synchronously -import 'package:adguard_home_manager/models/logs.dart'; import 'package:flutter/material.dart'; import 'package:adguard_home_manager/screens/logs/logs_list.dart'; import 'package:adguard_home_manager/screens/logs/details/log_details_screen.dart'; +import 'package:adguard_home_manager/models/logs.dart'; + class Logs extends StatefulWidget { const Logs({Key? key}) : super(key: key); diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 66ca288..498ce75 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -7,12 +7,11 @@ import 'package:percent_indicator/percent_indicator.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/domain_options.dart'; +import 'package:adguard_home_manager/widgets/options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; @@ -24,7 +23,9 @@ class TopItemsScreen extends StatefulWidget { final bool? isClient; final List> data; final bool withProgressBar; - final String? unit; + final String Function(dynamic) buildValue; + final List menuOptions; + final void Function(dynamic)? onTapEntry; const TopItemsScreen({ super.key, @@ -33,7 +34,9 @@ class TopItemsScreen extends StatefulWidget { this.isClient, required this.data, required this.withProgressBar, - this.unit, + required this.buildValue, + required this.menuOptions, + this.onTapEntry, }); @override @@ -63,7 +66,6 @@ class _TopItemsScreenState extends State { Widget build(BuildContext context) { final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); double total = 0; for (var element in data) { @@ -157,44 +159,19 @@ class _TopItemsScreenState extends State { } } - return DomainOptions( - item: screenData[index].keys.toList()[0], - isBlocked: widget.type == HomeTopItems.blockedDomains, - isDomain: widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains, - onTap: () { - if (widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains) { - logsProvider.setSearchText(screenData[index].keys.toList()[0]); - logsProvider.setSelectedClients(null); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: screenData[index].keys.toList()[0], - clients: null - ) - ); - appConfigProvider.setSelectedScreen(2); - Navigator.pop(context); - } - else if (widget.type == HomeTopItems.recurrentClients) { - logsProvider.setSearchText(null); - logsProvider.setSelectedClients([screenData[index].keys.toList()[0]]); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: null, - clients: [screenData[index].keys.toList()[0]] - ) - ); - appConfigProvider.setSelectedScreen(2); - Navigator.pop(context); - } - }, + return OptionsMenu( + value: screenData[index].keys.toList()[0], + options: widget.menuOptions, + onTap: widget.onTapEntry != null + ? (v) { + widget.onTapEntry!(v); + Navigator.pop(context); + } + : null, child: CustomListTile( title: screenData[index].keys.toList()[0], trailing: Text( - screenData[index].values.toList()[0].runtimeType == double - ? "${screenData[index].values.toList()[0].toStringAsFixed(2)}${widget.unit != null ? ' ${widget.unit}' : ''}" - : "${screenData[index].values.toList()[0].toString()}${widget.unit != null ? ' ${widget.unit}' : ''}", + widget.buildValue(screenData[index].values.toList()[0]), style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant ), diff --git a/lib/screens/top_items/top_items_modal.dart b/lib/screens/top_items/top_items_modal.dart index 1325c79..36ea793 100644 --- a/lib/screens/top_items/top_items_modal.dart +++ b/lib/screens/top_items/top_items_modal.dart @@ -7,15 +7,13 @@ import 'package:percent_indicator/percent_indicator.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/domain_options.dart'; +import 'package:adguard_home_manager/widgets/options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; class TopItemsModal extends StatefulWidget { final HomeTopItems type; @@ -23,7 +21,9 @@ class TopItemsModal extends StatefulWidget { final bool? isClient; final List> data; final bool withProgressBar; - final String? unit; + final String Function(dynamic) buildValue; + final List options; + final void Function(dynamic)? onTapEntry; const TopItemsModal({ super.key, @@ -32,7 +32,9 @@ class TopItemsModal extends StatefulWidget { this.isClient, required this.data, required this.withProgressBar, - this.unit, + required this.buildValue, + required this.options, + this.onTapEntry, }); @override @@ -61,8 +63,6 @@ class _TopItemsModalState extends State { @override Widget build(BuildContext context) { final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); double total = 0; for (var element in data) { @@ -133,44 +133,19 @@ class _TopItemsModalState extends State { } } - return DomainOptions( - isBlocked: widget.type == HomeTopItems.blockedDomains, - isDomain: widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains, - item: screenData[index].keys.toList()[0], - onTap: () { - if (widget.type == HomeTopItems.queriedDomains || widget.type == HomeTopItems.blockedDomains) { - logsProvider.setSearchText(screenData[index].keys.toList()[0]); - logsProvider.setSelectedClients(null); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: screenData[index].keys.toList()[0], - clients: null - ) - ); - appConfigProvider.setSelectedScreen(2); - Navigator.pop(context); - } - else if (widget.type == HomeTopItems.recurrentClients) { - logsProvider.setSearchText(null); - logsProvider.setSelectedClients([screenData[index].keys.toList()[0]]); - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: null, - clients: [screenData[index].keys.toList()[0]] - ) - ); - appConfigProvider.setSelectedScreen(2); - Navigator.pop(context); - } - }, + return OptionsMenu( + options: widget.options, + value: screenData[index].keys.toList()[0], + onTap: widget.onTapEntry != null + ? (v) { + widget.onTapEntry!(v); + Navigator.pop(context); + } + : null, child: CustomListTile( title: screenData[index].keys.toList()[0], trailing: Text( - screenData[index].values.toList()[0].runtimeType == double - ? "${screenData[index].values.toList()[0].toStringAsFixed(2)}${widget.unit != null ? ' ${widget.unit}' : ''}" - : "${screenData[index].values.toList()[0].toString()}${widget.unit != null ? ' ${widget.unit}' : ''}", + widget.buildValue(screenData[index].values.toList()[0]), style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant ), diff --git a/lib/widgets/domain_options.dart b/lib/widgets/domain_options.dart deleted file mode 100644 index 703f63f..0000000 --- a/lib/widgets/domain_options.dart +++ /dev/null @@ -1,136 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:flutter/material.dart'; -import 'package:contextmenu/contextmenu.dart'; -import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/widgets/options_modal.dart'; -import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; - -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/models/menu_option.dart'; - -class DomainOptions extends StatelessWidget { - final bool isBlocked; - final bool? isDomain; - final String? item; - final Widget child; - final void Function() onTap; - final BorderRadius? borderRadius; - - const DomainOptions({ - super.key, - required this.isBlocked, - this.isDomain, - required this.item, - required this.child, - required this.onTap, - this.borderRadius - }); - - @override - Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - void blockUnblock(String domain, String newStatus) async { - final ProcessModal processModal = ProcessModal(); - processModal.open(AppLocalizations.of(context)!.savingUserFilters); - - final rules = await statusProvider.blockUnblockDomain( - domain: domain, - newStatus: newStatus - ); - - processModal.close(); - - if (rules == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.userFilteringRulesUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, - color: Colors.red - - ); - } - } - - void copyDomainClipboard(String domain) async { - await Clipboard.setData( - ClipboardData(text: domain) - ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.domainCopiedClipboard), - backgroundColor: Colors.green, - ) - ); - } - - List generateOptions() { - return [ - if (isDomain == true && isBlocked == true) MenuOption( - title: AppLocalizations.of(context)!.unblock, - icon: Icons.check, - action: () => blockUnblock(item!, 'unblock') - ), - if (isDomain == true && isBlocked == false) MenuOption( - title: AppLocalizations.of(context)!.block, - icon: Icons.block, - action: () => blockUnblock(item!, 'block') - ), - MenuOption( - title: AppLocalizations.of(context)!.copyClipboard, - icon: Icons.copy, - action: () => copyDomainClipboard(item!) - ), - ]; - } - - void openOptionsModal() { - showDialog( - context: context, - builder: (context) => OptionsModal( - options: generateOptions(), - ) - ); - } - - if (item != null) { - return Material( - color: Colors.transparent, - borderRadius: borderRadius, - child: ContextMenuArea( - builder: (context) => generateOptions().map((opt) => CustomListTile( - title: opt.title, - icon: opt.icon, - onTap: () { - opt.action(); - Navigator.pop(context); - }, - )).toList(), - child: InkWell( - onTap: onTap, - onLongPress: openOptionsModal, - borderRadius: borderRadius, - child: child, - ), - ), - ); - } - else { - return child; - } - } -} \ No newline at end of file diff --git a/lib/widgets/options_menu.dart b/lib/widgets/options_menu.dart new file mode 100644 index 0000000..34b755b --- /dev/null +++ b/lib/widgets/options_menu.dart @@ -0,0 +1,63 @@ +import 'dart:io'; + +import 'package:contextmenu/contextmenu.dart'; +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/widgets/options_modal.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + +import 'package:adguard_home_manager/models/menu_option.dart'; + +class OptionsMenu extends StatelessWidget { + final Widget child; + final List options; + final dynamic value; + final BorderRadius? borderRadius; + final void Function(dynamic)? onTap; + + const OptionsMenu({ + super.key, + required this.child, + required this.options, + this.value, + this.borderRadius, + this.onTap, + }); + + @override + Widget build(BuildContext context) { + void openOptionsModal() { + showDialog( + context: context, + builder: (context) => OptionsModal( + options: options, + value: value + ) + ); + } + + return Material( + color: Colors.transparent, + child: ContextMenuArea( + builder: (context) => options.map((opt) => CustomListTile( + title: opt.title, + icon: opt.icon, + onTap: () { + opt.action(value); + Navigator.pop(context); + }, + )).toList(), + child: InkWell( + onTap: onTap != null + ? () => onTap!(value) + : null, + onLongPress: (Platform.isAndroid || Platform.isIOS) + ? () => openOptionsModal() + : null, + borderRadius: borderRadius, + child: child, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/options_modal.dart b/lib/widgets/options_modal.dart index 75a55a5..102f7ca 100644 --- a/lib/widgets/options_modal.dart +++ b/lib/widgets/options_modal.dart @@ -6,10 +6,12 @@ import 'package:adguard_home_manager/widgets/custom_list_tile_dialog.dart'; class OptionsModal extends StatelessWidget { final List options; + final dynamic value; const OptionsModal({ super.key, required this.options, + this.value, }); @override @@ -43,7 +45,7 @@ class OptionsModal extends StatelessWidget { icon: opt.icon, onTap: () { Navigator.pop(context); - opt.action(); + opt.action(value); }, )).toList() ), From 450390edbaa45047a15745a4b49d2b509a9d0d41 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 26 Nov 2023 05:22:50 +0100 Subject: [PATCH 428/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index e311cd9..8770025 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.12.0-beta.1+109 +version: 2.12.0-beta.2+110 environment: sdk: '>=2.18.1 <3.0.0' From 0c0f78c8d8f026d6502943cd17b2ccd0beef7195 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 26 Nov 2023 14:51:28 +0100 Subject: [PATCH 429/676] Updated turkish translation --- lib/l10n/app_tr.arb | 84 +++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 1fdb739..06c3b08 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -176,7 +176,7 @@ "generalSettings": "Genel ayarlar", "generalSettingsDescription": "Çeşitli farklı ayarları yönet", "hideZeroValues": "Sıfır değerlerini gizle", - "hideZeroValuesDescription": "Ana ekranda, değeri sıfır olan blokları gizler", + "hideZeroValuesDescription": "Ana ekranda, değeri sıfır olan blokları gizler.", "webAdminPanel": "Web yönetim paneli", "visitGooglePlay": "Google Play sayfasını ziyaret et", "gitHub": "Kaynak kodlarına GitHub'dan ulaşabilirsiniz", @@ -192,17 +192,17 @@ "enableFiltering": "Filtrelemeyi etkinleştir", "enableSafeBrowsing": "Güvenli gezintiyi etkinleştir", "enableParentalControl": "Ebeveyn kontrolünü etkinleştir", - "enableSafeSearch": "Güvenli aramayı etkinleştir", + "enableSafeSearch": "Güvenli aramayı aktif et", "blockedServices": "Engellenen hizmetler", "selectBlockedServices": "Engellenen hizmetleri seç", "noBlockedServicesSelected": "Engellenen hizmetler seçilmedi", "services": "Hizmetler", "servicesBlocked": "Hizmetler engellendi", "tagsSelected": "Seçilen etiketler", - "upstreamServers": "Üst akış sunucuları", + "upstreamServers": "Üst kaynak sunucuları", "serverAddress": "Sunucu adresi", - "noUpstreamServers": "Üst akış sunucusu yok.", - "willBeUsedGeneralServers": "Genel üst akış sunucuları kullanılacak.", + "noUpstreamServers": "Üst kaynak sunucusu yok.", + "willBeUsedGeneralServers": "Genel üst kaynak sunucuları kullanılacak.", "added": "Eklenenler", "clientUpdatedSuccessfully": "İstemci başarıyla güncellendi", "clientNotUpdated": "İstemci güncellenemedi", @@ -283,7 +283,7 @@ "clientsNotLoaded": "İstemciler yüklenemedi.", "noAllowedClients": "İzin verilmiş istemci yok", "allowedClientsDescription": "Eğer bu liste girdiler içeriyorsa, AdGuard Home yalnızca bu istemcilerden gelen talepleri kabul edecektir.", - "blockedClientsDescription": "Bu liste girdiler içeriyorsa, AdGuard Home bu istemcilerden gelen talepleri reddedecektir. Bu alan, İzin Verilen İstemciler'de girdi varsa görmezden gelinir.", + "blockedClientsDescription": "Bu liste girdileri içeriyorsa, AdGuard Home bu istemcilerden gelen talepleri reddedecektir. Bu alan adı, İzin Verilen İstemciler'de girdi varsa görmezden gelinir.", "disallowedDomainsDescription": "AdGuard Home, bu alan adlarına uyan DNS sorgularını reddeder ve bu sorgular sorgu günlüğünde bile görünmez.", "addClientFieldDescription": "CIDR'ler, IP adresi veya ClientID", "clientIdentifier": "İstemci tanımlayıcısı", @@ -293,15 +293,15 @@ "domainNotAdded": "Alan adı eklenemedi", "statusSelected": "Durum seçildi.", "updateLists": "Listeleri güncelle", - "checkHostFiltered": "Ana bilgisayarı kontrol et", + "checkHostFiltered": "Filtrelemeyi kontrol et", "updatingLists": "Listeler güncelleniyor...", "listsUpdated": "Listeler güncellendi", "listsNotUpdated": "Listeler güncellenemedi", "listsNotLoaded": "Listeler yüklenemedi", "domainNotValid": "Alan adı geçersiz", "check": "Kontrol et", - "checkingHost": "Ana bilgisayar kontrol ediliyor", - "errorCheckingHost": "Ana bilgisayar kontrol edilemedi", + "checkingHost": "Kontrol ediliyor", + "errorCheckingHost": "Kontrol etme başarısız", "block": "Engelle", "unblock": "Engeli kaldır", "custom": "Özel", @@ -336,7 +336,7 @@ "updating": "Değerler güncelleniyor...", "blockedServicesUpdated": "Engellenen hizmetler başarıyla güncellendi", "blockedServicesNotUpdated": "Engellenen hizmetler güncellenemedi", - "insertDomain": "Durumu kontrol etmek için bir alan adı ekleyin.", + "insertDomain": "Filtreleme durumunu kontrol etmek için bir alan adı ekleyin.", "dhcpSettings": "DHCP ayarları", "dhcpSettingsDescription": "DHCP sunucusunu yapılandır", "dhcpSettingsNotLoaded": "DHCP ayarları yüklenemedi", @@ -394,18 +394,18 @@ "noLeases": "Kullanılabilir DHCP kiralaması yok", "dnsRewrites": "DNS yeniden yazımları", "dnsRewritesDescription": "Özel DNS kurallarını yapılandır", - "loadingRewriteRules": "Yeniden yazma kuralları yükleniyor...", - "rewriteRulesNotLoaded": "DNS yeniden yazma kuralları yüklenemedi.", + "loadingRewriteRules": "Yeniden yazım kuralları yükleniyor...", + "rewriteRulesNotLoaded": "DNS yeniden yazım kuralları yüklenemedi.", "noRewriteRules": "DNS yeniden yazım kuralları yok", "answer": "Yanıt", "deleteDnsRewrite": "DNS yeniden yazımı sil", - "deleteDnsRewriteMessage": "Bu DNS yeniden yazmasını silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.", - "dnsRewriteRuleDeleted": "DNS yeniden yazma kuralı başarıyla silindi", - "dnsRewriteRuleNotDeleted": "DNS yeniden yazma kuralı silinemedi", + "deleteDnsRewriteMessage": "Bu DNS yeniden yazımını silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.", + "dnsRewriteRuleDeleted": "DNS yeniden yazım kuralı başarıyla silindi", + "dnsRewriteRuleNotDeleted": "DNS yeniden yazım kuralı silinemedi", "addDnsRewrite": "DNS yeniden yazımı ekle", - "addingRewrite": "Yeniden yazma ekleniyor...", - "dnsRewriteRuleAdded": "DNS yeniden yazma kuralı başarıyla eklendi", - "dnsRewriteRuleNotAdded": "DNS yeniden yazma kuralı eklenemedi", + "addingRewrite": "Yeniden yazım ekleniyor...", + "dnsRewriteRuleAdded": "DNS yeniden yazım kuralı başarıyla eklendi", + "dnsRewriteRuleNotAdded": "DNS yeniden yazım kuralı eklenemedi", "logsSettings": "Günlük ayarları", "enableLog": "Günlüğü etkinleştir", "clearLogs": "Günlükleri temizle", @@ -422,33 +422,33 @@ "deletingLogs": "Günlükler temizleniyor...", "logsCleared": "Günlükler başarıyla temizlendi", "logsNotCleared": "Günlükler temizlenemedi", - "runningHomeAssistant": "Ev Asistanı üzerinde çalıştır", + "runningHomeAssistant": "Ev asistanı üzerinde çalıştır", "serverError": "Sunucu hatası", "noItems": "Burada gösterilecek öğe yok", "dnsSettings": "DNS ayarları", "dnsSettingsDescription": "DNS sunucuları ile bağlantıyı yapılandır", - "upstreamDns": "Üst akış DNS sunucuları", + "upstreamDns": "Üst kaynak DNS sunucuları", "bootstrapDns": "Önyükleme DNS sunucuları", - "noUpstreamDns": "Üst akış DNS sunucuları eklenmedi.", + "noUpstreamDns": "Üst kaynak DNS sunucuları eklenmedi.", "dnsMode": "DNS modu", "noDnsMode": "DNS modu seçili değil", "loadBalancing": "Yük dengeleme", "parallelRequests": "Paralel istekler", "fastestIpAddress": "En hızlı IP adresi", - "loadBalancingDescription": "Her seferinde bir üst akış sunucusuna sorgu yap. AdGuard Home, sunucuyu seçmek için ağırlıklı rastgele algoritmasını kullanır, böylece en hızlı sunucu daha sık kullanılır.", - "parallelRequestsDescription": "Tüm üst akış sunucularını aynı anda sorgulayarak çözümlemeyi hızlandırmak için paralel sorgular kullanın.", + "loadBalancingDescription": "Her seferinde bir üst kaynak sunucusuna sorgu yap. AdGuard Home, sunucuyu seçmek için ağırlıklı rastgele algoritmasını kullanır, böylece en hızlı sunucu daha sık kullanılır.", + "parallelRequestsDescription": "Tüm üst kaynak sunucularını aynı anda sorgulayarak çözümlemeyi hızlandırmak için paralel sorgular kullanın.", "fastestIpAddressDescription": "Tüm DNS sunucularına sorgu yapın ve tüm yanıtlar arasında en hızlı IP adresini döndürün. Bu, AdGuard Home'un tüm DNS sunucularından yanıtları beklemesi gerektiği için DNS sorgularını yavaşlatır, ancak genel bağlantıyı iyileştirir.", "noBootstrapDns": "Önyükleme DNS sunucuları eklenmedi.", - "bootstrapDnsServersInfo": "Önyükleme ​​DNS sunucuları, üst akışlarda belirttiğiniz DoH/DoT çözümleyicilerinin IP adreslerini çözmek için kullanılır.", + "bootstrapDnsServersInfo": "Önyükleme ​​DNS sunucuları, üst kaynaklarda belirttiğiniz DoH/DoT çözümleyicilerinin IP adreslerini çözmek için kullanılır.", "privateReverseDnsServers": "Özel ters DNS sunucuları", "privateReverseDnsServersDescription": "AdGuard Home'un yerel PTR sorguları için kullandığı DNS sunucuları. Bu sunucular, özel IP aralıklarındaki adresler için ters DNS kullanarak PTR isteklerini çözmek için kullanılır, örneğin '192.168.12.34' olarak ayarlanmamışsa AdGuard Home, AdGuard Home'un kendi adresleri dışında, işletim sisteminizin varsayılan DNS çözümleyicilerinin adreslerini kullanır.", "reverseDnsDefault": "Varsayılan olarak, AdGuard Home aşağıdaki ters DNS çözümleyicilerini kullanır", "addItem": "Öğe ekle", "noServerAddressesAdded": "Sunucu adresleri eklenmedi.", "usePrivateReverseDnsResolvers": "Özel ters DNS çözümleyicilerini kullan", - "usePrivateReverseDnsResolversDescription": "Bu üst akış sunucularını kullanarak yerel olarak sunulan adresler için ters DNS sorguları gerçekleştirin. Devre dışı bırakılırsa, AdGuard Home, DHCP, /etc/hosts vb. kaynaklardan bilinen istemciler dışında tüm PTR isteklerine NXDOMAIN yanıtı verir.", + "usePrivateReverseDnsResolversDescription": "Bu üst kaynak sunucularını kullanarak yerel olarak sunulan adresler için ters DNS sorguları gerçekleştirin. Devre dışı bırakılırsa, AdGuard Home, DHCP, /etc/hosts vb. kaynaklardan bilinen istemciler dışında tüm PTR isteklerine NXDOMAIN yanıtı verir.", "enableReverseResolving": "İstemcilerin IP adreslerinin ters çözümlemesini etkinleştir", - "enableReverseResolvingDescription": "İstemcilerin IP adreslerini karşılık gelen çözücülere PTR sorguları göndererek IP adreslerini tersine çözümleyerek (yerel istemciler için özel DNS sunucuları, genel IP adresine sahip istemciler için yukarı akış sunucuları) istemcilerin ana bilgisayar adlarını tersine çöz.", + "enableReverseResolvingDescription": "İstemcilerin IP adreslerini karşılık gelen çözücülere PTR sorguları göndererek IP adreslerini tersine çözümleyerek (yerel istemciler için özel DNS sunucuları, genel IP adresine sahip istemciler için üst kaynak sunucuları) istemcilerin ana bilgisayar adlarını tersine çöz.", "dnsServerSettings": "AdGuard Home DNS sunucusu ayarları", "limitRequestsSecond": "Saniye başına sınırlama isteği", "valueNotNumber": "Değer bir sayı değil", @@ -460,13 +460,13 @@ "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını bırakın (AAAA yazın) ve HTTPS yanıtlarından IPv6 ipuçlarını kaldırın.", "blockingMode": "Engelleme modu", "defaultMode": "Varsayılan", - "defaultDescription": "Reklam engelleme tarzı bir kural tarafından engellendiğinde sıfır IP adresi ile yanıt verin (A için 0.0.0.0; :: AAAA için) /etc/hosts tarzı bir kural tarafından engellendiğinde kuralda belirtilen IP adresi ile yanıt verin", - "refusedDescription": "REFUSED kodu ile yanıt verin", - "nxdomainDescription": "NXDOMAIN kodu ile yanıt verin", + "defaultDescription": "Reklam engelleme tarzı bir kural tarafından engellendiğinde sıfır IP adresi ile yanıt verin. (A için 0.0.0.0; :: AAAA için) /etc/hosts tarzı bir kural tarafından engellendiğinde kuralda belirtilen IP adresi ile yanıt verin.", + "refusedDescription": "REFUSED kodu ile yanıt verin.", + "nxdomainDescription": "NXDOMAIN kodu ile yanıt verin.", "nullIp": "Boş IP", - "nullIpDescription": "Sıfır IP adresi ile yanıt verin (A için 0.0.0.0; :: AAAA için)", + "nullIpDescription": "Sıfır IP adresi ile yanıt verin. (A için 0.0.0.0; :: AAAA için)", "customIp": "Özel IP", - "customIpDescription": "Manuel olarak ayarlanmış bir IP adresi ile yanıt verin", + "customIpDescription": "Manuel olarak ayarlanmış bir IP adresi ile yanıt verin.", "dnsCacheConfig": "DNS önbellek yapılandırması", "cacheSize": "Önbellek boyutu", "inBytes": "Bayt olarak", @@ -487,7 +487,7 @@ "dnsConfigNotSaved": "DNS sunucusu yapılandırması kaydedilemedi", "savingConfig": "Yapılandırma kaydediliyor...", "someValueNotValid": "Bazı değerler geçerli değil", - "upstreamDnsDescription": "Üst akış sunucularını ve DNS modunu yapılandır", + "upstreamDnsDescription": "Üst kaynak sunucularını ve DNS modunu yapılandır", "bootstrapDnsDescription": "Önyükleme DNS sunucularını yapılandır", "privateReverseDnsDescription": "Özel DNS çözümleyicileri yapılandır ve özel ters DNS çözümlemeyi etkinleştir", "dnsServerSettingsDescription": "Hız limiti, engelleme modu ve daha fazlasını yapılandır", @@ -551,7 +551,7 @@ "deepOrange": "Koyu turuncu", "indigo": "Çivit mavisi", "useThemeColorStatus": "Durum için tema rengini kullan", - "useThemeColorStatusDescription": "Yeşil ve kırmızı durum renklerini tema rengi ve gri ile değiştirir", + "useThemeColorStatusDescription": "Yeşil ve kırmızı durum renklerini tema rengi ve gri ile değiştirir.", "invalidCertificateChain": "Geçersiz sertifika zinciri", "validCertificateChain": "Geçerli sertifika zinciri", "subject": "Konu", @@ -624,18 +624,18 @@ "unsupprtedVersionMessage": "Sunucu sürümünüz {version} için destek garantisi verilmiyor. Bu uygulamanın bu sunucu sürümüyle çalışmasında bazı sorunlar olabilir. AdGuard Home Yöneticisi, AdGuard Home sunucunun kararlı sürümleriyle çalışacak şekilde tasarlanmıştır. Alfa ve beta sürümleriyle çalışabilir, ancak uyumluluk garanti edilmez ve uygulama bu sürümlerle çalışırken bazı sorunlar yaşayabilir.", "iUnderstand": "Anladım", "appUpdates": "Uygulama güncellemeleri", - "usingLatestVersion": "En son sürümü kullanıyorsunuz", + "usingLatestVersion": "En son sürümü kullanıyorsunuz :)", "ipLogs": "Günlüklerdeki IP", "ipLogsDescription": "Günlükler listesinde istemci adı yerine IP adresini göster", "application": "Uygulama", "combinedChart": "Birleştirilmiş grafik", - "combinedChartDescription": "Tüm grafikleri bir araya getirir", + "combinedChartDescription": "Tüm grafikleri bir araya getirir.", "statistics": "İstatistikler", "errorLoadFilters": "Filtreler yüklenirken hata oluştu.", "clientRemovedSuccessfully": "İstemci başarıyla kaldırıldı.", - "editRewriteRule": "Yeniden yazma kuralını düzenle", - "dnsRewriteRuleUpdated": "DNS yeniden yazma kuralı başarıyla güncellendi", - "dnsRewriteRuleNotUpdated": "DNS yeniden yazma kuralı güncellenemedi", + "editRewriteRule": "Yeniden yazım kuralını düzenle", + "dnsRewriteRuleUpdated": "DNS yeniden yazım kuralı başarıyla güncellendi", + "dnsRewriteRuleNotUpdated": "DNS yeniden yazım kuralı güncellenemedi", "updatingRule": "Kural güncelleniyor...", "serverUpdateNeeded": "Sunucu güncellemesi gerekli", "updateYourServer": "Bu özelliği kullanmak için AdGuard Home sunucunuzu {version} veya üzeri bir sürüme güncelleyin.", @@ -657,7 +657,7 @@ "quickFilters": "Hızlı filtreler", "searchDomainInternet": "İnternette alan adı ara", "hideServerAddress": "Sunucu adresini gizle", - "hideServerAddressDescription": "Ana ekranda sunucu adresini gizler", + "hideServerAddressDescription": "Ana ekranda sunucu adresini gizler.", "topItemsOrder": "Öne çıkan öğeler sıralaması", "topItemsOrderDescription": "Ana ekrandaki öne çıkan öğe listelerini sırala", "topItemsReorderInfo": "Yeniden sıralamak için bir öğeyi basılı tutun ve kaydırın.", @@ -682,9 +682,11 @@ "processingLists": "Listeler işleniyor...", "enableDisableResult": "Sonucu etkinleştir veya devre dışı bırak", "selectedListsEnabledDisabledSuccessfully": "Seçilen tüm listeler başarıyla etkinleştirildi veya devre dışı bırakıldı", - "sslWarning": "Kendinden imzalı bir sertifika ile HTTPS bağlantısı kullanıyorsanız, Ayarlar > Gelişmiş ayarlar bölümünde \"SSL sertifikasını kontrol etme\" seçeneğini etkinleştirdiğinizden emin olun.", + "sslWarning": "Kendinden imzalı bir sertifika ile HTTPS bağlantısı kullanıyorsanız, Ayarlar > Gelişmiş ayarlar bölümünde \"SSL sertifikasını asla kontrol etme\" seçeneğini etkinleştirdiğinizden emin olun.", "unsupportedServerVersion": "Desteklenmeyen sunucu sürümü", "unsupportedServerVersionMessage": "AdGuard Home sunucu sürümünüz çok eski ve AdGuard Home Manager tarafından desteklenmiyor. Bu uygulamayı kullanmak için AdGuard Home sunucunuzu daha yeni bir sürüme yükseltmeniz gerekecektir.", "yourVersion": "Yüklü sürüm: {version}", - "minimumRequiredVersion": "Gerekli minimum sürüm: {version}" + "minimumRequiredVersion": "Gerekli minimum sürüm: {version}", + "topUpstreams": "Öne çıkan üst kaynaklar", + "averageUpstreamResponseTime": "Üst kaynak ortalama yanıt süresi" } From f53a498c03a5b8e774f653eb88b6f17c903ec7f9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 26 Nov 2023 22:42:05 +0100 Subject: [PATCH 430/676] Changed options menus --- lib/screens/clients/added_list.dart | 12 -- .../clients/client/added_client_tile.dart | 2 - lib/screens/clients/clients_list.dart | 4 +- lib/screens/clients/options_modal.dart | 72 ------- lib/screens/clients/search_clients.dart | 183 ++++++++++-------- .../filters/filters_triple_column.dart | 45 ++--- lib/screens/filters/list_options_menu.dart | 72 +++---- lib/widgets/custom_list_tile_dialog.dart | 4 +- lib/widgets/options_menu.dart | 67 ++++++- lib/widgets/options_modal.dart | 67 ------- 10 files changed, 225 insertions(+), 303 deletions(-) delete mode 100644 lib/screens/clients/options_modal.dart delete mode 100644 lib/widgets/options_modal.dart diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 124f32c..a272940 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -11,7 +11,6 @@ import 'package:adguard_home_manager/screens/clients/client/client_screen_functi import 'package:adguard_home_manager/screens/clients/client/added_client_tile.dart'; import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/fab.dart'; -import 'package:adguard_home_manager/screens/clients/options_modal.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -144,16 +143,6 @@ class _AddedListState extends State { ); } - void openOptionsModal(Client client) { - showModal( - context: context, - builder: (ctx) => OptionsModal( - onDelete: () => openDeleteModal(client), - onEdit: () => openClientModal(client), - ) - ); - } - return CustomTabContentList( listPadding: widget.splitView == true ? const EdgeInsets.only(top: 8) @@ -182,7 +171,6 @@ class _AddedListState extends State { selectedClient: widget.selectedClient, client: widget.data[index], onTap: widget.onClientSelected, - onLongPress: openOptionsModal, onEdit: statusProvider.serverStatus != null ? (c) => openClientModal(c) : null, diff --git a/lib/screens/clients/client/added_client_tile.dart b/lib/screens/clients/client/added_client_tile.dart index a33578f..4f4037e 100644 --- a/lib/screens/clients/client/added_client_tile.dart +++ b/lib/screens/clients/client/added_client_tile.dart @@ -13,7 +13,6 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; class AddedClientTile extends StatefulWidget { final Client client; final void Function(Client) onTap; - final void Function(Client) onLongPress; final void Function(Client)? onEdit; final void Function(Client) onDelete; final Client? selectedClient; @@ -23,7 +22,6 @@ class AddedClientTile extends StatefulWidget { super.key, required this.client, required this.onTap, - required this.onLongPress, this.onEdit, required this.onDelete, this.selectedClient, diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index 2e52738..bdff4ee 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -16,12 +16,12 @@ class ClientsList extends StatelessWidget { final bool splitView; const ClientsList({ - Key? key, + super.key, required this.data, required this.onClientSelected, this.selectedClient, required this.splitView, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/clients/options_modal.dart b/lib/screens/clients/options_modal.dart deleted file mode 100644 index d779aae..0000000 --- a/lib/screens/clients/options_modal.dart +++ /dev/null @@ -1,72 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/widgets/custom_list_tile_dialog.dart'; - -class OptionsModal extends StatelessWidget { - final void Function() onEdit; - final void Function() onDelete; - - const OptionsModal({ - Key? key, - required this.onDelete, - required this.onEdit, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - - return AlertDialog( - contentPadding: const EdgeInsets.symmetric( - horizontal: 0, - vertical: 16 - ), - title: Column( - children: [ - Icon( - Icons.more_horiz, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.options, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const SizedBox(height: 24), - if (statusProvider.serverStatus != null) CustomListTileDialog( - onTap: () { - Navigator.pop(context); - onEdit(); - }, - title: AppLocalizations.of(context)!.edit, - icon: Icons.edit, - ), - CustomListTileDialog( - onTap: () { - Navigator.pop(context); - onDelete(); - }, - title: AppLocalizations.of(context)!.delete, - icon: Icons.delete, - ), - ], - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close) - ) - ], - ); - } -} \ No newline at end of file diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index 895f458..d8e1104 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -7,11 +7,12 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/client/client_screen_functions.dart'; -import 'package:adguard_home_manager/screens/clients/options_modal.dart'; +import 'package:adguard_home_manager/widgets/options_menu.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/models/menu_option.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -151,15 +152,15 @@ class _SearchClientsState extends State { ); } - void openOptionsModal(Client client) { - showModal( - context: context, - builder: (ctx) => OptionsModal( - onDelete: () => openDeleteModal(client), - onEdit: () => openClientModal(client), - ) - ); - } + // void openOptionsModal(Client client) { + // showModal( + // context: context, + // builder: (ctx) => OptionsModal( + // onDelete: () => openDeleteModal(client), + // onEdit: () => openClientModal(client), + // ) + // ); + // } return Scaffold( appBar: AppBar( @@ -224,82 +225,96 @@ class _SearchClientsState extends State { primary: false, itemCount: clientsScreen.length, padding: const EdgeInsets.only(bottom: 0), - itemBuilder: (context, index) => ListTile( - contentPadding: index == 0 - ? const EdgeInsets.only(left: 20, right: 20, bottom: 15) - : const EdgeInsets.symmetric(horizontal: 20, vertical: 15), - isThreeLine: true, - onLongPress: () => openOptionsModal(clientsScreen[index]), - onTap: statusProvider.serverStatus != null - ? () => openClientModal(clientsScreen[index]) - : null, - title: Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Text( - clientsScreen[index].name, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.normal + itemBuilder: (context, index) => OptionsMenu( + options: [ + MenuOption( + icon: Icons.edit_rounded, + title: AppLocalizations.of(context)!.edit, + action: (v) => openClientModal(v) + ), + MenuOption( + icon: Icons.delete_rounded, + title: AppLocalizations.of(context)!.delete, + action: (v) => openDeleteModal(v) + ), + ], + value: clientsScreen[index], + child: ListTile( + contentPadding: index == 0 + ? const EdgeInsets.only(left: 20, right: 20, bottom: 15) + : const EdgeInsets.symmetric(horizontal: 20, vertical: 15), + isThreeLine: true, + onTap: statusProvider.serverStatus != null + ? () => openClientModal(clientsScreen[index]) + : null, + title: Padding( + padding: const EdgeInsets.only(bottom: 5), + child: Text( + clientsScreen[index].name, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.normal + ), ), ), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(clientsScreen[index].ids.toString().replaceAll(RegExp(r'^\[|\]$'), '')), - const SizedBox(height: 7), - Row( - children: [ - Icon( - Icons.filter_list_rounded, - size: 19, - color: clientsScreen[index].filteringEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.vpn_lock_rounded, - size: 18, - color: clientsScreen[index].safebrowsingEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.block, - size: 18, - color: clientsScreen[index].parentalEnabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - ), - const SizedBox(width: 10), - Icon( - Icons.search_rounded, - size: 19, - color: clientsScreen[index].safeSearch != null && clientsScreen[index].safeSearch!.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - ) - ], - ) - ], + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(clientsScreen[index].ids.toString().replaceAll(RegExp(r'^\[|\]$'), '')), + const SizedBox(height: 7), + Row( + children: [ + Icon( + Icons.filter_list_rounded, + size: 19, + color: clientsScreen[index].filteringEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.vpn_lock_rounded, + size: 18, + color: clientsScreen[index].safebrowsingEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.block, + size: 18, + color: clientsScreen[index].parentalEnabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + ), + const SizedBox(width: 10), + Icon( + Icons.search_rounded, + size: 19, + color: clientsScreen[index].safeSearch != null && clientsScreen[index].safeSearch!.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + ) + ], + ) + ], + ), ), ) ) diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 2042068..3401bac 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -7,10 +7,10 @@ import 'package:contextmenu/contextmenu.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/options_menu.dart'; import 'package:adguard_home_manager/screens/filters/add_button.dart'; import 'package:adguard_home_manager/screens/filters/list_options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; @@ -28,11 +28,11 @@ class FiltersTripleColumn extends StatelessWidget { final List actions; const FiltersTripleColumn({ - Key? key, + super.key, required this.onRemoveCustomRule, required this.onOpenDetailsModal, required this.actions, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -282,28 +282,25 @@ class FiltersTripleColumn extends StatelessWidget { } ), ], - child: CustomListTile( - onLongPress: () => showDialog( - context: context, - builder: (context) => OptionsModal( - options: [ - MenuOption( - title: AppLocalizations.of(context)!.copyClipboard, - icon: Icons.copy_rounded, - action: (_) => copyToClipboard( - value: filteringProvider.filtering!.userRules[index], - successMessage: AppLocalizations.of(context)!.copiedClipboard, - ) - ) - ] + child: OptionsMenu( + options: [ + MenuOption( + title: AppLocalizations.of(context)!.copyClipboard, + icon: Icons.copy_rounded, + action: (_) => copyToClipboard( + value: filteringProvider.filtering!.userRules[index], + successMessage: AppLocalizations.of(context)!.copiedClipboard, + ) ) - ), - title: filteringProvider.filtering!.userRules[index], - subtitleWidget: generateSubtitle(filteringProvider.filtering!.userRules[index]), - trailing: IconButton( - onPressed: () => onRemoveCustomRule(filteringProvider.filtering!.userRules[index]), - icon: const Icon(Icons.delete), - tooltip: AppLocalizations.of(context)!.delete, + ], + child: CustomListTile( + title: filteringProvider.filtering!.userRules[index], + subtitleWidget: generateSubtitle(filteringProvider.filtering!.userRules[index]), + trailing: IconButton( + onPressed: () => onRemoveCustomRule(filteringProvider.filtering!.userRules[index]), + icon: const Icon(Icons.delete), + tooltip: AppLocalizations.of(context)!.delete, + ), ), ), ), diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index f4337a1..4cb6865 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -8,7 +8,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/widgets/options_modal.dart'; +import 'package:adguard_home_manager/widgets/options_menu.dart'; import 'package:adguard_home_manager/screens/filters/selection/selection_screen.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; @@ -144,41 +144,41 @@ class ListOptionsMenu extends StatelessWidget { child: Material( color: Colors.transparent, child: InkWell( - onLongPress: Platform.isAndroid || Platform.isIOS ? () => showDialog( - context: context, - builder: (context) => OptionsModal( - options: [ - MenuOption( - title: list.enabled == true - ? AppLocalizations.of(context)!.disable - : AppLocalizations.of(context)!.enable, - icon: list.enabled == true - ? Icons.gpp_bad_rounded - : Icons.verified_user_rounded, - action: (_) => enableDisable() - ), - MenuOption( - title: AppLocalizations.of(context)!.copyListUrl, - icon: Icons.copy_rounded, - action: (_) => copyToClipboard( - value: list.url, - successMessage: AppLocalizations.of(context)!.listUrlCopied - ) - ), - MenuOption( - title: AppLocalizations.of(context)!.openListUrl, - icon: Icons.open_in_browser_rounded, - action: (_) => openUrl(list.url) - ), - MenuOption( - title: AppLocalizations.of(context)!.selectionMode, - icon: Icons.check_rounded, - action: (_) => openSelectionMode() - ), - ] - ) - ) : null, - child: child + child: OptionsMenu( + options: [ + MenuOption( + title: list.enabled == true + ? AppLocalizations.of(context)!.disable + : AppLocalizations.of(context)!.enable, + icon: list.enabled == true + ? Icons.gpp_bad_rounded + : Icons.verified_user_rounded, + action: (_) => enableDisable() + ), + MenuOption( + title: AppLocalizations.of(context)!.copyListUrl, + icon: Icons.copy_rounded, + action: (_) => copyToClipboard( + value: list.url, + successMessage: AppLocalizations.of(context)!.listUrlCopied + ) + ), + MenuOption( + title: AppLocalizations.of(context)!.openListUrl, + icon: Icons.open_in_browser_rounded, + action: (_) => openUrl(list.url) + ), + MenuOption( + title: AppLocalizations.of(context)!.selectionMode, + icon: Icons.check_rounded, + action: (_) => Future.delayed( + const Duration(milliseconds: 0), + () => openSelectionMode() + ) + ), + ], + child: child + ) ), ), ); diff --git a/lib/widgets/custom_list_tile_dialog.dart b/lib/widgets/custom_list_tile_dialog.dart index 1d09760..2e3cff4 100644 --- a/lib/widgets/custom_list_tile_dialog.dart +++ b/lib/widgets/custom_list_tile_dialog.dart @@ -6,11 +6,11 @@ class CustomListTileDialog extends StatelessWidget { final void Function()? onTap; const CustomListTileDialog({ - Key? key, + super.key, required this.title, this.icon, this.onTap - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/options_menu.dart b/lib/widgets/options_menu.dart index 34b755b..b6f6ec7 100644 --- a/lib/widgets/options_menu.dart +++ b/lib/widgets/options_menu.dart @@ -2,8 +2,9 @@ import 'dart:io'; import 'package:contextmenu/contextmenu.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/options_modal.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile_dialog.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; @@ -29,7 +30,7 @@ class OptionsMenu extends StatelessWidget { void openOptionsModal() { showDialog( context: context, - builder: (context) => OptionsModal( + builder: (context) => _OptionsModal( options: options, value: value ) @@ -60,4 +61,66 @@ class OptionsMenu extends StatelessWidget { ), ); } +} + +class _OptionsModal extends StatelessWidget { + final List options; + final dynamic value; + + const _OptionsModal({ + super.key, + required this.options, + this.value, + }); + + @override + Widget build(BuildContext context) { + return AlertDialog( + contentPadding: const EdgeInsets.symmetric(vertical: 16), + title: Column( + children: [ + Icon( + Icons.more_horiz, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.options, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: SingleChildScrollView( + child: Wrap( + children: options.map((opt) => CustomListTileDialog( + title: opt.title, + icon: opt.icon, + onTap: () { + Navigator.pop(context); + opt.action(value); + }, + )).toList() + ), + ), + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ) + ], + ) + ], + ); + } } \ No newline at end of file diff --git a/lib/widgets/options_modal.dart b/lib/widgets/options_modal.dart deleted file mode 100644 index 102f7ca..0000000 --- a/lib/widgets/options_modal.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:adguard_home_manager/models/menu_option.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/widgets/custom_list_tile_dialog.dart'; - -class OptionsModal extends StatelessWidget { - final List options; - final dynamic value; - - const OptionsModal({ - super.key, - required this.options, - this.value, - }); - - @override - Widget build(BuildContext context) { - return AlertDialog( - contentPadding: const EdgeInsets.symmetric(vertical: 16), - title: Column( - children: [ - Icon( - Icons.more_horiz, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.options, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - content: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 400 - ), - child: SingleChildScrollView( - child: Wrap( - children: options.map((opt) => CustomListTileDialog( - title: opt.title, - icon: opt.icon, - onTap: () { - Navigator.pop(context); - opt.action(value); - }, - )).toList() - ), - ), - ), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ) - ], - ) - ], - ); - } -} \ No newline at end of file From 69ee579139c4603cc5e820bebf32bc98f4f97dec Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 26 Nov 2023 22:51:51 +0100 Subject: [PATCH 431/676] Fixed clients search --- lib/screens/clients/added_list.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index a272940..0a0bc08 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -142,6 +142,11 @@ class _AddedListState extends State { ) ); } + final clientsDisplay = clientsProvider.searchTermClients != null && clientsProvider.searchTermClients != "" + ? widget.data.where( + (c) => c.name.toLowerCase().contains(clientsProvider.searchTermClients.toString()) || c.ids.where((id) => id.contains(clientsProvider.searchTermClients.toString())).isNotEmpty + ).toList() + : widget.data; return CustomTabContentList( listPadding: widget.splitView == true @@ -166,10 +171,10 @@ class _AddedListState extends State { ], ), ), - itemsCount: widget.data.length, + itemsCount: clientsDisplay.length, contentWidget: (index) => AddedClientTile( selectedClient: widget.selectedClient, - client: widget.data[index], + client: clientsDisplay[index], onTap: widget.onClientSelected, onEdit: statusProvider.serverStatus != null ? (c) => openClientModal(c) From 991a73c47a4188629778d6562ea8fbd72db90dbd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 26 Nov 2023 22:53:08 +0100 Subject: [PATCH 432/676] Improvement --- lib/widgets/options_menu.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/widgets/options_menu.dart b/lib/widgets/options_menu.dart index b6f6ec7..861edab 100644 --- a/lib/widgets/options_menu.dart +++ b/lib/widgets/options_menu.dart @@ -68,7 +68,6 @@ class _OptionsModal extends StatelessWidget { final dynamic value; const _OptionsModal({ - super.key, required this.options, this.value, }); From 1c009df41f2667306d8489673b7e5854ac63d61d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 26 Nov 2023 22:54:29 +0100 Subject: [PATCH 433/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 8770025..0043bc7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.12.0-beta.2+110 +version: 2.12.0+111 environment: sdk: '>=2.18.1 <3.0.0' From 48794b26a81c02f9fa734742d82cabf17dfbb633 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 27 Nov 2023 01:04:23 +0100 Subject: [PATCH 434/676] Fixed copy log domain clipboard --- lib/screens/logs/log_tile.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 95981e8..af130e2 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -319,10 +319,13 @@ class LogTile extends StatelessWidget { newStatus: domainBlocked == true ? 'unblock' : 'block' ) ), - MenuOption( + if (log.question.name != null) MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: (v) => copyToClipboard(value: v, successMessage: AppLocalizations.of(context)!.copiedClipboard) + action: (_) => copyToClipboard( + value: log.question.name!, + successMessage: AppLocalizations.of(context)!.copiedClipboard + ) ) ], child: Container( From ffe30150a31a43d61e3f7ac16b6559e3cfc92796 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 27 Nov 2023 14:45:22 +0100 Subject: [PATCH 435/676] Add status code sentry --- lib/services/api_client.dart | 78 ++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 13 deletions(-) diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index 66ac615..25b6fa3 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -166,7 +166,11 @@ class ApiClientV2 { content: clients ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) }) + ); return const ApiResponse(successful: false); } } @@ -210,7 +214,11 @@ class ApiClientV2 { content: LogsData.fromJson(jsonDecode(result.body!)) ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); return const ApiResponse(successful: false); } } @@ -228,7 +236,11 @@ class ApiClientV2 { content: FilteringStatus.fromJson(jsonDecode(result.body!)) ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); return const ApiResponse(successful: false); } } @@ -298,7 +310,11 @@ class ApiClientV2 { }) ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) }) + ); return const ApiResponse(successful: false); } } @@ -364,7 +380,11 @@ class ApiClientV2 { content: ServerInfoData.fromJson(jsonDecode(result.body!)) ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); return const ApiResponse(successful: false); } } @@ -398,7 +418,11 @@ class ApiClientV2 { content: {'updated': jsonDecode(results[0].body!)['updated']+jsonDecode(results[1].body!)['updated']} ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) }) + ); return const ApiResponse(successful: false); } } @@ -463,7 +487,11 @@ class ApiClientV2 { ) ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) }) + ); return const ApiResponse(successful: false); } } @@ -549,7 +577,11 @@ class ApiClientV2 { content: data ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); return const ApiResponse(successful: false); } } @@ -622,7 +654,11 @@ class ApiClientV2 { content: DnsInfo.fromJson(jsonDecode(result.body!)) ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); return const ApiResponse(successful: false); } } @@ -658,7 +694,11 @@ class ApiClientV2 { content: EncryptionData.fromJson(jsonDecode(result.body!)) ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); return const ApiResponse(successful: false); } } @@ -678,7 +718,11 @@ class ApiClientV2 { ) ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); return const ApiResponse(successful: false); } } @@ -712,7 +756,11 @@ class ApiClientV2 { ) : null ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); return const ApiResponse(successful: false); } } @@ -758,7 +806,11 @@ class ApiClientV2 { content: obj ); } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": results.map((e) => e.statusCode.toString()) }) + ); return const ApiResponse(successful: false); } } From 06d543553f880adcf13bb85fab65ee8689431331 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 27 Nov 2023 14:45:54 +0100 Subject: [PATCH 436/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 0043bc7..bfddb2f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.12.0+111 +version: 2.12.1+112 environment: sdk: '>=2.18.1 <3.0.0' From 946f779567ef57f4b70f8d3504a01758b7d1f4c5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 27 Nov 2023 15:05:26 +0100 Subject: [PATCH 437/676] Fixed encryption error message --- lib/services/api_client.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index 25b6fa3..636cc34 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -743,7 +743,7 @@ class ApiClientV2 { return ApiResponse( successful: result.successful, content: result.body != null ? EncryptionValidationResult( - isObject: false, + isObject: true, encryptionValidation: EncryptionValidation.fromJson(jsonDecode(result.body!)) ) : null ); From bddfac7e721b13f701943fc241a28b7b82a164a9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 29 Nov 2023 10:32:12 +0100 Subject: [PATCH 438/676] Removed fixed text size --- lib/main.dart | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 5b38138..9734263 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -236,20 +236,9 @@ class _MainState extends State
{ ], scaffoldMessengerKey: scaffoldMessengerKey, navigatorKey: globalNavigatorKey, - builder: (context, child) { - return CustomMenuBar( - child: MediaQuery( - data: MediaQuery.of(context).copyWith( - textScaler: TextScaler.linear( - !(Platform.isAndroid || Platform.isIOS) - ? 0.9 - : 1.0 - ) - ), - child: child!, - ), - ); - }, + builder: (context, child) => CustomMenuBar( + child: child!, + ), home: const Layout(), ), ); From c9c960d1ee38f52667aa533ade8d76cbc7e6e106 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 29 Nov 2023 11:56:28 +0100 Subject: [PATCH 439/676] Adapt ui to support text scale --- .../client/blocked_services_section.dart | 60 +-- lib/screens/clients/client/client_form.dart | 16 +- lib/screens/clients/client/client_screen.dart | 4 +- lib/screens/clients/client/tags_modal.dart | 18 +- .../modals/update_interval_lists_modal.dart | 340 +++++++++-------- .../filters/selection/selection_screen.dart | 11 +- lib/screens/home/chart.dart | 4 +- .../home/management_modal/main_switch.dart | 64 ++-- .../management_modal/management_modal.dart | 3 +- lib/screens/home/server_status.dart | 99 +++-- lib/screens/home/status_box.dart | 4 +- .../logs/configuration/config_widgets.dart | 34 +- .../logs/configuration/logs_config_modal.dart | 1 - lib/screens/logs/filters/clients_modal.dart | 10 +- .../logs/filters/filter_status_modal.dart | 354 ++++++++++-------- .../settings/dhcp/add_static_lease_modal.dart | 42 ++- lib/screens/settings/dhcp/dhcp.dart | 1 + .../settings/dhcp/dhcp_interface_item.dart | 17 +- .../settings/dhcp/select_interface_modal.dart | 4 +- .../settings/dns/clear_dns_cache_dialog.dart | 5 +- .../settings/dns_rewrites/dns_rewrites.dart | 4 +- .../settings/safe_search_settings.dart | 10 +- lib/widgets/custom_list_tile_dialog.dart | 14 +- 23 files changed, 624 insertions(+), 495 deletions(-) diff --git a/lib/screens/clients/client/blocked_services_section.dart b/lib/screens/clients/client/blocked_services_section.dart index 37c01d3..f6effd4 100644 --- a/lib/screens/clients/client/blocked_services_section.dart +++ b/lib/screens/clients/client/blocked_services_section.dart @@ -10,12 +10,12 @@ class BlockedServicesSection extends StatelessWidget { final void Function(bool) onUpdateServicesGlobalSettings; const BlockedServicesSection({ - Key? key, + super.key, required this.useGlobalSettingsServices, required this.blockedServices, required this.onUpdatedBlockedServices, required this.onUpdateServicesGlobalSettings - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -37,11 +37,13 @@ class BlockedServicesSection extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - AppLocalizations.of(context)!.useGlobalSettings, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface + Flexible( + child: Text( + AppLocalizations.of(context)!.useGlobalSettings, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), ), ), Switch( @@ -78,30 +80,32 @@ class BlockedServicesSection extends StatelessWidget { : Theme.of(context).colorScheme.onSurface.withOpacity(0.38), ), const SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.selectBlockedServices, - style: TextStyle( - fontSize: 16, - color: useGlobalSettingsServices == false - ? Theme.of(context).colorScheme.onSurface - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38), - ), - ), - if (useGlobalSettingsServices == false) ...[ - const SizedBox(height: 5), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ Text( - blockedServices.isNotEmpty - ? "${blockedServices.length} ${AppLocalizations.of(context)!.servicesBlocked}" - : AppLocalizations.of(context)!.noBlockedServicesSelected, + AppLocalizations.of(context)!.selectBlockedServices, style: TextStyle( - color: Theme.of(context).listTileTheme.iconColor + fontSize: 16, + color: useGlobalSettingsServices == false + ? Theme.of(context).colorScheme.onSurface + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38), ), - ) - ] - ], + ), + if (useGlobalSettingsServices == false) ...[ + const SizedBox(height: 5), + Text( + blockedServices.isNotEmpty + ? "${blockedServices.length} ${AppLocalizations.of(context)!.servicesBlocked}" + : AppLocalizations.of(context)!.noBlockedServicesSelected, + style: TextStyle( + color: Theme.of(context).listTileTheme.iconColor + ), + ) + ] + ], + ), ) ], ), diff --git a/lib/screens/clients/client/client_form.dart b/lib/screens/clients/client/client_form.dart index 5d54b86..2151288 100644 --- a/lib/screens/clients/client/client_form.dart +++ b/lib/screens/clients/client/client_form.dart @@ -47,7 +47,7 @@ class ClientForm extends StatelessWidget { final void Function(bool) updateUseGlobalSettingsServices; const ClientForm({ - Key? key, + super.key, required this.isFullScreen, required this.client, required this.nameController, @@ -75,7 +75,7 @@ class ClientForm extends StatelessWidget { required this.updateEnableSafeSearch, required this.updateSafeSearch, required this.updateUseGlobalSettingsServices, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -154,11 +154,13 @@ class ClientForm extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - AppLocalizations.of(context)!.useGlobalSettings, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface + Flexible( + child: Text( + AppLocalizations.of(context)!.useGlobalSettings, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), ), ), Switch( diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index 34fb88b..2ab5c75 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -27,12 +27,12 @@ class ClientScreen extends StatefulWidget { final bool fullScreen; const ClientScreen({ - Key? key, + super.key, this.client, required this.onConfirm, this.onDelete, required this.fullScreen - }) : super(key: key); + }); @override State createState() => _ClientScreenState(); diff --git a/lib/screens/clients/client/tags_modal.dart b/lib/screens/clients/client/tags_modal.dart index 42843b1..0756c83 100644 --- a/lib/screens/clients/client/tags_modal.dart +++ b/lib/screens/clients/client/tags_modal.dart @@ -7,11 +7,11 @@ class TagsModal extends StatefulWidget { final void Function(List) onConfirm; const TagsModal({ - Key? key, + super.key, required this.selectedTags, required this.tags, required this.onConfirm, - }) : super(key: key); + }); @override State createState() => _TagsModalState(); @@ -82,12 +82,14 @@ class _TagsModalState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - widget.tags[index], - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface, + Flexible( + child: Text( + widget.tags[index], + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), ), ), Checkbox( diff --git a/lib/screens/filters/modals/update_interval_lists_modal.dart b/lib/screens/filters/modals/update_interval_lists_modal.dart index deb714f..4827082 100644 --- a/lib/screens/filters/modals/update_interval_lists_modal.dart +++ b/lib/screens/filters/modals/update_interval_lists_modal.dart @@ -12,11 +12,11 @@ class UpdateIntervalListsModal extends StatefulWidget { final bool dialog; const UpdateIntervalListsModal({ - Key? key, + super.key, required this.interval, required this.onChange, required this.dialog - }) : super(key: key); + }); @override State createState() => _UpdateIntervalListsModalState(); @@ -25,7 +25,7 @@ class UpdateIntervalListsModal extends StatefulWidget { class _UpdateIntervalListsModalState extends State { int? selectedOption; - void _updateRadioValue(value) { + void _updateRadioValue(int value) { setState(() { selectedOption = value; }); @@ -41,18 +41,67 @@ class _UpdateIntervalListsModalState extends State { Widget build(BuildContext context) { final MediaQueryData mediaQueryData = MediaQuery.of(context); - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: _Content( + selectedOption: selectedOption, + onUpdateValue: _updateRadioValue, + onConfirm: () => widget.onChange(selectedOption!), + ) + ), + ); + } + else { + return Padding( + padding: mediaQueryData.viewInsets, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).dialogBackgroundColor, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + ), + child: _Content( + selectedOption: selectedOption, + onUpdateValue: _updateRadioValue, + onConfirm: () => widget.onChange(selectedOption!), + ) + ), + ); + } + } +} + +class _Content extends StatelessWidget { + final int? selectedOption; + final void Function(int) onUpdateValue; + final void Function() onConfirm; + + const _Content({ + required this.selectedOption, + required this.onUpdateValue, + required this.onConfirm, + }); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Column( children: [ Padding( padding: const EdgeInsets.only(top: 24), @@ -62,7 +111,7 @@ class _UpdateIntervalListsModalState extends State { color: Theme.of(context).listTileTheme.iconColor ), ), - Container( + Padding( padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 16 @@ -78,157 +127,128 @@ class _UpdateIntervalListsModalState extends State { ), ), ], - ) + ), + ) + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Wrap( + runSpacing: 16, + children: [ + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(right: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 0, + onTap: (v) => onUpdateValue(v as int), + label: AppLocalizations.of(context)!.never, + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(left: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 1, + onTap: (v) => onUpdateValue(v as int), + label: AppLocalizations.of(context)!.hour1, + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(right: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 12, + onTap: (v) => onUpdateValue(v as int), + label: AppLocalizations.of(context)!.hours12, + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(left: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 24, + onTap: (v) => onUpdateValue(v as int), + label: AppLocalizations.of(context)!.hours24, + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(right: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 72, + onTap: (v) => onUpdateValue(v as int), + label: AppLocalizations.of(context)!.days3, + ), + ), + ), + FractionallySizedBox( + widthFactor: 0.5, + child: Padding( + padding: const EdgeInsets.only(left: 6), + child: OptionBox( + optionsValue: selectedOption, + itemValue: 168, + onTap: (v) => onUpdateValue(v as int), + label: AppLocalizations.of(context)!.days7, + ), + ), + ), ], ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Wrap( - runSpacing: 16, - children: [ - FractionallySizedBox( - widthFactor: 0.5, - child: Padding( - padding: const EdgeInsets.only(right: 6), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 0, - onTap: _updateRadioValue, - label: AppLocalizations.of(context)!.never, - ), - ), - ), - FractionallySizedBox( - widthFactor: 0.5, - child: Padding( - padding: const EdgeInsets.only(left: 6), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 1, - onTap: _updateRadioValue, - label: AppLocalizations.of(context)!.hour1, - ), - ), - ), - FractionallySizedBox( - widthFactor: 0.5, - child: Padding( - padding: const EdgeInsets.only(right: 6), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 12, - onTap: _updateRadioValue, - label: AppLocalizations.of(context)!.hours12, - ), - ), - ), - FractionallySizedBox( - widthFactor: 0.5, - child: Padding( - padding: const EdgeInsets.only(left: 6), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 24, - onTap: _updateRadioValue, - label: AppLocalizations.of(context)!.hours24, - - ), - ), - ), - FractionallySizedBox( - widthFactor: 0.5, - child: Padding( - padding: const EdgeInsets.only(right: 6), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 72, - onTap: _updateRadioValue, - label: AppLocalizations.of(context)!.days3, - - ), - ), - ), - FractionallySizedBox( - widthFactor: 0.5, - child: Padding( - padding: const EdgeInsets.only(left: 6), - child: OptionBox( - optionsValue: selectedOption, - itemValue: 168, - onTap: _updateRadioValue, - label: AppLocalizations.of(context)!.days7, - ), - ), - ), - ], - ), - ) - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel), - ), - const SizedBox(width: 20), - TextButton( - onPressed: selectedOption != null - ? () { - Navigator.pop(context); - widget.onChange(selectedOption!); - } - : null, - style: ButtonStyle( - overlayColor: MaterialStateProperty.all( - Theme.of(context).colorScheme.primary.withOpacity(0.1) - ), - foregroundColor: MaterialStateProperty.all( - selectedOption != null - ? Theme.of(context).colorScheme.primary - : Colors.grey, - ), - ), - child: Text(AppLocalizations.of(context)!.confirm), - ), + ) ], ), ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ); - } - - if (widget.dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: content() ), - ); - } - else { - return Padding( - padding: mediaQueryData.viewInsets, - child: Container( - height: Platform.isIOS ? 406 : 390, - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel), + ), + const SizedBox(width: 20), + TextButton( + onPressed: selectedOption != null + ? () { + Navigator.pop(context); + onConfirm(); + } + : null, + style: ButtonStyle( + overlayColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.primary.withOpacity(0.1) + ), + foregroundColor: MaterialStateProperty.all( + selectedOption != null + ? Theme.of(context).colorScheme.primary + : Colors.grey, + ), + ), + child: Text(AppLocalizations.of(context)!.confirm), + ), + ], ), - child: content() ), - ); - } + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); } } \ No newline at end of file diff --git a/lib/screens/filters/selection/selection_screen.dart b/lib/screens/filters/selection/selection_screen.dart index 11539b2..1475454 100644 --- a/lib/screens/filters/selection/selection_screen.dart +++ b/lib/screens/filters/selection/selection_screen.dart @@ -197,7 +197,7 @@ class _SelectionScreenState extends State with TickerProviderSt ), _Tab( icon: Icons.gpp_bad_rounded, - text: AppLocalizations.of(context)!.blacklist, + text: AppLocalizations.of(context)!.blacklists, quantity: _selectedBlacklists.length ), ] @@ -263,7 +263,7 @@ class _SelectionScreenState extends State with TickerProviderSt ), _Tab( icon: Icons.gpp_bad_rounded, - text: AppLocalizations.of(context)!.blacklist, + text: AppLocalizations.of(context)!.blacklists, quantity: _selectedBlacklists.length ), ] @@ -336,7 +336,12 @@ class _Tab extends StatelessWidget { children: [ Icon(icon), const SizedBox(width: 8), - Text(text), + Flexible( + child: Text( + text, + overflow: TextOverflow.ellipsis, + ) + ), const SizedBox(width: 8), Container( height: 22, diff --git a/lib/screens/home/chart.dart b/lib/screens/home/chart.dart index 682d5b9..ba97f79 100644 --- a/lib/screens/home/chart.dart +++ b/lib/screens/home/chart.dart @@ -14,14 +14,14 @@ class HomeChart extends StatelessWidget { final int hoursInterval; const HomeChart({ - Key? key, + super.key, required this.data, required this.label, required this.primaryValue, required this.secondaryValue, required this.color, required this.hoursInterval - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/home/management_modal/main_switch.dart b/lib/screens/home/management_modal/main_switch.dart index d4ce5ed..3dbe0ec 100644 --- a/lib/screens/home/management_modal/main_switch.dart +++ b/lib/screens/home/management_modal/main_switch.dart @@ -15,12 +15,12 @@ class MainSwitch extends StatelessWidget { final Animation animation; const MainSwitch({ - Key? key, + super.key, required this.expandableController, required this.updateBlocking, required this.disableWithCountdown, required this.animation, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -88,12 +88,11 @@ class _TopRow extends StatelessWidget { final Animation animation; const _TopRow({ - Key? key, required this.legacyMode, required this.expandableController, required this.updateBlocking, required this.animation, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -102,9 +101,9 @@ class _TopRow extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( - children: [ - if (legacyMode == false) ...[ + Expanded( + child: Row( + children: [ RotationTransition( turns: animation, child: Icon( @@ -116,26 +115,30 @@ class _TopRow extends StatelessWidget { ), ), const SizedBox(width: 8), - ], - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.allProtections, - style: const TextStyle( - fontSize: 18, - ), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.allProtections, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 18, + ), + ), + if (statusProvider.serverStatus!.timeGeneralDisabled > 0) ...[ + const SizedBox(height: 2), + if (statusProvider.currentDeadline != null) Text( + "${AppLocalizations.of(context)!.remainingTime}: ${formatRemainingSeconds(statusProvider.remainingTime)}" + ) + ] + ], ), - if (statusProvider.serverStatus!.timeGeneralDisabled > 0) ...[ - const SizedBox(height: 2), - if (statusProvider.currentDeadline != null) Text( - "${AppLocalizations.of(context)!.remainingTime}: ${formatRemainingSeconds(statusProvider.remainingTime)}" - ) - ] - ], - ), - ], + ), + ], + ), ), + const SizedBox(width: 8), Switch( value: statusProvider.serverStatus!.generalEnabled, onChanged: statusProvider.protectionsManagementProcess.contains('general') == false @@ -145,7 +148,7 @@ class _TopRow extends StatelessWidget { } updateBlocking( value: value, - filter: legacyMode == true ? 'general_legacy' : 'general' + filter: 'general' ); } : null, ) @@ -158,9 +161,8 @@ class _BottomRow extends StatefulWidget { final void Function(int) disableWithCountdown; const _BottomRow({ - Key? key, required this.disableWithCountdown, - }) : super(key: key); + }); @override State<_BottomRow> createState() => _BottomRowState(); @@ -173,8 +175,12 @@ class _BottomRowState extends State<_BottomRow> { Widget build(BuildContext context) { final statusProvider = Provider.of(context); + final textScale = MediaQuery.of(context).textScaleFactor; + return Container( - height: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 50 : 40, + height: Platform.isMacOS || Platform.isLinux || Platform.isWindows + ? 50 * textScale + : 40 * textScale, margin: const EdgeInsets.only(top: 8), child: Scrollbar( controller: _chipsScrollController, diff --git a/lib/screens/home/management_modal/management_modal.dart b/lib/screens/home/management_modal/management_modal.dart index 5096a9d..79fe043 100644 --- a/lib/screens/home/management_modal/management_modal.dart +++ b/lib/screens/home/management_modal/management_modal.dart @@ -181,12 +181,11 @@ class _Modal extends StatelessWidget { final Animation animation; const _Modal({ - Key? key, required this.expandableController, required this.updateBlocking, required this.disableWithCountdown, required this.animation, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/home/server_status.dart b/lib/screens/home/server_status.dart index c130564..a0e1715 100644 --- a/lib/screens/home/server_status.dart +++ b/lib/screens/home/server_status.dart @@ -9,17 +9,43 @@ class ServerStatusWidget extends StatelessWidget { final ServerStatus serverStatus; const ServerStatusWidget({ - Key? key, + super.key, required this.serverStatus, - }) : super(key: key); + }); @override Widget build(BuildContext context) { final width = MediaQuery.of(context).size.width; - - return Container( + final textScaleFactor = MediaQuery.of(context).textScaleFactor; + + double boxSize() { + if (textScaleFactor < 1 || (textScaleFactor >= 1 && textScaleFactor < 1.15)) { + return 65; + } + else if (textScaleFactor >= 1.15 && textScaleFactor < 1.3) { + return 75; + } + else if (textScaleFactor >= 1.3 && textScaleFactor < 1.45) { + return 80; + } + else if (textScaleFactor >= 1.45 && textScaleFactor < 1.6) { + return 85; + } + else if (textScaleFactor >= 1.6 && textScaleFactor < 1.85) { + return 100; + } + else if (textScaleFactor >= 1.85) { + return 110; + } + else { + return 65; + } + } + + return Padding( padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16), child: Column( + mainAxisSize: MainAxisSize.min, children: [ Text( AppLocalizations.of(context)!.serverStatus, @@ -30,40 +56,39 @@ class ServerStatusWidget extends StatelessWidget { ), ), const SizedBox(height: 16), - SizedBox( - height: width > 700 ? 66 : 146, - child: GridView( - padding: const EdgeInsets.all(0), - physics: const NeverScrollableScrollPhysics(), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: width > 700 ? 4 : 2, - crossAxisSpacing: 10, - mainAxisSpacing: 10, - mainAxisExtent: 65 - ), - children: [ - StatusBox( - icon: Icons.filter_list_rounded, - label: AppLocalizations.of(context)!.ruleFilteringWidget, - isEnabled: serverStatus.filteringEnabled - ), - StatusBox( - icon: Icons.vpn_lock_rounded, - label: AppLocalizations.of(context)!.safeBrowsingWidget, - isEnabled: serverStatus.safeBrowsingEnabled - ), - StatusBox( - icon: Icons.block, - label: AppLocalizations.of(context)!.parentalFilteringWidget, - isEnabled: serverStatus.parentalControlEnabled - ), - StatusBox( - icon: Icons.search_rounded, - label: AppLocalizations.of(context)!.safeSearchWidget, - isEnabled: serverStatus.safeSearchEnabled - ), - ], + GridView( + primary: false, + shrinkWrap: true, + padding: const EdgeInsets.all(0), + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: width > 700 ? 4 : 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + mainAxisExtent: boxSize() ), + children: [ + StatusBox( + icon: Icons.filter_list_rounded, + label: AppLocalizations.of(context)!.ruleFilteringWidget, + isEnabled: serverStatus.filteringEnabled + ), + StatusBox( + icon: Icons.vpn_lock_rounded, + label: AppLocalizations.of(context)!.safeBrowsingWidget, + isEnabled: serverStatus.safeBrowsingEnabled + ), + StatusBox( + icon: Icons.block, + label: AppLocalizations.of(context)!.parentalFilteringWidget, + isEnabled: serverStatus.parentalControlEnabled + ), + StatusBox( + icon: Icons.search_rounded, + label: AppLocalizations.of(context)!.safeSearchWidget, + isEnabled: serverStatus.safeSearchEnabled + ), + ], ) ], ), diff --git a/lib/screens/home/status_box.dart b/lib/screens/home/status_box.dart index 2f57106..38f6c95 100644 --- a/lib/screens/home/status_box.dart +++ b/lib/screens/home/status_box.dart @@ -9,11 +9,11 @@ class StatusBox extends StatelessWidget { final bool isEnabled; const StatusBox({ - Key? key, + super.key, required this.icon, required this.label, required this.isEnabled - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/logs/configuration/config_widgets.dart b/lib/screens/logs/configuration/config_widgets.dart index 2d70285..1fa59f9 100644 --- a/lib/screens/logs/configuration/config_widgets.dart +++ b/lib/screens/logs/configuration/config_widgets.dart @@ -17,7 +17,7 @@ class LogsConfigOptions extends StatelessWidget { final void Function() onConfirm; const LogsConfigOptions({ - Key? key, + super.key, required this.generalSwitch, required this.updateGeneralSwitch, required this.anonymizeClientIp, @@ -27,10 +27,12 @@ class LogsConfigOptions extends StatelessWidget { required this.updateRetentionTime, required this.onClear, required this.onConfirm - }) : super(key: key); + }); @override Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -111,10 +113,12 @@ class LogsConfigOptions extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - AppLocalizations.of(context)!.anonymizeClientIp, - style: const TextStyle( - fontSize: 16 + Flexible( + child: Text( + AppLocalizations.of(context)!.anonymizeClientIp, + style: const TextStyle( + fontSize: 16 + ), ), ), Switch( @@ -159,13 +163,21 @@ class LogsConfigOptions extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TextButton( + if (width > 500) TextButton( onPressed: () { Navigator.pop(context); onClear(); }, child: Text(AppLocalizations.of(context)!.clearLogs) ), + if (width <= 500) IconButton( + onPressed: () { + Navigator.pop(context); + onClear(); + }, + icon: const Icon(Icons.delete_rounded), + tooltip: AppLocalizations.of(context)!.clearLogs, + ), Row( children: [ TextButton( @@ -174,7 +186,7 @@ class LogsConfigOptions extends StatelessWidget { ), const SizedBox(width: 20), TextButton( - onPressed: retentionTime != '' + onPressed: retentionTime != null ? () { Navigator.pop(context); onConfirm(); @@ -183,7 +195,7 @@ class LogsConfigOptions extends StatelessWidget { child: Text( AppLocalizations.of(context)!.confirm, style: TextStyle( - color: retentionTime != '' + color: retentionTime != null ? Theme.of(context).colorScheme.primary : Colors.grey ), @@ -201,7 +213,7 @@ class LogsConfigOptions extends StatelessWidget { } class ConfigLogsLoading extends StatelessWidget { - const ConfigLogsLoading({Key? key}) : super(key: key); + const ConfigLogsLoading({super.key}); @override Widget build(BuildContext context) { @@ -232,7 +244,7 @@ class ConfigLogsLoading extends StatelessWidget { } class ConfigLogsError extends StatelessWidget { - const ConfigLogsError({Key? key}) : super(key: key); + const ConfigLogsError({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/screens/logs/configuration/logs_config_modal.dart b/lib/screens/logs/configuration/logs_config_modal.dart index fb260b9..1b6c641 100644 --- a/lib/screens/logs/configuration/logs_config_modal.dart +++ b/lib/screens/logs/configuration/logs_config_modal.dart @@ -143,7 +143,6 @@ class _LogsConfigModalState extends State { } else { return Container( - height: Platform.isIOS ? 436 : 420, decoration: BoxDecoration( borderRadius: const BorderRadius.only( topLeft: Radius.circular(28), diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index 7bb0574..1730d8e 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -12,10 +12,10 @@ class ClientsModal extends StatefulWidget { final bool dialog; const ClientsModal({ - Key? key, + super.key, required this.value, required this.dialog - }) : super(key: key); + }); @override State createState() => _ClientsModalState(); @@ -75,10 +75,9 @@ class _ModalContent extends StatelessWidget { final void Function(List) onClientsSelected; const _ModalContent({ - Key? key, required this.selectedClients, required this.onClientsSelected, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -188,11 +187,10 @@ class _ListItem extends StatelessWidget { final void Function(bool) onChanged; const _ListItem({ - Key? key, required this.label, required this.checkboxActive, required this.onChanged, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/logs/filters/filter_status_modal.dart b/lib/screens/logs/filters/filter_status_modal.dart index aec5aac..d3c1079 100644 --- a/lib/screens/logs/filters/filter_status_modal.dart +++ b/lib/screens/logs/filters/filter_status_modal.dart @@ -11,10 +11,10 @@ class FilterStatusModal extends StatefulWidget { final bool dialog; const FilterStatusModal({ - Key? key, + super.key, required this.value, required this.dialog - }) : super(key: key); + }); @override State createState() => _FilterStatusModalState(); @@ -39,164 +39,17 @@ class _FilterStatusModalState extends State { Navigator.pop(context); } - Widget filterStatusListItem({ - required String id, - required IconData icon, - required String label, - required void Function(String?) onChanged - }) { - return Material( - color: Colors.transparent, - child: InkWell( - onTap: () => onChanged(id), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Icon( - icon, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(width: 16), - Text( - label, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - Radio( - value: id, - groupValue: selectedResultStatus, - onChanged: onChanged - ) - ], - ), - ), - ), - ); - } - - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 24, - bottom: 16, - ), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Text( - AppLocalizations.of(context)!.responseStatus, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ) - ], - ), - Container(height: 16), - filterStatusListItem( - id: "all", - icon: Icons.shield_rounded, - label: AppLocalizations.of(context)!.all, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "filtered", - icon: Icons.shield_rounded, - label: AppLocalizations.of(context)!.filtered, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "processed", - icon: Icons.verified_user_rounded, - label: AppLocalizations.of(context)!.processedRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "whitelisted", - icon: Icons.verified_user_rounded, - label: AppLocalizations.of(context)!.processedWhitelistRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "blocked", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blocked, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "blocked_safebrowsing", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedSafeBrowsingRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "blocked_parental", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedParentalRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - filterStatusListItem( - id: "safe_search", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedSafeSearchRow, - onChanged: (value) => setState(() => selectedResultStatus = value!) - ), - - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: apply, - child: Text(AppLocalizations.of(context)!.apply) - ) - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ); - } - if (widget.dialog == true) { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( maxWidth: 400 ), - child: content() + child: _Content( + onApply: apply, + updateSelectedResultStatus: (v) => setState(() => selectedResultStatus = v), + selectedResultStatus: selectedResultStatus, + ) ), ); } @@ -209,8 +62,199 @@ class _FilterStatusModalState extends State { ), color: Theme.of(context).dialogBackgroundColor ), - child: content() + child: _Content( + onApply: apply, + updateSelectedResultStatus: (v) => setState(() => selectedResultStatus = v), + selectedResultStatus: selectedResultStatus, + ) ); } } +} + +class _Content extends StatelessWidget { + final String selectedResultStatus; + final void Function(String) updateSelectedResultStatus; + final void Function() onApply; + + const _Content({ + required this.selectedResultStatus, + required this.updateSelectedResultStatus, + required this.onApply, + }); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 24, + bottom: 16, + ), + child: Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + Text( + AppLocalizations.of(context)!.responseStatus, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ) + ], + ), + Container(height: 16), + _Item( + selectedResultStatus: selectedResultStatus, + id: "all", + icon: Icons.shield_rounded, + label: AppLocalizations.of(context)!.all, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "filtered", + icon: Icons.shield_rounded, + label: AppLocalizations.of(context)!.filtered, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "processed", + icon: Icons.verified_user_rounded, + label: AppLocalizations.of(context)!.processedRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "whitelisted", + icon: Icons.verified_user_rounded, + label: AppLocalizations.of(context)!.processedWhitelistRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "blocked", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blocked, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "blocked_safebrowsing", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedSafeBrowsingRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "blocked_parental", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedParentalRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "safe_search", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedSafeSearchRow, + onChanged: updateSelectedResultStatus + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: onApply, + child: Text(AppLocalizations.of(context)!.apply) + ) + ], + ), + ), + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); + } +} + +class _Item extends StatelessWidget { + final String selectedResultStatus; + final String id; + final IconData icon; + final String label; + final void Function(String) onChanged; + + const _Item({ + required this.selectedResultStatus, + required this.id, + required this.icon, + required this.label, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () => onChanged(id), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + children: [ + Icon( + icon, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(width: 16), + Flexible( + child: Text( + label, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ) + ], + ), + ), + Radio( + value: id, + groupValue: selectedResultStatus, + onChanged: (v) => onChanged(v!) + ) + ], + ), + ), + ), + ); + } } \ No newline at end of file diff --git a/lib/screens/settings/dhcp/add_static_lease_modal.dart b/lib/screens/settings/dhcp/add_static_lease_modal.dart index a7f2f5f..fd222d3 100644 --- a/lib/screens/settings/dhcp/add_static_lease_modal.dart +++ b/lib/screens/settings/dhcp/add_static_lease_modal.dart @@ -8,10 +8,10 @@ class AddStaticLeaseModal extends StatefulWidget { final bool dialog; const AddStaticLeaseModal({ - Key? key, + super.key, required this.onConfirm, required this.dialog - }) : super(key: key); + }); @override State createState() => _AddStaticLeaseModalState(); @@ -80,26 +80,28 @@ class _AddStaticLeaseModalState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.add, - size: 24, - color: Theme.of(context).listTileTheme.iconColor + Flexible( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.add, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.addStaticLease, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.addStaticLease, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), ), - ), - ], + ], + ), ), ], ), diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 84a4e76..88f1dad 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -414,6 +414,7 @@ class _DhcpScreenState extends State { const SizedBox(height: 30), Text( AppLocalizations.of(context)!.loadingDhcp, + textAlign: TextAlign.center, style: TextStyle( fontSize: 22, color: Theme.of(context).colorScheme.onSurfaceVariant, diff --git a/lib/screens/settings/dhcp/dhcp_interface_item.dart b/lib/screens/settings/dhcp/dhcp_interface_item.dart index 900328e..9d68f4e 100644 --- a/lib/screens/settings/dhcp/dhcp_interface_item.dart +++ b/lib/screens/settings/dhcp/dhcp_interface_item.dart @@ -8,10 +8,10 @@ class DhcpInterfaceItem extends StatelessWidget { final void Function(NetworkInterface) onSelect; const DhcpInterfaceItem({ - Key? key, + super.key, required this.networkInterface, required this.onSelect - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -56,6 +56,7 @@ class DhcpInterfaceItem extends StatelessWidget { const SizedBox(height: 5), if (networkInterface.flags.isNotEmpty) ...[ Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Flags: ", @@ -64,11 +65,13 @@ class DhcpInterfaceItem extends StatelessWidget { color: Theme.of(context).colorScheme.onSurfaceVariant ), ), - Text( - networkInterface.flags.join(', '), - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant + Flexible( + child: Text( + networkInterface.flags.join(', '), + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), ), ), ], diff --git a/lib/screens/settings/dhcp/select_interface_modal.dart b/lib/screens/settings/dhcp/select_interface_modal.dart index 0a740fd..e2dc26d 100644 --- a/lib/screens/settings/dhcp/select_interface_modal.dart +++ b/lib/screens/settings/dhcp/select_interface_modal.dart @@ -13,11 +13,11 @@ class SelectInterfaceModal extends StatelessWidget { final bool dialog; const SelectInterfaceModal({ - Key? key, + super.key, required this.interfaces, required this.onSelect, required this.dialog - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/settings/dns/clear_dns_cache_dialog.dart b/lib/screens/settings/dns/clear_dns_cache_dialog.dart index 425d11d..b04c889 100644 --- a/lib/screens/settings/dns/clear_dns_cache_dialog.dart +++ b/lib/screens/settings/dns/clear_dns_cache_dialog.dart @@ -5,9 +5,9 @@ class ClearDnsCacheDialog extends StatelessWidget { final void Function() onConfirm; const ClearDnsCacheDialog({ - Key? key, + super.key, required this.onConfirm - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -22,6 +22,7 @@ class ClearDnsCacheDialog extends StatelessWidget { const SizedBox(height: 16), Text( AppLocalizations.of(context)!.clearDnsCache, + textAlign: TextAlign.center, style: TextStyle( fontSize: 24, color: Theme.of(context).colorScheme.onSurface diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 236b107..8b5ee0d 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -19,7 +19,7 @@ import 'package:adguard_home_manager/models/rewrite_rules.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; class DnsRewritesScreen extends StatefulWidget { - const DnsRewritesScreen({Key? key}) : super(key: key); + const DnsRewritesScreen({super.key}); @override State createState() => _DnsRewritesScreenState(); @@ -152,6 +152,7 @@ class _DnsRewritesScreenState extends State { const SizedBox(height: 30), Text( AppLocalizations.of(context)!.loadingRewriteRules, + textAlign: TextAlign.center, style: TextStyle( fontSize: 22, color: Theme.of(context).colorScheme.onSurfaceVariant, @@ -305,6 +306,7 @@ class _DnsRewritesScreenState extends State { const SizedBox(height: 30), Text( AppLocalizations.of(context)!.rewriteRulesNotLoaded, + textAlign: TextAlign.center, style: TextStyle( fontSize: 22, color: Theme.of(context).colorScheme.onSurfaceVariant, diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 4f6713a..99f6ad7 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -177,10 +177,12 @@ class _SafeSearchSettingsScreenState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - AppLocalizations.of(context)!.enableSafeSearch, - style: const TextStyle( - fontSize: 18 + Flexible( + child: Text( + AppLocalizations.of(context)!.enableSafeSearch, + style: const TextStyle( + fontSize: 18 + ), ), ), Switch( diff --git a/lib/widgets/custom_list_tile_dialog.dart b/lib/widgets/custom_list_tile_dialog.dart index 2e3cff4..3faf8d4 100644 --- a/lib/widgets/custom_list_tile_dialog.dart +++ b/lib/widgets/custom_list_tile_dialog.dart @@ -29,12 +29,14 @@ class CustomListTileDialog extends StatelessWidget { ), const SizedBox(width: 24), ], - Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface, + Flexible( + child: Text( + title, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), ), ) ], From e01cc5ba65a52dcd5587cf870125b83fa131efd0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 29 Nov 2023 11:57:14 +0100 Subject: [PATCH 440/676] Removed unused import --- lib/screens/logs/configuration/logs_config_modal.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/screens/logs/configuration/logs_config_modal.dart b/lib/screens/logs/configuration/logs_config_modal.dart index 1b6c641..6352f36 100644 --- a/lib/screens/logs/configuration/logs_config_modal.dart +++ b/lib/screens/logs/configuration/logs_config_modal.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; From 5f9d24cc5fb129a920739cf89d39bb719c513941 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 29 Nov 2023 17:18:35 +0100 Subject: [PATCH 441/676] Changed top items --- .../home/top_items/top_items_lists.dart | 12 +- .../home/top_items/top_items_screen.dart | 324 ++++++++++++++++++ ...{top_items.dart => top_items_section.dart} | 72 ++-- lib/screens/top_items/top_items.dart | 241 ------------- lib/screens/top_items/top_items_modal.dart | 218 ------------ 5 files changed, 365 insertions(+), 502 deletions(-) create mode 100644 lib/screens/home/top_items/top_items_screen.dart rename lib/screens/home/top_items/{top_items.dart => top_items_section.dart} (86%) delete mode 100644 lib/screens/top_items/top_items.dart delete mode 100644 lib/screens/top_items/top_items_modal.dart diff --git a/lib/screens/home/top_items/top_items_lists.dart b/lib/screens/home/top_items/top_items_lists.dart index 2f8820d..7f230fb 100644 --- a/lib/screens/home/top_items/top_items_lists.dart +++ b/lib/screens/home/top_items/top_items_lists.dart @@ -4,7 +4,7 @@ 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/home/top_items/top_items.dart'; +import 'package:adguard_home_manager/screens/home/top_items/top_items_section.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -106,7 +106,7 @@ class TopItemsLists extends StatelessWidget { case HomeTopItems.queriedDomains: return Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.topQueriedDomains, type: HomeTopItems.queriedDomains, data: statusProvider.serverStatus?.stats.topQueriedDomains ?? [], @@ -134,7 +134,7 @@ class TopItemsLists extends StatelessWidget { case HomeTopItems.blockedDomains: return Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.topBlockedDomains, type: HomeTopItems.blockedDomains, data: statusProvider.serverStatus?.stats.topBlockedDomains ?? [], @@ -162,7 +162,7 @@ class TopItemsLists extends StatelessWidget { case HomeTopItems.recurrentClients: return Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.topClients, type: HomeTopItems.recurrentClients, data: statusProvider.serverStatus?.stats.topClients ?? [], @@ -186,7 +186,7 @@ class TopItemsLists extends StatelessWidget { return statusProvider.serverStatus!.stats.topUpstreamResponses != null ? Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.topUpstreams, type: HomeTopItems.topUpstreams, data: statusProvider.serverStatus?.stats.topUpstreamResponses ?? [], @@ -210,7 +210,7 @@ class TopItemsLists extends StatelessWidget { return statusProvider.serverStatus!.stats.topUpstreamsAvgTime != null ? Column( children: [ - TopItems( + TopItemsSection( label: AppLocalizations.of(context)!.averageUpstreamResponseTime, type: HomeTopItems.avgUpstreamResponseTime, data: statusProvider.serverStatus?.stats.topUpstreamsAvgTime ?? [], diff --git a/lib/screens/home/top_items/top_items_screen.dart b/lib/screens/home/top_items/top_items_screen.dart new file mode 100644 index 0000000..01ac83e --- /dev/null +++ b/lib/screens/home/top_items/top_items_screen.dart @@ -0,0 +1,324 @@ +// ignore_for_file: use_build_context_synchronously + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:percent_indicator/percent_indicator.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/options_menu.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + +import 'package:adguard_home_manager/models/menu_option.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; + +class TopItemsScreen extends StatefulWidget { + final HomeTopItems type; + final String title; + final bool? isClient; + final List> data; + final bool withProgressBar; + final String Function(dynamic) buildValue; + final List options; + final void Function(dynamic)? onTapEntry; + final bool isFullscreen; + + const TopItemsScreen({ + super.key, + required this.type, + required this.title, + this.isClient, + required this.data, + required this.withProgressBar, + required this.buildValue, + required this.options, + this.onTapEntry, + required this.isFullscreen, + }); + + @override + State createState() => _TopItemsScreenState(); +} + +class _TopItemsScreenState extends State { + bool searchActive = false; + final TextEditingController searchController = TextEditingController(); + + List> data = []; + List> screenData = []; + + void search(String value) { + List> newValues = widget.data.where((item) => item.keys.toList()[0].contains(value)).toList(); + setState(() => screenData = newValues); + } + + @override + void initState() { + data = widget.data; + screenData = widget.data; + super.initState(); + } + + @override + Widget build(BuildContext context) { + double total = 0; + for (var element in data) { + total = total + double.parse(element.values.toList()[0].toString()); + } + + if (widget.isFullscreen == true) { + return Dialog.fullscreen( + child: Scaffold( + appBar: AppBar( + title: searchActive == true + ? Padding( + padding: const EdgeInsets.only(bottom: 3), + child: TextFormField( + controller: searchController, + onChanged: search, + decoration: InputDecoration( + hintText: AppLocalizations.of(context)!.search, + hintStyle: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + border: InputBorder.none, + ), + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18 + ), + autofocus: true, + ), + ) + : Text(widget.title), + leading: searchActive == true ? + IconButton( + onPressed: () => setState(() { + searchActive = false; + searchController.text = ''; + screenData = data; + }), + icon: const Icon(Icons.arrow_back), + tooltip: AppLocalizations.of(context)!.exitSearch, + ) : null, + actions: [ + if (searchActive == false) IconButton( + onPressed: () => setState(() => searchActive = true), + icon: const Icon(Icons.search), + tooltip: AppLocalizations.of(context)!.search, + ), + if (searchActive == true) IconButton( + onPressed: () => setState(() { + searchController.text = ''; + screenData = data; + }), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.clearSearch, + ), + const SizedBox(width: 8) + ], + ), + body: _Content( + buildValue: widget.buildValue, + isClient: widget.isClient, + onTapEntry: widget.onTapEntry, + options: widget.options, + screenData: screenData, + total: total, + withProgressBar: widget.withProgressBar, + ), + ), + ); + } + else { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 1, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, + ), + ], + ), + ), + Expanded( + flex: 1, + child: TextField( + controller: searchController, + onChanged: search, + decoration: InputDecoration( + filled: true, + fillColor: Theme.of(context).colorScheme.primary.withOpacity(0.1), + hintText: AppLocalizations.of(context)!.search, + prefixIcon: const Icon(Icons.search_rounded), + contentPadding: const EdgeInsets.only(left: 14, bottom: 9, top: 11), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + borderRadius: BorderRadius.circular(25.7), + ), + enabledBorder: UnderlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + borderRadius: BorderRadius.circular(25.7), + ), + ), + ), + ), + ], + ), + ), + Expanded( + child: _Content( + buildValue: widget.buildValue, + isClient: widget.isClient, + onTapEntry: widget.onTapEntry, + options: widget.options, + screenData: screenData, + total: total, + withProgressBar: widget.withProgressBar, + ), + ), + ], + ), + ), + ); + } + } +} + +class _Content extends StatelessWidget { + final List> screenData; + final bool? isClient; + final List options; + final bool withProgressBar; + final void Function(dynamic)? onTapEntry; + final String Function(dynamic) buildValue; + final double total; + + const _Content({ + required this.screenData, + required this.isClient, + required this.options, + required this.withProgressBar, + required this.onTapEntry, + required this.buildValue, + required this.total, + }); + + @override + Widget build(BuildContext context) { + final statusProvider = Provider.of(context); + + if (screenData.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.only(top: 0), + itemCount: screenData.length, + itemBuilder: (context, index) { + String? name; + if (isClient != null && isClient == true) { + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; + } catch (e) { + // ---- // + } + } + + return OptionsMenu( + options: options, + value: screenData[index].keys.toList()[0], + onTap: onTapEntry != null + ? (v) { + onTapEntry!(v); + Navigator.pop(context); + } + : null, + child: CustomListTile( + title: screenData[index].keys.toList()[0], + trailing: Text( + buildValue(screenData[index].values.toList()[0]), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + subtitleWidget: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (name != null) ...[ + Text( + name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 5), + ], + if (withProgressBar == true) Row( + children: [ + SizedBox( + width: 50, + child: Text( + "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor + ), + ), + ), + const SizedBox(width: 10), + Flexible( + child: LinearPercentIndicator( + animation: true, + lineHeight: 4, + animationDuration: 500, + curve: Curves.easeOut, + percent: screenData[index].values.toList()[0]/total, + barRadius: const Radius.circular(5), + progressColor: Theme.of(context).colorScheme.primary, + backgroundColor: Theme.of(context).colorScheme.surfaceVariant, + ), + ), + const SizedBox(width: 10), + ], + ), + ], + ) + ), + ); + } + ); + } + else { + return Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.noItemsSearch, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ); + } + } +} \ No newline at end of file diff --git a/lib/screens/home/top_items/top_items.dart b/lib/screens/home/top_items/top_items_section.dart similarity index 86% rename from lib/screens/home/top_items/top_items.dart rename to lib/screens/home/top_items/top_items_section.dart index 00fa63c..f084b3f 100644 --- a/lib/screens/home/top_items/top_items.dart +++ b/lib/screens/home/top_items/top_items_section.dart @@ -7,15 +7,14 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/home/top_items/row_item.dart'; -import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; -import 'package:adguard_home_manager/screens/top_items/top_items.dart'; +import 'package:adguard_home_manager/screens/home/top_items/top_items_screen.dart'; import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class TopItems extends StatefulWidget { +class TopItemsSection extends StatefulWidget { final HomeTopItems type; final String label; final List> data; @@ -25,7 +24,7 @@ class TopItems extends StatefulWidget { final List menuOptions; final void Function(dynamic)? onTapEntry; - const TopItems({ + const TopItemsSection({ super.key, required this.type, required this.label, @@ -38,10 +37,10 @@ class TopItems extends StatefulWidget { }); @override - State createState() => _TopItemsState(); + State createState() => _TopItemsState(); } -class _TopItemsState extends State { +class _TopItemsState extends State { bool _showChart = true; final colors = [ @@ -289,38 +288,37 @@ class _TopItemsState extends State { children: [ TextButton( onPressed: () => { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => TopItemsModal( - type: widget.type, - title: widget.label, - isClient: widget.type == HomeTopItems.recurrentClients, - data: widget.data, - withProgressBar: widget.withProgressBar, - buildValue: widget.buildValue, - options: widget.menuOptions, - onTapEntry: widget.onTapEntry, - ) + showGeneralDialog( + context: context, + barrierColor: !(width > 700 || !(Platform.isAndroid | Platform.isIOS)) + ?Colors.transparent + : Colors.black54, + transitionBuilder: (context, anim1, anim2, child) { + return SlideTransition( + position: Tween( + begin: const Offset(0, 1), + end: const Offset(0, 0) + ).animate( + CurvedAnimation( + parent: anim1, + curve: Curves.easeInOutCubicEmphasized + ) + ), + child: child, + ); + }, + pageBuilder: (context, animation, secondaryAnimation) => TopItemsScreen( + type: widget.type, + title: widget.label, + isClient: widget.type == HomeTopItems.recurrentClients, + data: widget.data, + withProgressBar: widget.withProgressBar, + buildValue: widget.buildValue, + options: widget.menuOptions, + onTapEntry: widget.onTapEntry, + isFullscreen: !(width > 700 || !(Platform.isAndroid | Platform.isIOS)), ) - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => TopItemsScreen( - type: widget.type, - title: widget.label, - isClient: widget.type == HomeTopItems.recurrentClients, - data: widget.data, - withProgressBar: widget.withProgressBar, - buildValue: widget.buildValue, - menuOptions: widget.menuOptions, - onTapEntry: widget.onTapEntry, - ) - ) - ) - } + ) }, child: Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart deleted file mode 100644 index 498ce75..0000000 --- a/lib/screens/top_items/top_items.dart +++ /dev/null @@ -1,241 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:percent_indicator/percent_indicator.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/widgets/options_menu.dart'; -import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; - -import 'package:adguard_home_manager/models/menu_option.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/functions/number_format.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; - -class TopItemsScreen extends StatefulWidget { - final HomeTopItems type; - final String title; - final bool? isClient; - final List> data; - final bool withProgressBar; - final String Function(dynamic) buildValue; - final List menuOptions; - final void Function(dynamic)? onTapEntry; - - const TopItemsScreen({ - super.key, - required this.type, - required this.title, - this.isClient, - required this.data, - required this.withProgressBar, - required this.buildValue, - required this.menuOptions, - this.onTapEntry, - }); - - @override - State createState() => _TopItemsScreenState(); -} - -class _TopItemsScreenState extends State { - bool searchActive = false; - final TextEditingController searchController = TextEditingController(); - - List> data = []; - List> screenData = []; - - void search(String value) { - List> newValues = widget.data.where((item) => item.keys.toList()[0].contains(value)).toList(); - setState(() => screenData = newValues); - } - - @override - void initState() { - data = widget.data; - screenData = widget.data; - super.initState(); - } - - @override - Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - double total = 0; - for (var element in data) { - total = total + double.parse(element.values.toList()[0].toString()); - } - - return Scaffold( - appBar: AppBar( - title: searchActive == true - ? Padding( - padding: const EdgeInsets.only(bottom: 3), - child: TextFormField( - controller: searchController, - onChanged: search, - decoration: InputDecoration( - hintText: AppLocalizations.of(context)!.search, - hintStyle: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - border: InputBorder.none, - ), - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - autofocus: true, - ), - ) - : Text(widget.title), - leading: searchActive == true ? - IconButton( - onPressed: () => setState(() { - searchActive = false; - searchController.text = ''; - screenData = data; - }), - icon: const Icon(Icons.arrow_back), - tooltip: AppLocalizations.of(context)!.exitSearch, - ) : null, - actions: [ - if (searchActive == false) IconButton( - onPressed: () => setState(() => searchActive = true), - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.search, - ), - if (searchActive == true) IconButton( - onPressed: () => setState(() { - searchController.text = ''; - screenData = data; - }), - icon: const Icon(Icons.clear_rounded), - tooltip: AppLocalizations.of(context)!.clearSearch, - ), - const SizedBox(width: 10) - ], - bottom: PreferredSize( - preferredSize: const Size(double.maxFinite, 1), - child: Container( - width: double.maxFinite, - height: 1, - decoration: BoxDecoration( - color: searchActive == true - ? Colors.grey.withOpacity(0.5) - : Colors.transparent - ), - ), - ), - ), - body: RefreshIndicator( - onRefresh: () async { - final result = await statusProvider.getServerStatus(); - if (mounted && result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.serverStatusNotRefreshed, - color: Colors.red - ); - } - }, - child: screenData.isNotEmpty - ? ListView.builder( - itemCount: screenData.length, - itemBuilder: (context, index) { - String? name; - if (widget.isClient != null && widget.isClient == true) { - try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; - } catch (e) { - // ---- // - } - } - - return OptionsMenu( - value: screenData[index].keys.toList()[0], - options: widget.menuOptions, - onTap: widget.onTapEntry != null - ? (v) { - widget.onTapEntry!(v); - Navigator.pop(context); - } - : null, - child: CustomListTile( - title: screenData[index].keys.toList()[0], - trailing: Text( - widget.buildValue(screenData[index].values.toList()[0]), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - subtitleWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (name != null) ...[ - Text( - name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 5), - ], - if (widget.withProgressBar == true) Row( - children: [ - SizedBox( - width: 50, - child: Text( - "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor - ), - ), - ), - const SizedBox(width: 10), - Flexible( - child: LinearPercentIndicator( - animation: true, - lineHeight: 4, - animationDuration: 500, - curve: Curves.easeOut, - percent: screenData[index].values.toList()[0]/total, - barRadius: const Radius.circular(5), - progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: Theme.of(context).colorScheme.surfaceVariant, - ), - ), - const SizedBox(width: 10), - ], - ), - ], - ) - ), - ); - } - ) - : Center( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.noItemsSearch, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - ) - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/top_items/top_items_modal.dart b/lib/screens/top_items/top_items_modal.dart deleted file mode 100644 index 36ea793..0000000 --- a/lib/screens/top_items/top_items_modal.dart +++ /dev/null @@ -1,218 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:percent_indicator/percent_indicator.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/widgets/options_menu.dart'; -import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; - -import 'package:adguard_home_manager/models/menu_option.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/functions/number_format.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; - -class TopItemsModal extends StatefulWidget { - final HomeTopItems type; - final String title; - final bool? isClient; - final List> data; - final bool withProgressBar; - final String Function(dynamic) buildValue; - final List options; - final void Function(dynamic)? onTapEntry; - - const TopItemsModal({ - super.key, - required this.type, - required this.title, - this.isClient, - required this.data, - required this.withProgressBar, - required this.buildValue, - required this.options, - this.onTapEntry, - }); - - @override - State createState() => _TopItemsModalState(); -} - -class _TopItemsModalState extends State { - bool searchActive = false; - final TextEditingController searchController = TextEditingController(); - - List> data = []; - List> screenData = []; - - void search(String value) { - List> newValues = widget.data.where((item) => item.keys.toList()[0].contains(value)).toList(); - setState(() => screenData = newValues); - } - - @override - void initState() { - data = widget.data; - screenData = widget.data; - super.initState(); - } - - @override - Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - - double total = 0; - for (var element in data) { - total = total + double.parse(element.values.toList()[0].toString()); - } - - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - flex: 1, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.clear_rounded), - tooltip: AppLocalizations.of(context)!.close, - ), - ], - ), - ), - Expanded( - flex: 1, - child: TextField( - controller: searchController, - onChanged: search, - decoration: InputDecoration( - filled: true, - fillColor: Theme.of(context).colorScheme.primary.withOpacity(0.1), - hintText: AppLocalizations.of(context)!.search, - prefixIcon: const Icon(Icons.search_rounded), - contentPadding: const EdgeInsets.only(left: 14, bottom: 9, top: 11), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent), - borderRadius: BorderRadius.circular(25.7), - ), - enabledBorder: UnderlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent), - borderRadius: BorderRadius.circular(25.7), - ), - ), - ), - ) - ], - ), - ), - if (screenData.isNotEmpty) Flexible( - child: ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: screenData.length, - itemBuilder: (context, index) { - String? name; - if (widget.isClient != null && widget.isClient == true) { - try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; - } catch (e) { - // ---- // - } - } - - return OptionsMenu( - options: widget.options, - value: screenData[index].keys.toList()[0], - onTap: widget.onTapEntry != null - ? (v) { - widget.onTapEntry!(v); - Navigator.pop(context); - } - : null, - child: CustomListTile( - title: screenData[index].keys.toList()[0], - trailing: Text( - widget.buildValue(screenData[index].values.toList()[0]), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - subtitleWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (name != null) ...[ - Text( - name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 5), - ], - if (widget.withProgressBar == true) Row( - children: [ - SizedBox( - width: 50, - child: Text( - "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor - ), - ), - ), - const SizedBox(width: 10), - Flexible( - child: LinearPercentIndicator( - animation: true, - lineHeight: 4, - animationDuration: 500, - curve: Curves.easeOut, - percent: screenData[index].values.toList()[0]/total, - barRadius: const Radius.circular(5), - progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: Theme.of(context).colorScheme.surfaceVariant, - ), - ), - const SizedBox(width: 10), - ], - ), - ], - ) - ), - ); - } - ), - ), - if (screenData.isEmpty) Center( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.noItemsSearch, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - ) - ], - ), - ), - ); - } -} \ No newline at end of file From d8eeb7a51b4c78697318263f3616f50577a8a684 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 29 Nov 2023 17:28:50 +0100 Subject: [PATCH 442/676] Improved text scale factor --- .../home/management_modal/main_switch.dart | 2 +- lib/screens/home/server_status.dart | 28 ++----------------- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/lib/screens/home/management_modal/main_switch.dart b/lib/screens/home/management_modal/main_switch.dart index 3dbe0ec..f746b0e 100644 --- a/lib/screens/home/management_modal/main_switch.dart +++ b/lib/screens/home/management_modal/main_switch.dart @@ -175,7 +175,7 @@ class _BottomRowState extends State<_BottomRow> { Widget build(BuildContext context) { final statusProvider = Provider.of(context); - final textScale = MediaQuery.of(context).textScaleFactor; + final textScale = MediaQuery.of(context).textScaler.scale(1); return Container( height: Platform.isMacOS || Platform.isLinux || Platform.isWindows diff --git a/lib/screens/home/server_status.dart b/lib/screens/home/server_status.dart index a0e1715..b716c82 100644 --- a/lib/screens/home/server_status.dart +++ b/lib/screens/home/server_status.dart @@ -16,31 +16,7 @@ class ServerStatusWidget extends StatelessWidget { @override Widget build(BuildContext context) { final width = MediaQuery.of(context).size.width; - final textScaleFactor = MediaQuery.of(context).textScaleFactor; - - double boxSize() { - if (textScaleFactor < 1 || (textScaleFactor >= 1 && textScaleFactor < 1.15)) { - return 65; - } - else if (textScaleFactor >= 1.15 && textScaleFactor < 1.3) { - return 75; - } - else if (textScaleFactor >= 1.3 && textScaleFactor < 1.45) { - return 80; - } - else if (textScaleFactor >= 1.45 && textScaleFactor < 1.6) { - return 85; - } - else if (textScaleFactor >= 1.6 && textScaleFactor < 1.85) { - return 100; - } - else if (textScaleFactor >= 1.85) { - return 110; - } - else { - return 65; - } - } + final textScaleFactor = MediaQuery.of(context).textScaler.scale(1); return Padding( padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16), @@ -65,7 +41,7 @@ class ServerStatusWidget extends StatelessWidget { crossAxisCount: width > 700 ? 4 : 2, crossAxisSpacing: 10, mainAxisSpacing: 10, - mainAxisExtent: boxSize() + mainAxisExtent: 70*textScaleFactor ), children: [ StatusBox( From 232fedd27377655d76096304728d93d2eaa80b5c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 30 Nov 2023 11:07:15 +0100 Subject: [PATCH 443/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index bfddb2f..c769999 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.12.1+112 +version: 2.12.2+113 environment: sdk: '>=2.18.1 <3.0.0' From 8e1dd6e22e4e86e974e898e3b905d2f893157f71 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 1 Dec 2023 02:03:13 +0100 Subject: [PATCH 444/676] Improved settings --- lib/screens/settings/settings.dart | 143 +++++++++++++++++------------ 1 file changed, 85 insertions(+), 58 deletions(-) diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 8d5f384..8edbc11 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -32,7 +32,7 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class Settings extends StatelessWidget { - const Settings({Key? key}) : super(key: key); + const Settings({super.key}); @override Widget build(BuildContext context) { @@ -55,13 +55,13 @@ class Settings extends StatelessWidget { ), ), ), - child: const SettingsWidget( + child: const _SettingsWidget( twoColumns: true, ), ); } else { - return const SettingsWidget( + return const _SettingsWidget( twoColumns: false, ); } @@ -69,19 +69,18 @@ class Settings extends StatelessWidget { ); } } -class SettingsWidget extends StatefulWidget { +class _SettingsWidget extends StatefulWidget { final bool twoColumns; - const SettingsWidget({ - Key? key, + const _SettingsWidget({ required this.twoColumns, - }) : super(key: key); + }); @override - State createState() => _SettingsWidgetState(); + State<_SettingsWidget> createState() => _SettingsWidgetState(); } -class _SettingsWidgetState extends State { +class _SettingsWidgetState extends State<_SettingsWidget> { @override void initState() { Provider.of(context, listen: false).setSelectedSettingsScreen(screen: null); @@ -100,43 +99,6 @@ class _SettingsWidgetState extends State { appConfigProvider.setSelectedSettingsScreen(screen: null); } - Widget settingsTile({ - required String title, - required String subtitle, - required IconData icon, - Widget? trailing, - required Widget screenToNavigate, - required int thisItem - }) { - if (widget.twoColumns) { - return CustomSettingsTile( - title: title, - subtitle: subtitle, - icon: icon, - trailing: trailing, - thisItem: thisItem, - selectedItem: appConfigProvider.selectedSettingsScreen, - onTap: () { - appConfigProvider.setSelectedSettingsScreen(screen: thisItem, notify: true); - SplitView.of(context).setSecondary(screenToNavigate); - }, - ); - } - else { - return CustomListTile( - title: title, - subtitle: subtitle, - icon: icon, - trailing: trailing, - onTap: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (context) => screenToNavigate) - ); - }, - ); - } - } - return Scaffold( body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ @@ -169,28 +131,31 @@ class _SettingsWidgetState extends State { serversProvider.apiClient2 != null ) ...[ SectionLabel(label: AppLocalizations.of(context)!.serverSettings), - settingsTile( + _SettingsTile( icon: Icons.search_rounded, title: AppLocalizations.of(context)!.safeSearch, subtitle: AppLocalizations.of(context)!.safeSearchSettings, thisItem: 0, screenToNavigate: const SafeSearchSettingsScreen(), + twoColumns: widget.twoColumns, ), - settingsTile( + _SettingsTile( icon: Icons.lock_rounded, title: AppLocalizations.of(context)!.accessSettings, subtitle: AppLocalizations.of(context)!.accessSettingsDescription, thisItem: 1, screenToNavigate: const AccessSettings(), + twoColumns: widget.twoColumns, ), - settingsTile( + _SettingsTile( icon: Icons.install_desktop_rounded, title: AppLocalizations.of(context)!.dhcpSettings, subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, thisItem: 2, screenToNavigate: const DhcpScreen(), + twoColumns: widget.twoColumns, ), - settingsTile( + _SettingsTile( icon: Icons.dns_rounded, title: AppLocalizations.of(context)!.dnsSettings, subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, @@ -198,22 +163,25 @@ class _SettingsWidgetState extends State { screenToNavigate: DnsSettings( splitView: widget.twoColumns, ), + twoColumns: widget.twoColumns, ), - settingsTile( + _SettingsTile( icon: Icons.security_rounded, title: AppLocalizations.of(context)!.encryptionSettings, subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, thisItem: 4, screenToNavigate: const EncryptionSettings(), + twoColumns: widget.twoColumns, ), - settingsTile( + _SettingsTile( icon: Icons.route_rounded, title: AppLocalizations.of(context)!.dnsRewrites, subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, thisItem: 5, screenToNavigate: const DnsRewritesScreen(), + twoColumns: widget.twoColumns, ), - if (serversProvider.updateAvailable.data != null) settingsTile( + if (serversProvider.updateAvailable.data != null) _SettingsTile( icon: Icons.system_update_rounded, title: AppLocalizations.of(context)!.updates, subtitle: AppLocalizations.of(context)!.updatesDescription, @@ -231,24 +199,27 @@ class _SettingsWidgetState extends State { : null, thisItem: 6, screenToNavigate: const UpdateScreen(), + twoColumns: widget.twoColumns, ), - settingsTile( + _SettingsTile( icon: Icons.info_rounded, title: AppLocalizations.of(context)!.serverInformation, subtitle: AppLocalizations.of(context)!.serverInformationDescription, thisItem: 7, screenToNavigate: const ServerInformation(), + twoColumns: widget.twoColumns, ), ], SectionLabel(label: AppLocalizations.of(context)!.appSettings), - settingsTile( + _SettingsTile( icon: Icons.palette_rounded, title: AppLocalizations.of(context)!.customization, subtitle: AppLocalizations.of(context)!.customizationDescription, thisItem: 8, screenToNavigate: const Customization(), + twoColumns: widget.twoColumns, ), - settingsTile( + _SettingsTile( icon: Icons.storage_rounded, title: AppLocalizations.of(context)!.servers, subtitle: serversProvider.selectedServer != null @@ -258,20 +229,23 @@ class _SettingsWidgetState extends State { : AppLocalizations.of(context)!.noServerSelected, thisItem: 9, screenToNavigate: const Servers(), + twoColumns: widget.twoColumns, ), - settingsTile( + _SettingsTile( icon: Icons.settings, title: AppLocalizations.of(context)!.generalSettings, subtitle: AppLocalizations.of(context)!.generalSettingsDescription, thisItem: 10, screenToNavigate: const GeneralSettings(), + twoColumns: widget.twoColumns, ), - settingsTile( + _SettingsTile( icon: Icons.build_outlined, title: AppLocalizations.of(context)!.advancedSettings, subtitle: AppLocalizations.of(context)!.advancedSetupDescription, thisItem: 11, screenToNavigate: const AdvancedSettings(), + twoColumns: widget.twoColumns, ), SectionLabel(label: AppLocalizations.of(context)!.aboutApp), CustomListTile( @@ -319,4 +293,57 @@ class _SettingsWidgetState extends State { ) ); } +} + +class _SettingsTile extends StatelessWidget { + final String title; + final String subtitle; + final IconData icon; + final Widget? trailing; + final Widget screenToNavigate; + final int thisItem; + final bool twoColumns; + + const _SettingsTile({ + required this.title, + required this.subtitle, + required this.icon, + this.trailing, + required this.screenToNavigate, + required this.thisItem, + required this.twoColumns + }); + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + + if (twoColumns) { + return CustomSettingsTile( + title: title, + subtitle: subtitle, + icon: icon, + trailing: trailing, + thisItem: thisItem, + selectedItem: appConfigProvider.selectedSettingsScreen, + onTap: () { + appConfigProvider.setSelectedSettingsScreen(screen: thisItem, notify: true); + SplitView.of(context).setSecondary(screenToNavigate); + }, + ); + } + else { + return CustomListTile( + title: title, + subtitle: subtitle, + icon: icon, + trailing: trailing, + onTap: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => screenToNavigate) + ); + }, + ); + } + } } \ No newline at end of file From b42306cde361953a6b793ab15a6f7219fc94a171 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 1 Dec 2023 02:14:12 +0100 Subject: [PATCH 445/676] Fixed screen change desktop mode reorder items screen --- .../general_settings/general_settings.dart | 20 ++- .../reorderable_top_items_home.dart | 142 +++++++----------- lib/screens/settings/settings.dart | 2 +- 3 files changed, 66 insertions(+), 98 deletions(-) diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index 4625136..20e13e8 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:store_checker/store_checker.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -20,7 +21,12 @@ import 'package:adguard_home_manager/functions/app_update_download_link.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class GeneralSettings extends StatefulWidget { - const GeneralSettings({Key? key}) : super(key: key); + final bool splitView; + + const GeneralSettings({ + super.key, + required this.splitView, + }); @override State createState() => _GeneralSettingsState(); @@ -191,11 +197,13 @@ class _GeneralSettingsState extends State { icon: Icons.reorder_rounded, title: AppLocalizations.of(context)!.topItemsOrder, subtitle: AppLocalizations.of(context)!.topItemsOrderDescription, - onTap: () => Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const ReorderableTopItemsHome() - ) - ) + onTap: () => widget.splitView == true + ? SplitView.of(context).push(const ReorderableTopItemsHome()) + : Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const ReorderableTopItemsHome() + ) + ) ), CustomListTile( icon: Icons.donut_large_rounded, diff --git a/lib/screens/settings/general_settings/reorderable_top_items_home.dart b/lib/screens/settings/general_settings/reorderable_top_items_home.dart index 2b7bfe1..9d5e8ed 100644 --- a/lib/screens/settings/general_settings/reorderable_top_items_home.dart +++ b/lib/screens/settings/general_settings/reorderable_top_items_home.dart @@ -136,42 +136,6 @@ class _ReorderableTopItemsHomeState extends State { } } - Future onWillPopScope(bool popInvoked) async { - if (!listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList)) { - await showDialog( - context: context, - useRootNavigator: false, - builder: (ctx) => AlertDialog( - title: Text(AppLocalizations.of(context)!.discardChanges), - content: Text(AppLocalizations.of(context)!.discardChangesDescription), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () { - Navigator.pop(context); - Navigator.pop(context); - }, - child: Text(AppLocalizations.of(context)!.confirm) - ), - const SizedBox(width: 8), - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ), - ], - ) - ], - ) - ); - return false; - } - else { - return true; - } - } - void saveSettings() async { final result = await appConfigProvider.setHomeTopItemsOrder(homeTopItemsList); if (result == true) { @@ -190,64 +154,60 @@ class _ReorderableTopItemsHomeState extends State { } } - return PopScope( - canPop: listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList), - onPopInvoked: onWillPopScope, - child: Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.topItemsOrder), - surfaceTintColor: isDesktop(width) ? Colors.transparent : null, - actions: [ - IconButton( - onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList) - ? () => saveSettings() - : null, - icon: const Icon(Icons.save_rounded), - tooltip: AppLocalizations.of(context)!.save, - ), - const SizedBox(width: 8) - ], - ), - body: Column( - children: [ - Card( - margin: const EdgeInsets.all(16), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Icon( - Icons.info_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(width: 16), - Flexible( - child: Text(AppLocalizations.of(context)!.topItemsReorderInfo) - ) - ], - ), - ), - ), - Expanded( - child: reorderable_list_library.ReorderableList( - onReorder: _reorderCallback, - onReorderDone: _reorderDone, - child: ListView.builder( - itemBuilder: (context, index) => reorderable_list_library.ReorderableItem( - key: renderItems[index].key, - childBuilder: (context, state) => _Item( - tileWidget: tile(renderItems[index].title), - isFirst: index == 0, - isLast: index == renderItems.length - 1, - state: state - ), + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.topItemsOrder), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, + actions: [ + IconButton( + onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList) + ? () => saveSettings() + : null, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 8) + ], + ), + body: Column( + children: [ + Card( + margin: const EdgeInsets.all(16), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - itemCount: renderItems.length, - ) + const SizedBox(width: 16), + Flexible( + child: Text(AppLocalizations.of(context)!.topItemsReorderInfo) + ) + ], ), ), - ], - ), + ), + Expanded( + child: reorderable_list_library.ReorderableList( + onReorder: _reorderCallback, + onReorderDone: _reorderDone, + child: ListView.builder( + itemBuilder: (context, index) => reorderable_list_library.ReorderableItem( + key: renderItems[index].key, + childBuilder: (context, state) => _Item( + tileWidget: tile(renderItems[index].title), + isFirst: index == 0, + isLast: index == renderItems.length - 1, + state: state + ), + ), + itemCount: renderItems.length, + ) + ), + ), + ], ), ); } diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 8edbc11..6efdd9b 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -236,7 +236,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { title: AppLocalizations.of(context)!.generalSettings, subtitle: AppLocalizations.of(context)!.generalSettingsDescription, thisItem: 10, - screenToNavigate: const GeneralSettings(), + screenToNavigate: GeneralSettings(splitView: widget.twoColumns), twoColumns: widget.twoColumns, ), _SettingsTile( From ac6e8f700035fc969d9c3c769c8afa21f5f5657b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 1 Dec 2023 02:45:17 +0100 Subject: [PATCH 446/676] Improved reorderable list --- .../reorderable_top_items_home.dart | 150 +++++++++++------- 1 file changed, 91 insertions(+), 59 deletions(-) diff --git a/lib/screens/settings/general_settings/reorderable_top_items_home.dart b/lib/screens/settings/general_settings/reorderable_top_items_home.dart index 9d5e8ed..46e3a58 100644 --- a/lib/screens/settings/general_settings/reorderable_top_items_home.dart +++ b/lib/screens/settings/general_settings/reorderable_top_items_home.dart @@ -1,9 +1,9 @@ -// ignore_for_file: use_build_context_synchronously +import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:flutter_reorderable_list/flutter_reorderable_list.dart' as reorderable_list_library; +import 'package:flutter_reorderable_list/flutter_reorderable_list.dart' as reorderable_list; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; @@ -138,6 +138,7 @@ class _ReorderableTopItemsHomeState extends State { void saveSettings() async { final result = await appConfigProvider.setHomeTopItemsOrder(homeTopItemsList); + if (!mounted) return; if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, @@ -153,6 +154,10 @@ class _ReorderableTopItemsHomeState extends State { ); } } + + final draggingMode = Platform.isAndroid + ? DraggingMode.android + : DraggingMode.iOS; return Scaffold( appBar: AppBar( @@ -190,18 +195,34 @@ class _ReorderableTopItemsHomeState extends State { ), ), Expanded( - child: reorderable_list_library.ReorderableList( + child: reorderable_list.ReorderableList( onReorder: _reorderCallback, onReorderDone: _reorderDone, child: ListView.builder( - itemBuilder: (context, index) => reorderable_list_library.ReorderableItem( + itemBuilder: (context, index) => reorderable_list.ReorderableItem( key: renderItems[index].key, - childBuilder: (context, state) => _Item( - tileWidget: tile(renderItems[index].title), - isFirst: index == 0, - isLast: index == renderItems.length - 1, - state: state - ), + childBuilder: (context, state) { + if (draggingMode == DraggingMode.android) { + return reorderable_list.DelayedReorderableListener( + child: _Tile( + draggingMode: draggingMode, + isFirst: index == 0, + isLast: index == renderItems.length - 1, + state: state, + tileWidget: tile(renderItems[index].title), + ), + ); + } + else { + return _Tile( + draggingMode: draggingMode, + isFirst: index == 0, + isLast: index == renderItems.length - 1, + state: state, + tileWidget: tile(renderItems[index].title), + ); + } + }, ), itemCount: renderItems.length, ) @@ -213,68 +234,79 @@ class _ReorderableTopItemsHomeState extends State { } } -class _Item extends StatelessWidget { +class _Tile extends StatelessWidget { final Widget tileWidget; final bool isFirst; final bool isLast; - final reorderable_list_library.ReorderableItemState state; + final reorderable_list.ReorderableItemState state; + final DraggingMode draggingMode; - const _Item({ + const _Tile({ required this.tileWidget, required this.isFirst, required this.isLast, required this.state, + required this.draggingMode }); @override Widget build(BuildContext context) { - BoxDecoration decoration; - - if ( - state == reorderable_list_library.ReorderableItemState.dragProxy || - state == reorderable_list_library.ReorderableItemState.dragProxyFinished - ) { - decoration = BoxDecoration( - color: Theme.of(context).colorScheme.surface.withOpacity(0.7) - ); - } - else { - bool placeholder = state == reorderable_list_library.ReorderableItemState.placeholder; - decoration = BoxDecoration( - border: Border( - top: isFirst && !placeholder ? BorderSide( - width: 1, - color: Theme.of(context).colorScheme.primary.withOpacity(0.1) - ) : BorderSide.none, - bottom: isLast && placeholder ? BorderSide.none : BorderSide( - width: 1, - color: Theme.of(context).colorScheme.primary.withOpacity(0.1) - ), - ), - ); - } - - return reorderable_list_library.DelayedReorderableListener( - child: Container( - decoration: decoration, - child: SafeArea( - top: false, - bottom: false, - child: Opacity( - opacity: state == reorderable_list_library.ReorderableItemState.placeholder ? 0.0 : 1.0, - child: IntrinsicHeight( - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: tileWidget - ), - ], - ), + BoxDecoration getDecoration() { + if ( + state == reorderable_list.ReorderableItemState.dragProxy || + state == reorderable_list.ReorderableItemState.dragProxyFinished + ) { + return BoxDecoration( + color: Theme.of(context).colorScheme.surface.withOpacity(0.7) + ); + } + else { + bool placeholder = state == reorderable_list.ReorderableItemState.placeholder; + return BoxDecoration( + border: Border( + top: isFirst && !placeholder ? BorderSide( + width: 1, + color: Theme.of(context).colorScheme.primary.withOpacity(0.1) + ) : BorderSide.none, + bottom: isLast && placeholder ? BorderSide.none : BorderSide( + width: 1, + color: Theme.of(context).colorScheme.primary.withOpacity(0.1) ), - ) - ), - ) + ), + ); + } + } + + return Container( + decoration: getDecoration(), + child: SafeArea( + top: false, + bottom: false, + child: Opacity( + opacity: state == reorderable_list.ReorderableItemState.placeholder ? 0.0 : 1.0, + child: IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: tileWidget + ), + if (draggingMode == DraggingMode.iOS) reorderable_list.ReorderableListener( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Center( + child: Icon( + Icons.reorder, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ) + ], + ), + ), + ) + ), ); } } \ No newline at end of file From 1f74da906a5544ea2764ee9b563fa2b733650695 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 1 Dec 2023 02:50:55 +0100 Subject: [PATCH 447/676] Fix --- lib/screens/filters/list_options_menu.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 4cb6865..32e4610 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -56,7 +56,8 @@ class ListOptionsMenu extends StatelessWidget { ); processModal.close(); - + + if (!context.mounted) return; if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, From 2511ac2c24c2d6b52eaf9ad21681d782193867ef Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 1 Dec 2023 02:52:10 +0100 Subject: [PATCH 448/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index c769999..32d01fc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.12.2+113 +version: 2.12.3+114 environment: sdk: '>=2.18.1 <3.0.0' From 83ea5891876f4d690c579ab361cc8d981dec97a5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 8 Dec 2023 20:43:45 +0100 Subject: [PATCH 449/676] Support AGH without DHCP server --- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/models/dhcp.dart | 4 +- lib/providers/dhcp_provider.dart | 4 +- lib/screens/settings/dhcp/dhcp.dart | 418 +++++++----------- .../settings/dhcp/dhcp_main_button.dart | 76 ++++ .../settings/dhcp/dhcp_not_available.dart | 47 ++ lib/services/api_client.dart | 7 +- lib/services/http_requests.dart | 1 + 9 files changed, 291 insertions(+), 274 deletions(-) create mode 100644 lib/screens/settings/dhcp/dhcp_main_button.dart create mode 100644 lib/screens/settings/dhcp/dhcp_not_available.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index b9ba629..fb875cc 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -688,5 +688,7 @@ "yourVersion": "Your version: {version}", "minimumRequiredVersion": "Minimum required version: {version}", "topUpstreams": "Top upstreams", - "averageUpstreamResponseTime": "Average upstream response time" + "averageUpstreamResponseTime": "Average upstream response time", + "dhcpNotAvailable": "The DHCP server is not available.", + "osServerInstalledIncompatible": "The OS where the server is installed is not compatible with this feature." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 0e1566c..cf328dc 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -688,5 +688,7 @@ "yourVersion": "Tu versión: {version}", "minimumRequiredVersion": "Versión mínima requerida: {version}", "topUpstreams": "DNS de subida más frecuentes", - "averageUpstreamResponseTime": "Tiempo promedio de respuesta upstream" + "averageUpstreamResponseTime": "Tiempo promedio de respuesta upstream", + "dhcpNotAvailable": "El servidor DHCP no está disponible.", + "osServerInstalledIncompatible": "El SO donde el servidor está instalado no es compatible con esta característica." } \ No newline at end of file diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index 21b460b..9e7f7ca 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -1,9 +1,11 @@ import 'dart:convert'; class DhcpModel { + bool dhcpAvailable; List networkInterfaces; - DhcpStatus dhcpStatus; + DhcpStatus? dhcpStatus; DhcpModel({ + required this.dhcpAvailable, required this.networkInterfaces, required this.dhcpStatus, }); diff --git a/lib/providers/dhcp_provider.dart b/lib/providers/dhcp_provider.dart index 637f870..4fbd66b 100644 --- a/lib/providers/dhcp_provider.dart +++ b/lib/providers/dhcp_provider.dart @@ -69,7 +69,7 @@ class DhcpProvider with ChangeNotifier { if (result.successful == true) { DhcpModel data = dhcp!; - data.dhcpStatus.staticLeases = data.dhcpStatus.staticLeases.where((l) => l.mac != lease.mac).toList(); + data.dhcpStatus!.staticLeases = data.dhcpStatus!.staticLeases.where((l) => l.mac != lease.mac).toList(); setDhcpData(data); return true; } @@ -90,7 +90,7 @@ class DhcpProvider with ChangeNotifier { if (result.successful == true) { DhcpModel data = dhcp!; - data.dhcpStatus.staticLeases.add(lease); + data.dhcpStatus!.staticLeases.add(lease); setDhcpData(data); return result; } diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 88f1dad..fff464e 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -7,8 +7,10 @@ import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/section_label.dart'; +import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_not_available.dart'; import 'package:adguard_home_manager/widgets/confirm_action_modal.dart'; +import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_main_button.dart'; +import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_leases.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/select_interface_modal.dart'; @@ -22,7 +24,7 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class DhcpScreen extends StatefulWidget { - const DhcpScreen({Key? key}) : super(key: key); + const DhcpScreen({super.key}); @override State createState() => _DhcpScreenState(); @@ -55,24 +57,25 @@ class _DhcpScreenState extends State { void loadDhcpStatus() async { final result = await Provider.of(context, listen: false).loadDhcpStatus(); - if (mounted && result == true) { - final dhcpProvider = Provider.of(context, listen: false); - if (dhcpProvider.dhcp != null) { - setState(() { - if (dhcpProvider.dhcp!.dhcpStatus.interfaceName != null && dhcpProvider.dhcp!.dhcpStatus.interfaceName != '') { - try {selectedInterface = dhcpProvider.dhcp!.networkInterfaces.firstWhere((iface) => iface.name == dhcpProvider.dhcp!.dhcpStatus.interfaceName);} catch (_) {} - enabled = dhcpProvider.dhcp!.dhcpStatus.enabled; - if (dhcpProvider.dhcp!.dhcpStatus.v4 != null) { - ipv4StartRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.rangeStart; - ipv4EndRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.rangeEnd ?? ''; - ipv4SubnetMaskController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.subnetMask ?? ''; - ipv4GatewayController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.gatewayIp ?? ''; - ipv4LeaseTimeController.text = dhcpProvider.dhcp!.dhcpStatus.v4!.leaseDuration.toString(); - } - } - }); + if (!mounted || result == false) return; + + final dhcpProvider = Provider.of(context, listen: false); + if (dhcpProvider.dhcp == null) return; + + setState(() { + if (dhcpProvider.dhcp!.dhcpStatus!.interfaceName != null && dhcpProvider.dhcp!.dhcpStatus!.interfaceName != '') { + try {selectedInterface = dhcpProvider.dhcp!.networkInterfaces.firstWhere((iface) => iface.name == dhcpProvider.dhcp!.dhcpStatus!.interfaceName);} catch (_) {} + enabled = dhcpProvider.dhcp!.dhcpStatus!.enabled; + if (dhcpProvider.dhcp!.dhcpStatus!.v4 != null) { + ipv4StartRangeController.text = dhcpProvider.dhcp!.dhcpStatus!.v4!.rangeStart; + ipv4EndRangeController.text = dhcpProvider.dhcp!.dhcpStatus!.v4!.rangeEnd ?? ''; + ipv4SubnetMaskController.text = dhcpProvider.dhcp!.dhcpStatus!.v4!.subnetMask ?? ''; + ipv4GatewayController.text = dhcpProvider.dhcp!.dhcpStatus!.v4!.gatewayIp ?? ''; + ipv4LeaseTimeController.text = dhcpProvider.dhcp!.dhcpStatus!.v4!.leaseDuration.toString(); + } } - } + }); + checkDataValid(); } @@ -266,8 +269,8 @@ class _DhcpScreenState extends State { if (result.successful == true) { DhcpModel data = dhcpProvider.dhcp!; - data.dhcpStatus.staticLeases = []; - data.dhcpStatus.leases = []; + data.dhcpStatus!.staticLeases = []; + data.dhcpStatus!.leases = []; dhcpProvider.setDhcpData(data); showSnacbkar( @@ -350,6 +353,14 @@ class _DhcpScreenState extends State { }); } + if ( + dhcpProvider.loadStatus == LoadStatus.loaded && + dhcpProvider.dhcp != null && + dhcpProvider.dhcp!.dhcpAvailable == false + ) { + return const DhcpNotAvailable(); + } + return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.dhcpSettings), @@ -429,60 +440,10 @@ class _DhcpScreenState extends State { return SingleChildScrollView( child: Wrap( children: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - left: 16, - right: 16 - ), - child: Material( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(28), - child: InkWell( - onTap: selectedInterface != null - ? () => setState(() => enabled = !enabled) - : null, - borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.enableDhcpServer, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - if (selectedInterface != null) ...[ - Text( - selectedInterface!.name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).listTileTheme.textColor - ), - ) - ] - ], - ), - Switch( - value: enabled, - onChanged: selectedInterface != null - ? (value) => setState(() => enabled = value) - : null, - ), - ], - ), - ), - ), - ), + DhcpMainButton( + selectedInterface: selectedInterface, + enabled: enabled, + setEnabled: (v) => setState(() => enabled = v) ), if (selectedInterface!.ipv4Addresses.isNotEmpty) ...[ SectionLabel( @@ -491,125 +452,47 @@ class _DhcpScreenState extends State { top: 24, left: 16, right: 16, bottom: 8 ) ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4StartRangeController, - onChanged: (value) => validateIpV4(value, 'ipv4StartRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_previous_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4StartRangeError, - labelText: AppLocalizations.of(context)!.startOfRange, - ), - keyboardType: TextInputType.number, - ), - ), + _DhcpField( + icon: Icons.skip_previous_rounded, + label: AppLocalizations.of(context)!.startOfRange, + controller: ipv4StartRangeController, + onChanged: (value) => validateIpV4(value, 'ipv4StartRangeError', AppLocalizations.of(context)!.ipNotValid), + error: ipv4StartRangeError ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4EndRangeController, - onChanged: (value) => validateIpV4(value, 'ipv4EndRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_next_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4EndRangeError, - labelText: AppLocalizations.of(context)!.endOfRange, - ), - keyboardType: TextInputType.number, - ), - ), + _DhcpField( + icon: Icons.skip_next_rounded, + label: AppLocalizations.of(context)!.endOfRange, + controller: ipv4EndRangeController, + onChanged: (value) => validateIpV4(value, 'ipv4EndRangeError', AppLocalizations.of(context)!.ipNotValid), + error: ipv4EndRangeError ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4SubnetMaskController, - onChanged: (value) => validateIpV4(value, 'ipv4SubnetMaskError', AppLocalizations.of(context)!.subnetMaskNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.hub_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4SubnetMaskError, - labelText: AppLocalizations.of(context)!.subnetMask, - ), - keyboardType: TextInputType.number, - ), - ), + _DhcpField( + icon: Icons.hub_rounded, + label: AppLocalizations.of(context)!.subnetMask, + controller: ipv4SubnetMaskController, + onChanged: (value) => validateIpV4(value, 'ipv4SubnetMaskError', AppLocalizations.of(context)!.subnetMaskNotValid), + error: ipv4SubnetMaskError ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 12, bottom: 12, left: 8, right: 16) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4GatewayController, - onChanged: (value) => validateIpV4(value, 'ipv4GatewayError', AppLocalizations.of(context)!.gatewayNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.router_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4GatewayError, - labelText: AppLocalizations.of(context)!.gateway, - ), - keyboardType: TextInputType.number, - ), - ), + _DhcpField( + icon: Icons.router_rounded, + label: AppLocalizations.of(context)!.gateway, + controller: ipv4GatewayController, + onChanged: (value) => validateIpV4(value, 'ipv4GatewayError', AppLocalizations.of(context)!.gatewayNotValid), + error: ipv4GatewayError ), - FractionallySizedBox( - widthFactor: 1, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv4LeaseTimeController, - onChanged: (value) { - if (int.tryParse(value).runtimeType == int) { - setState(() => ipv4LeaseTimeError = null); - } - else { - setState(() => ipv4LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); - } - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.timer), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv4LeaseTimeError, - labelText: AppLocalizations.of(context)!.leaseTime, - ), - keyboardType: TextInputType.number, - ), - ), + _DhcpField( + icon: Icons.timer, + label: AppLocalizations.of(context)!.leaseTime, + controller: ipv4LeaseTimeController, + onChanged: (value) { + if (int.tryParse(value).runtimeType == int) { + setState(() => ipv4LeaseTimeError = null); + } + else { + setState(() => ipv4LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); + } + }, + error: ipv4LeaseTimeError ), ], if (selectedInterface!.ipv6Addresses.isNotEmpty) ...[ @@ -617,80 +500,34 @@ class _DhcpScreenState extends State { label: AppLocalizations.of(context)!.ipv6settings, padding: const EdgeInsets.all(16) ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 8, bottom: 12, left: 16, right: 8) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv6StartRangeController, - onChanged: (value) => validateIpV4(value, 'ipv6StartRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_next_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv6StartRangeError, - labelText: AppLocalizations.of(context)!.startOfRange, - ), - keyboardType: TextInputType.number, - ), - ), + _DhcpField( + icon: Icons.skip_next_rounded, + label: AppLocalizations.of(context)!.startOfRange, + controller: ipv6StartRangeController, + onChanged: (value) => validateIpV6(value, 'ipv6StartRangeError', AppLocalizations.of(context)!.ipNotValid), + error: ipv6StartRangeError ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.5 : 1, - child: Padding( - padding: width > 900 - ? const EdgeInsets.only(top: 8, bottom: 12, left: 8, right: 16) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv6EndRangeController, - onChanged: (value) => validateIpV4(value, 'ipv6EndRangeError', AppLocalizations.of(context)!.ipNotValid), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.skip_previous_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv6EndRangeError, - labelText: AppLocalizations.of(context)!.endOfRange, - ), - keyboardType: TextInputType.number, - ), - ), - ), - FractionallySizedBox( - widthFactor: 1, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: TextFormField( - controller: ipv6LeaseTimeController, - onChanged: (value) { - if (int.tryParse(value).runtimeType == int) { - setState(() => ipv6LeaseTimeError = null); - } - else { - setState(() => ipv6LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); - } - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.timer), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipv6LeaseTimeError, - labelText: AppLocalizations.of(context)!.leaseTime, - ), - keyboardType: TextInputType.number, - ), - ), + _DhcpField( + icon: Icons.skip_previous_rounded, + label: AppLocalizations.of(context)!.endOfRange, + controller: ipv6EndRangeController, + onChanged: (value) => validateIpV6(value, 'ipv6EndRangeError', AppLocalizations.of(context)!.ipNotValid), + error: ipv6EndRangeError ), + _DhcpField( + icon: Icons.timer, + label: AppLocalizations.of(context)!.leaseTime, + controller: ipv6LeaseTimeController, + onChanged: (value) { + if (int.tryParse(value).runtimeType == int) { + setState(() => ipv6LeaseTimeError = null); + } + else { + setState(() => ipv6LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); + } + }, + error: ipv6LeaseTimeError + ) ], const SizedBox(height: 20), SectionLabel( @@ -704,7 +541,7 @@ class _DhcpScreenState extends State { Navigator.of(context).push( MaterialPageRoute( builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.leases, + items: dhcpProvider.dhcp!.dhcpStatus!.leases, staticLeases: false, ) ) @@ -739,7 +576,7 @@ class _DhcpScreenState extends State { Navigator.of(context).push( MaterialPageRoute( builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, + items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, staticLeases: true, ) ) @@ -775,7 +612,7 @@ class _DhcpScreenState extends State { if (!(Platform.isAndroid || Platform.isIOS)) { SplitView.of(context).push( DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.leases, + items: dhcpProvider.dhcp!.dhcpStatus!.leases, staticLeases: false, ) ); @@ -784,7 +621,7 @@ class _DhcpScreenState extends State { Navigator.of(context).push( MaterialPageRoute( builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.leases, + items: dhcpProvider.dhcp!.dhcpStatus!.leases, staticLeases: false, ) ) @@ -804,7 +641,7 @@ class _DhcpScreenState extends State { if (!(Platform.isAndroid || Platform.isIOS)) { SplitView.of(context).push( DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, + items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, staticLeases: true, ) ); @@ -813,7 +650,7 @@ class _DhcpScreenState extends State { Navigator.of(context).push( MaterialPageRoute( builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, + items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, staticLeases: true, ) ) @@ -899,4 +736,49 @@ class _DhcpScreenState extends State { ) ); } +} + +class _DhcpField extends StatelessWidget { + final IconData icon; + final String label; + final TextEditingController controller; + final void Function(String) onChanged; + final String? error; + + const _DhcpField({ + required this.icon, + required this.label, + required this.controller, + required this.onChanged, + required this.error, + }); + + @override + Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + + return FractionallySizedBox( + widthFactor: width > 900 ? 0.5 : 1, + child: Padding( + padding: width > 900 + ? const EdgeInsets.only(top: 12, bottom: 12, left: 16, right: 8) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: TextFormField( + controller: controller, + onChanged: onChanged, + decoration: InputDecoration( + prefixIcon: Icon(icon), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: error, + labelText: label, + ), + keyboardType: TextInputType.number, + ), + ), + ); + } } \ No newline at end of file diff --git a/lib/screens/settings/dhcp/dhcp_main_button.dart b/lib/screens/settings/dhcp/dhcp_main_button.dart new file mode 100644 index 0000000..3e46a14 --- /dev/null +++ b/lib/screens/settings/dhcp/dhcp_main_button.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/models/dhcp.dart'; + +class DhcpMainButton extends StatelessWidget { + final NetworkInterface? selectedInterface; + final bool enabled; + final void Function(bool) setEnabled; + + const DhcpMainButton({ + super.key, + required this.selectedInterface, + required this.enabled, + required this.setEnabled, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only( + top: 10, + left: 16, + right: 16 + ), + child: Material( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: selectedInterface != null + ? () => setEnabled(!enabled) + : null, + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.enableDhcpServer, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + if (selectedInterface != null) ...[ + Text( + selectedInterface!.name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).listTileTheme.textColor + ), + ) + ] + ], + ), + Switch( + value: enabled, + onChanged: selectedInterface != null + ? (value) => setEnabled(value) + : null, + ), + ], + ), + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/dhcp/dhcp_not_available.dart b/lib/screens/settings/dhcp/dhcp_not_available.dart new file mode 100644 index 0000000..ceb3f6b --- /dev/null +++ b/lib/screens/settings/dhcp/dhcp_not_available.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/functions/desktop_mode.dart'; + +class DhcpNotAvailable extends StatelessWidget { + const DhcpNotAvailable({super.key}); + + @override + Widget build(BuildContext context) { + final width = MediaQuery.of(context).size.width; + + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.dhcpSettings), + centerTitle: false, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + AppLocalizations.of(context)!.dhcpNotAvailable, + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.w400, + fontSize: 24 + ), + ), + const SizedBox(height: 20), + Text( + AppLocalizations.of(context)!.osServerInstalledIncompatible, + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index 636cc34..f626f75 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -482,8 +482,13 @@ class ApiClientV2 { return ApiResponse( successful: true, content: DhcpModel( + dhcpAvailable: jsonDecode(results[1].body!)['message'] != null + ? false + : true, networkInterfaces: interfaces, - dhcpStatus: DhcpStatus.fromJson(jsonDecode(results[1].body!)) + dhcpStatus: jsonDecode(results[1].body!)['message'] != null + ? null + : DhcpStatus.fromJson(jsonDecode(results[1].body!)) ) ); } catch (e, stackTrace) { diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 2d001f2..37a2cc8 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1352,6 +1352,7 @@ class ApiClient { return { 'result': 'success', 'data': DhcpModel( + dhcpAvailable: true, networkInterfaces: interfaces, dhcpStatus: DhcpStatus.fromJson(jsonDecode(result[1]['body'])) ) From b164d520db51ea98915978c344462f836c7afe1f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Dec 2023 04:04:14 +0100 Subject: [PATCH 450/676] Changed system navigation bar color --- lib/main.dart | 2 + lib/screens/clients/client/client_screen.dart | 58 +- .../clients/client/logs_list_client.dart | 218 +++--- lib/screens/connect/connect.dart | 44 +- .../filters/details/add_list_modal.dart | 333 +++++---- .../filters/details/check_host_modal.dart | 352 ++++----- .../filters/details/list_details_screen.dart | 72 +- .../filters/modals/add_custom_rule.dart | 10 +- .../modals/blocked_services_screen.dart | 249 ++++--- .../filters/modals/delete_list_modal.dart | 4 +- .../modals/update_interval_lists_modal.dart | 10 +- .../filters/selection/selection_lists.dart | 5 +- .../management_modal/management_modal.dart | 88 +-- .../home/top_items/top_items_screen.dart | 18 +- .../logs/configuration/logs_config_modal.dart | 62 +- .../logs/details/log_details_screen.dart | 5 +- lib/screens/logs/filters/clients_modal.dart | 8 +- .../logs/filters/filter_status_modal.dart | 10 +- .../logs/filters/logs_filters_modal.dart | 12 +- lib/screens/servers/servers.dart | 50 +- .../access_settings/add_client_modal.dart | 8 +- lib/screens/settings/advanced_setings.dart | 48 +- .../settings/customization/customization.dart | 286 ++++---- .../settings/dhcp/add_static_lease_modal.dart | 335 ++++----- lib/screens/settings/dhcp/dhcp.dart | 624 ++++++++-------- lib/screens/settings/dhcp/dhcp_leases.dart | 56 +- .../settings/dhcp/select_interface_modal.dart | 17 +- lib/screens/settings/dns/bootstrap_dns.dart | 182 ++--- lib/screens/settings/dns/cache_config.dart | 146 ++-- lib/screens/settings/dns/comment_modal.dart | 259 ++++--- lib/screens/settings/dns/dns.dart | 178 ++--- .../settings/dns/dns_server_settings.dart | 242 ++++--- .../settings/dns/private_reverse_servers.dart | 258 +++---- lib/screens/settings/dns/upstream_dns.dart | 234 +++--- .../dns_rewrites/dns_rewrite_modal.dart | 10 +- .../settings/dns_rewrites/dns_rewrites.dart | 444 ++++++------ .../settings/dns_rewrites/rule_modal.dart | 0 .../dns_rewrites/server_version_needed.dart | 1 + .../settings/encryption/encryption.dart | 682 +++++++++--------- .../general_settings/general_settings.dart | 298 ++++---- .../settings/safe_search_settings.dart | 296 ++++---- .../settings/server_info/server_info.dart | 204 +++--- lib/screens/settings/theme_modal.dart | 4 +- .../settings/update_server/update.dart | 55 +- lib/widgets/add_server/add_server_modal.dart | 6 +- lib/widgets/system_ui_overlay_style.dart | 14 +- lib/widgets/tab_content_list.dart | 80 +- 47 files changed, 3370 insertions(+), 3207 deletions(-) delete mode 100644 lib/screens/settings/dns_rewrites/rule_modal.dart diff --git a/lib/main.dart b/lib/main.dart index 9734263..33f241d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:provider/provider.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; @@ -35,6 +36,7 @@ import 'package:adguard_home_manager/services/db/database.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { setWindowMinSize(const Size(500, 500)); diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index 2ab5c75..d4628e7 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -185,34 +185,36 @@ class _ClientScreenState extends State { ), actions: actions(), ), - 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), + body: SafeArea( + child: 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), + ), ), ), ); diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index bd4d2af..3267128 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -149,125 +149,127 @@ class _LogsListClientState extends State { ] ], ), - body: Builder( - builder: (context) { - switch (loadStatus) { - case 0: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingLogs, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case 1: - if (logsData!.data.isNotEmpty) { - return RefreshIndicator( - onRefresh: fetchLogs, - child: ListView.builder( - controller: scrollController, - padding: const EdgeInsets.only(top: 0), - itemCount: isLoadingMore == true - ? logsData!.data.length+1 - : logsData!.data.length, - itemBuilder: (context, index) { - if (isLoadingMore == true && index == logsData!.data.length) { - return const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - else { - return LogTile( - log: logsData!.data[index], - index: index, - length: logsData!.data.length, - useAlwaysNormalTile: true, - onLogTap: (log) => { - if (width > 700) { - showDialog( - context: context, - builder: (context) => LogDetailsScreen( - log: log, - dialog: true - ) - ) - } - else { - Navigator.of(context).push( - MaterialPageRoute( + body: SafeArea( + child: Builder( + builder: (context) { + switch (loadStatus) { + case 0: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingLogs, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case 1: + if (logsData!.data.isNotEmpty) { + return RefreshIndicator( + onRefresh: fetchLogs, + child: ListView.builder( + controller: scrollController, + padding: const EdgeInsets.only(top: 0), + itemCount: isLoadingMore == true + ? logsData!.data.length+1 + : logsData!.data.length, + itemBuilder: (context, index) { + if (isLoadingMore == true && index == logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else { + return LogTile( + log: logsData!.data[index], + index: index, + length: logsData!.data.length, + useAlwaysNormalTile: true, + onLogTap: (log) => { + if (width > 700) { + showDialog( + context: context, builder: (context) => LogDetailsScreen( log: log, - dialog: false + dialog: true ) ) - ) - } - }, - twoColumns: widget.splitView, - ); + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false + ) + ) + ) + } + }, + twoColumns: widget.splitView, + ); + } } - } - ), - ); - } - else { - return Center( - child: Text( - AppLocalizations.of(context)!.noLogsDisplay, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ), - ); - } - - case 2: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.logsNotLoaded, + ); + } + else { + return Center( + child: Text( + AppLocalizations.of(context)!.noLogsDisplay, textAlign: TextAlign.center, style: TextStyle( fontSize: 22, color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - }, + ), + ); + } + + case 2: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.logsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ), ) ); } diff --git a/lib/screens/connect/connect.dart b/lib/screens/connect/connect.dart index 3528718..01ac7cc 100644 --- a/lib/screens/connect/connect.dart +++ b/lib/screens/connect/connect.dart @@ -11,7 +11,7 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class Connect extends StatefulWidget { - const Connect({Key? key}) : super(key: key); + const Connect({super.key}); @override State createState() => _ConnectState(); @@ -61,26 +61,28 @@ class _ConnectState extends State { appBar: AppBar( title: Text(AppLocalizations.of(context)!.connect), ), - body: Stack( - children: [ - ServersList( - context: context, - controllers: expandableControllerList, - onChange: expandOrContract, - scrollController: scrollController, - breakingWidth: 700, - ), - AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: isVisible ? - appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, - right: 20, - child: const FabConnect() - ) - ], + body: SafeArea( + child: Stack( + children: [ + ServersList( + context: context, + controllers: expandableControllerList, + onChange: expandOrContract, + scrollController: scrollController, + breakingWidth: 700, + ), + AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: isVisible ? + appConfigProvider.showingSnackbar + ? 90 : 20 + : -90, + right: 20, + child: const FabConnect() + ) + ], + ), ), ); } diff --git a/lib/screens/filters/details/add_list_modal.dart b/lib/screens/filters/details/add_list_modal.dart index fceebf9..d5579a6 100644 --- a/lib/screens/filters/details/add_list_modal.dart +++ b/lib/screens/filters/details/add_list_modal.dart @@ -5,7 +5,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/models/filtering.dart'; -class AddListModal extends StatefulWidget { +class AddListModal extends StatelessWidget { final String type; final Filter? list; final void Function({required String name, required String url, required String type})? onConfirm; @@ -13,19 +13,74 @@ class AddListModal extends StatefulWidget { final bool dialog; const AddListModal({ - Key? key, + super.key, required this.type, this.list, this.onConfirm, this.onEdit, required this.dialog - }) : super(key: key); + }); @override - State createState() => _AddListModalState(); + Widget build(BuildContext context) { + if (dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: _Content( + list: list, + onConfirm: onConfirm, + onEdit: onEdit, + type: type, + ) + ), + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: SafeArea( + child: _Content( + list: list, + onConfirm: onConfirm, + onEdit: onEdit, + type: type, + ), + ) + ), + ); + } + } } -class _AddListModalState extends State { +class _Content extends StatefulWidget { + final String type; + final Filter? list; + final void Function({required String name, required String url, required String type})? onConfirm; + final void Function({required Filter list, required String type})? onEdit; + + const _Content({ + required this.type, + required this.list, + required this.onConfirm, + required this.onEdit, + }); + + @override + State<_Content> createState() => _ContentState(); +} + +class _ContentState extends State<_Content> { final TextEditingController nameController = TextEditingController(); final TextEditingController urlController = TextEditingController(); String? urlError; @@ -69,162 +124,134 @@ class _AddListModalState extends State { } @override - Widget build(BuildContext context) { - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - widget.type == 'whitelist' - ? Icons.verified_user_rounded - : Icons.gpp_bad_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - widget.list != null - ? widget.type == 'whitelist' - ? AppLocalizations.of(context)!.editWhitelist - : AppLocalizations.of(context)!.editBlacklist - : widget.type == 'whitelist' - ? AppLocalizations.of(context)!.addWhitelist - : AppLocalizations.of(context)!.addBlacklist, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - ], - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: nameController, - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.badge_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.name, - ), - ), - ), - Container(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: urlController, - onChanged: validateUrl, - enabled: widget.list != null ? false : true, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: urlError, - labelText: AppLocalizations.of(context)!.urlAbsolutePath, - ), - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + widget.type == 'whitelist' + ? Icons.verified_user_rounded + : Icons.gpp_bad_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + const SizedBox(height: 16), + Text( + widget.list != null + ? widget.type == 'whitelist' + ? AppLocalizations.of(context)!.editWhitelist + : AppLocalizations.of(context)!.editBlacklist + : widget.type == 'whitelist' + ? AppLocalizations.of(context)!.addWhitelist + : AppLocalizations.of(context)!.addBlacklist, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], ), - const SizedBox(width: 20), - TextButton( - onPressed: () { - Navigator.pop(context); - if (widget.list != null) { - final Filter newList = Filter( - url: urlController.text, - name: nameController.text, - lastUpdated: widget.list!.lastUpdated, - id: widget.list!.id, - rulesCount: widget.list!.rulesCount, - enabled: widget.list!.enabled - ); - widget.onEdit!( - list: newList, - type: widget.type - ); - } - else { - widget.onConfirm!( - name: nameController.text, - url: urlController.text, - type: widget.type - ); - } - }, - child: Text( - widget.list != null - ? AppLocalizations.of(context)!.save - : AppLocalizations.of(context)!.confirm - ) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: nameController, + onChanged: (_) => checkValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.badge_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.name, + ), + ), + ), + Container(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: urlController, + onChanged: validateUrl, + enabled: widget.list != null ? false : true, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: urlError, + labelText: AppLocalizations.of(context)!.urlAbsolutePath, + ), + ), ), ], ), ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ); - } - - if (widget.dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 400 - ), - child: content() ), - ); - } - else { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + const SizedBox(width: 20), + TextButton( + onPressed: () { + Navigator.pop(context); + if (widget.list != null) { + final Filter newList = Filter( + url: urlController.text, + name: nameController.text, + lastUpdated: widget.list!.lastUpdated, + id: widget.list!.id, + rulesCount: widget.list!.rulesCount, + enabled: widget.list!.enabled + ); + widget.onEdit!( + list: newList, + type: widget.type + ); + } + else { + widget.onConfirm!( + name: nameController.text, + url: urlController.text, + type: widget.type + ); + } + }, + child: Text( + widget.list != null + ? AppLocalizations.of(context)!.save + : AppLocalizations.of(context)!.confirm + ) + ), + ], ), - child: content() ), - ); - } + if (Platform.isIOS) const SizedBox(height: 16) + ], + ); } } \ No newline at end of file diff --git a/lib/screens/filters/details/check_host_modal.dart b/lib/screens/filters/details/check_host_modal.dart index 5325ada..3065588 100644 --- a/lib/screens/filters/details/check_host_modal.dart +++ b/lib/screens/filters/details/check_host_modal.dart @@ -8,19 +8,55 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class CheckHostModal extends StatefulWidget { +class CheckHostModal extends StatelessWidget { final bool dialog; const CheckHostModal({ - Key? key, + super.key, required this.dialog - }) : super(key: key); + }); @override - State createState() => _CheckHostModalState(); + Widget build(BuildContext context) { + if (dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: const _Content() + ), + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + width: double.maxFinite, + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28), + ), + color: Theme.of(context).dialogBackgroundColor + ), + child: const SafeArea( + child: _Content() + ) + ), + ); + } + } } -class _CheckHostModalState extends State { +class _Content extends StatefulWidget { + const _Content(); + + @override + State<_Content> createState() => _ContentState(); +} + +class _ContentState extends State<_Content> { final TextEditingController domainController = TextEditingController(); String? domainError; @@ -59,17 +95,29 @@ class _CheckHostModalState extends State { setState(() => resultWidget = checking()); final result = await serversProvider.apiClient2!.checkHostFiltered(host: domainController.text); + if (!mounted) return; - if (mounted) { - if (result.successful == true) { - final status = getFilteredStatus(context, appConfigProvider, result.content['reason'], true); - if (mounted) { - setState(() => resultWidget = Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - status['icon'], - size: 18, + if (result.successful == true) { + final status = getFilteredStatus(context, appConfigProvider, result.content['reason'], true); + if (mounted) { + setState(() => resultWidget = Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + status['icon'], + size: 18, + color: status['filtered'] == true + ? appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red + : appConfigProvider.useThemeColorForStatus + ? Theme.of(context).colorScheme.primary + : Colors.green, + ), + const SizedBox(width: 10), + Text( + status['label'], + style: TextStyle( color: status['filtered'] == true ? appConfigProvider.useThemeColorForStatus == true ? Colors.grey @@ -77,39 +125,6 @@ class _CheckHostModalState extends State { : appConfigProvider.useThemeColorForStatus ? Theme.of(context).colorScheme.primary : Colors.green, - ), - const SizedBox(width: 10), - Text( - status['label'], - style: TextStyle( - color: status['filtered'] == true - ? appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red - : appConfigProvider.useThemeColorForStatus - ? Theme.of(context).colorScheme.primary - : Colors.green, - fontWeight: FontWeight.w500 - ), - ) - ], - )); - } - } - else { - setState(() => resultWidget = Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.cancel, - size: 18, - color: Colors.red, - ), - const SizedBox(width: 10), - Text( - AppLocalizations.of(context)!.check, - style: const TextStyle( - color: Colors.red, fontWeight: FontWeight.w500 ), ) @@ -117,143 +132,134 @@ class _CheckHostModalState extends State { )); } } + else { + setState(() => resultWidget = Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.cancel, + size: 18, + color: Colors.red, + ), + const SizedBox(width: 10), + Text( + AppLocalizations.of(context)!.check, + style: const TextStyle( + color: Colors.red, + fontWeight: FontWeight.w500 + ), + ) + ], + )); + } } - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.checkHostFiltered, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - ], - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: domainController, - onChanged: validateDomain, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) ), - errorText: domainError, - labelText: AppLocalizations.of(context)!.domain, + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.checkHostFiltered, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: domainController, + onChanged: validateDomain, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: domainError, + labelText: AppLocalizations.of(context)!.domain, + ), + ), + ), + if (resultWidget != null) Padding( + padding: const EdgeInsets.all(24), + child: resultWidget, + ), + if (resultWidget == null) Padding( + padding: const EdgeInsets.all(24), + child: Center( + child: Text( + AppLocalizations.of(context)!.insertDomain, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 16, ), ), ), - if (resultWidget != null) Padding( - padding: const EdgeInsets.all(24), - child: resultWidget, + ), + ], + ), + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only( + bottom: 24, + right: 24 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close), ), - if (resultWidget == null) Padding( - padding: const EdgeInsets.all(24), - child: Center( - child: Text( - AppLocalizations.of(context)!.insertDomain, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 16, - ), + const SizedBox(width: 20), + TextButton( + onPressed: domainController.text != '' && domainError == null + ? () => checkHost() + : null, + child: Text( + AppLocalizations.of(context)!.check, + style: TextStyle( + color: domainController.text != '' && domainError == null + ? Theme.of(context).colorScheme.primary + : Colors.grey ), ), ), ], ), - ), - ), - Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Padding( - padding: const EdgeInsets.only( - bottom: 24, - right: 24 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close), - ), - const SizedBox(width: 20), - TextButton( - onPressed: domainController.text != '' && domainError == null - ? () => checkHost() - : null, - child: Text( - AppLocalizations.of(context)!.check, - style: TextStyle( - color: domainController.text != '' && domainError == null - ? Theme.of(context).colorScheme.primary - : Colors.grey - ), - ), - ), - ], - ), - ) - ], - ) - ], - ); - } - - if (widget.dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 400 - ), - child: content() - ), - ); - } - else { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - width: double.maxFinite, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28), - ), - color: Theme.of(context).dialogBackgroundColor - ), - child: content() - ), - ); - } + ) + ], + ) + ], + ); } } \ No newline at end of file diff --git a/lib/screens/filters/details/list_details_screen.dart b/lib/screens/filters/details/list_details_screen.dart index b5e305c..bbc7c41 100644 --- a/lib/screens/filters/details/list_details_screen.dart +++ b/lib/screens/filters/details/list_details_screen.dart @@ -25,11 +25,11 @@ class ListDetailsScreen extends StatefulWidget { final bool dialog; const ListDetailsScreen({ - Key? key, + super.key, required this.listId, required this.type, required this.dialog - }) : super(key: key); + }); @override State createState() => _ListDetailsScreenState(); @@ -367,42 +367,44 @@ class _ListDetailsScreenState extends State { title: Text(AppLocalizations.of(context)!.listDetails), actions: list != null ? actions() : null, ), - body: Stack( - children: [ - if (list != null) ListView( - children: content(), - ), - if (list == null) Center( - child: Text( - AppLocalizations.of(context)!.listNotAvailable, - style: const TextStyle( - fontSize: 24, + body: SafeArea( + child: Stack( + children: [ + if (list != null) ListView( + children: content(), + ), + if (list == null) Center( + child: Text( + AppLocalizations.of(context)!.listNotAvailable, + style: const TextStyle( + fontSize: 24, + ), ), ), - ), - if (list != null) AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: fabVisible ? - appConfigProvider.showingSnackbar - ? 70 : (Platform.isIOS ? 40 : 20) - : -70, - right: 20, - child: FloatingActionButton( - onPressed: () => updateList( - action: list!.enabled == true - ? FilteringListActions.disable - : FilteringListActions.enable, - filterList: list + if (list != null) AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: fabVisible ? + appConfigProvider.showingSnackbar + ? 70 : (Platform.isIOS ? 40 : 20) + : -70, + right: 20, + child: FloatingActionButton( + onPressed: () => updateList( + action: list!.enabled == true + ? FilteringListActions.disable + : FilteringListActions.enable, + filterList: list + ), + child: Icon( + list.enabled == true + ? Icons.gpp_bad_rounded + : Icons.verified_user_rounded, + ), ), - child: Icon( - list.enabled == true - ? Icons.gpp_bad_rounded - : Icons.verified_user_rounded, - ), - ), - ) - ], + ) + ], + ), ), ), ); diff --git a/lib/screens/filters/modals/add_custom_rule.dart b/lib/screens/filters/modals/add_custom_rule.dart index c7e5bcd..abe68bc 100644 --- a/lib/screens/filters/modals/add_custom_rule.dart +++ b/lib/screens/filters/modals/add_custom_rule.dart @@ -10,10 +10,10 @@ class AddCustomRule extends StatefulWidget { final bool fullScreen; const AddCustomRule({ - Key? key, + super.key, required this.onConfirm, required this.fullScreen - }) : super(key: key); + }); @override State createState() => _AddCustomRuleState(); @@ -349,8 +349,10 @@ class _AddCustomRuleState extends State { const SizedBox(width: 10) ], ), - body: ListView( - children: content(), + body: SafeArea( + child: ListView( + children: content(), + ), ) ), ); diff --git a/lib/screens/filters/modals/blocked_services_screen.dart b/lib/screens/filters/modals/blocked_services_screen.dart index 6169d0b..b95dd4f 100644 --- a/lib/screens/filters/modals/blocked_services_screen.dart +++ b/lib/screens/filters/modals/blocked_services_screen.dart @@ -17,9 +17,9 @@ class BlockedServicesScreen extends StatefulWidget { final bool fullScreen; const BlockedServicesScreen({ - Key? key, + super.key, required this.fullScreen - }) : super(key: key); + }); @override State createState() => _BlockedServicesScreenStateWidget(); @@ -83,105 +83,6 @@ class _BlockedServicesScreenStateWidget extends State { } } - Widget body() { - switch (filteringProvider.blockedServicesLoadStatus) { - case LoadStatus.loading: - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingBlockedServicesList, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - return ListView.builder( - itemCount: filteringProvider.blockedServices!.services.length, - itemBuilder: (context, index) => Material( - color: Colors.transparent, - child: InkWell( - onTap: () => updateValues( - values.contains(filteringProvider.blockedServices!.services[index].id), - filteringProvider.blockedServices!.services[index] - ), - child: Padding( - padding: const EdgeInsets.only( - top: 6, - bottom: 6, - right: 12, - left: 24 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - filteringProvider.blockedServices!.services[index].name, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Checkbox( - value: values.contains(filteringProvider.blockedServices!.services[index].id), - onChanged: (value) => updateValues( - value!, - filteringProvider.blockedServices!.services[index] - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5) - ), - ) - ], - ), - ), - ), - ) - ); - - case LoadStatus.error: - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.blockedServicesListNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - } - if (widget.fullScreen == true) { return Dialog.fullscreen( child: Scaffold( @@ -199,18 +100,23 @@ class _BlockedServicesScreenStateWidget extends State { const SizedBox(width: 10) ], ), - body: RefreshIndicator( - onRefresh: () async { - final result = await filteringProvider.loadBlockedServices(); - if (result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.blockedServicesListNotLoaded, - color: Colors.red - ); - } - }, - child: body() + body: SafeArea( + child: RefreshIndicator( + onRefresh: () async { + final result = await filteringProvider.loadBlockedServices(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.blockedServicesListNotLoaded, + color: Colors.red + ); + } + }, + child: _Content( + values: values, + updateValues: updateValues, + ) + ), ), ), ); @@ -256,7 +162,10 @@ class _BlockedServicesScreenStateWidget extends State { ), ), Expanded( - child: body() + child: _Content( + values: values, + updateValues: updateValues, + ) ), ], ) @@ -266,6 +175,118 @@ class _BlockedServicesScreenStateWidget extends State { } } +class _Content extends StatelessWidget { + final List values; + final void Function(bool value, BlockedService item) updateValues; + + const _Content({ + required this.values, + required this.updateValues, + }); + + @override + Widget build(BuildContext context) { + final filteringProvider = Provider.of(context); + + switch (filteringProvider.blockedServicesLoadStatus) { + case LoadStatus.loading: + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingBlockedServicesList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + return ListView.builder( + itemCount: filteringProvider.blockedServices!.services.length, + itemBuilder: (context, index) => Material( + color: Colors.transparent, + child: InkWell( + onTap: () => updateValues( + values.contains(filteringProvider.blockedServices!.services[index].id), + filteringProvider.blockedServices!.services[index] + ), + child: Padding( + padding: const EdgeInsets.only( + top: 6, + bottom: 6, + right: 12, + left: 24 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + filteringProvider.blockedServices!.services[index].name, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Checkbox( + value: values.contains(filteringProvider.blockedServices!.services[index].id), + onChanged: (value) => updateValues( + value!, + filteringProvider.blockedServices!.services[index] + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + ) + ], + ), + ), + ), + ) + ); + + case LoadStatus.error: + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.blockedServicesListNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + } +} + void openBlockedServicesModal({ required BuildContext context, required double width, diff --git a/lib/screens/filters/modals/delete_list_modal.dart b/lib/screens/filters/modals/delete_list_modal.dart index 5d751e4..86e7e88 100644 --- a/lib/screens/filters/modals/delete_list_modal.dart +++ b/lib/screens/filters/modals/delete_list_modal.dart @@ -5,9 +5,9 @@ class DeleteListModal extends StatelessWidget { final void Function() onConfirm; const DeleteListModal({ - Key? key, + super.key, required this.onConfirm - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/filters/modals/update_interval_lists_modal.dart b/lib/screens/filters/modals/update_interval_lists_modal.dart index 4827082..f6504a5 100644 --- a/lib/screens/filters/modals/update_interval_lists_modal.dart +++ b/lib/screens/filters/modals/update_interval_lists_modal.dart @@ -66,10 +66,12 @@ class _UpdateIntervalListsModalState extends State { topRight: Radius.circular(28) ), ), - child: _Content( - selectedOption: selectedOption, - onUpdateValue: _updateRadioValue, - onConfirm: () => widget.onChange(selectedOption!), + child: SafeArea( + child: _Content( + selectedOption: selectedOption, + onUpdateValue: _updateRadioValue, + onConfirm: () => widget.onChange(selectedOption!), + ), ) ), ); diff --git a/lib/screens/filters/selection/selection_lists.dart b/lib/screens/filters/selection/selection_lists.dart index 9562e74..b423f77 100644 --- a/lib/screens/filters/selection/selection_lists.dart +++ b/lib/screens/filters/selection/selection_lists.dart @@ -72,19 +72,18 @@ class SelectionSliverList extends StatelessWidget { final void Function() unselectAll; const SelectionSliverList({ - Key? key, + super.key, required this.lists, required this.selectedLists, required this.onSelect, required this.selectAll, required this.unselectAll, - }) : super(key: key); + }); @override Widget build(BuildContext context) { return SafeArea( top: false, - bottom: false, child: Builder( builder: (BuildContext context) { return CustomScrollView( diff --git a/lib/screens/home/management_modal/management_modal.dart b/lib/screens/home/management_modal/management_modal.dart index 79fe043..b18586b 100644 --- a/lib/screens/home/management_modal/management_modal.dart +++ b/lib/screens/home/management_modal/management_modal.dart @@ -19,9 +19,9 @@ class ManagementModal extends StatefulWidget { final bool dialog; const ManagementModal({ - Key? key, + super.key, required this.dialog - }) : super(key: key); + }); @override State createState() => _ManagementModalState(); @@ -141,33 +141,35 @@ class _ManagementModalState extends State with SingleTickerProv topRight: Radius.circular(28) ) ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: _Modal( - expandableController: expandableController, - updateBlocking: updateBlocking, - disableWithCountdown: disableWithCountdown, - animation: animation, - ) + child: SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: _Modal( + expandableController: expandableController, + updateBlocking: updateBlocking, + disableWithCountdown: disableWithCountdown, + animation: animation, + ) + ), ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close), - ), - ], + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close), + ), + ], + ), ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], + if (Platform.isIOS) const SizedBox(height: 16) + ], + ), ), ); } @@ -201,24 +203,24 @@ class _Modal extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Text( - AppLocalizations.of(context)!.manageServer, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface, + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.shield_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Text( + AppLocalizations.of(context)!.manageServer, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface, + ), ), ), - ), ], ), ], diff --git a/lib/screens/home/top_items/top_items_screen.dart b/lib/screens/home/top_items/top_items_screen.dart index 01ac83e..7e7e623 100644 --- a/lib/screens/home/top_items/top_items_screen.dart +++ b/lib/screens/home/top_items/top_items_screen.dart @@ -122,14 +122,16 @@ class _TopItemsScreenState extends State { const SizedBox(width: 8) ], ), - body: _Content( - buildValue: widget.buildValue, - isClient: widget.isClient, - onTapEntry: widget.onTapEntry, - options: widget.options, - screenData: screenData, - total: total, - withProgressBar: widget.withProgressBar, + body: SafeArea( + child: _Content( + buildValue: widget.buildValue, + isClient: widget.isClient, + onTapEntry: widget.onTapEntry, + options: widget.options, + screenData: screenData, + total: total, + withProgressBar: widget.withProgressBar, + ), ), ), ); diff --git a/lib/screens/logs/configuration/logs_config_modal.dart b/lib/screens/logs/configuration/logs_config_modal.dart index 6352f36..5c2ba44 100644 --- a/lib/screens/logs/configuration/logs_config_modal.dart +++ b/lib/screens/logs/configuration/logs_config_modal.dart @@ -148,36 +148,38 @@ class _LogsConfigModalState extends State { ), color: Theme.of(context).dialogBackgroundColor ), - child: Builder( - builder: (context) { - switch (loadStatus) { - case LoadStatus.loading: - return const ConfigLogsLoading(); - - case LoadStatus.loaded: - return LogsConfigOptions( - generalSwitch: generalSwitch, - updateGeneralSwitch: (v) => setState(() => generalSwitch = v), - anonymizeClientIp: anonymizeClientIp, - updateAnonymizeClientIp: (v) => setState(() => anonymizeClientIp = v), - retentionItems: retentionItems, - retentionTime: retentionTime, - updateRetentionTime: (v) => setState(() => retentionTime = v), - onClear: () => widget.onClear(), - onConfirm: () => widget.onConfirm({ - "enabled": generalSwitch, - "interval": retentionTime, - "anonymize_client_ip": anonymizeClientIp - }) - ); - - case LoadStatus.error: - return const ConfigLogsError(); - - default: - return const SizedBox(); - } - }, + child: SafeArea( + child: Builder( + builder: (context) { + switch (loadStatus) { + case LoadStatus.loading: + return const ConfigLogsLoading(); + + case LoadStatus.loaded: + return LogsConfigOptions( + generalSwitch: generalSwitch, + updateGeneralSwitch: (v) => setState(() => generalSwitch = v), + anonymizeClientIp: anonymizeClientIp, + updateAnonymizeClientIp: (v) => setState(() => anonymizeClientIp = v), + retentionItems: retentionItems, + retentionTime: retentionTime, + updateRetentionTime: (v) => setState(() => retentionTime = v), + onClear: () => widget.onClear(), + onConfirm: () => widget.onConfirm({ + "enabled": generalSwitch, + "interval": retentionTime, + "anonymize_client_ip": anonymizeClientIp + }) + ); + + case LoadStatus.error: + return const ConfigLogsError(); + + default: + return const SizedBox(); + } + }, + ), ) ); } diff --git a/lib/screens/logs/details/log_details_screen.dart b/lib/screens/logs/details/log_details_screen.dart index ff88eaa..42918dd 100644 --- a/lib/screens/logs/details/log_details_screen.dart +++ b/lib/screens/logs/details/log_details_screen.dart @@ -25,10 +25,10 @@ class LogDetailsScreen extends StatelessWidget { final bool dialog; const LogDetailsScreen({ - Key? key, + super.key, required this.log, required this.dialog - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -322,7 +322,6 @@ class LogDetailsScreen extends StatelessWidget { ], body: SafeArea( top: false, - bottom: false, child: Builder( builder: (context) => CustomScrollView( slivers: [ diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index 1730d8e..84728f8 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -60,9 +60,11 @@ class _ClientsModalState extends State { ), color: Theme.of(context).dialogBackgroundColor ), - child: _ModalContent( - selectedClients: selectedClients, - onClientsSelected: (v) => setState(() => selectedClients = v), + child: SafeArea( + child: _ModalContent( + selectedClients: selectedClients, + onClientsSelected: (v) => setState(() => selectedClients = v), + ), ) ), ); diff --git a/lib/screens/logs/filters/filter_status_modal.dart b/lib/screens/logs/filters/filter_status_modal.dart index d3c1079..88f782b 100644 --- a/lib/screens/logs/filters/filter_status_modal.dart +++ b/lib/screens/logs/filters/filter_status_modal.dart @@ -62,10 +62,12 @@ class _FilterStatusModalState extends State { ), color: Theme.of(context).dialogBackgroundColor ), - child: _Content( - onApply: apply, - updateSelectedResultStatus: (v) => setState(() => selectedResultStatus = v), - selectedResultStatus: selectedResultStatus, + child: SafeArea( + child: _Content( + onApply: apply, + updateSelectedResultStatus: (v) => setState(() => selectedResultStatus = v), + selectedResultStatus: selectedResultStatus, + ), ) ); } diff --git a/lib/screens/logs/filters/logs_filters_modal.dart b/lib/screens/logs/filters/logs_filters_modal.dart index 8e1cdbe..5e7e746 100644 --- a/lib/screens/logs/filters/logs_filters_modal.dart +++ b/lib/screens/logs/filters/logs_filters_modal.dart @@ -19,9 +19,9 @@ class LogsFiltersModal extends StatefulWidget { final bool dialog; const LogsFiltersModal({ - Key? key, + super.key, required this.dialog - }) : super(key: key); + }); @override State createState() => _LogsFiltersModalState(); @@ -65,9 +65,11 @@ class _LogsFiltersModalState extends State { topRight: Radius.circular(28) ) ), - child: _FiltersList( - searchController: searchController, - onClearSearch: () => setState(() => searchController.text = "") + child: SafeArea( + child: _FiltersList( + searchController: searchController, + onClearSearch: () => setState(() => searchController.text = "") + ), ) ), ); diff --git a/lib/screens/servers/servers.dart b/lib/screens/servers/servers.dart index 180af77..25bca06 100644 --- a/lib/screens/servers/servers.dart +++ b/lib/screens/servers/servers.dart @@ -16,9 +16,9 @@ class Servers extends StatefulWidget { final double? breakingWidth; const Servers({ - Key? key, + super.key, this.breakingWidth - }) : super(key: key); + }); @override State createState() => _ServersState(); @@ -77,29 +77,31 @@ class _ServersState extends State { title: Text(AppLocalizations.of(context)!.servers), centerTitle: false, ), - body: Stack( - children: [ - ServersList( - context: context, - controllers: expandableControllerList, - onChange: expandOrContract, - scrollController: scrollController, - breakingWidth: widget.breakingWidth ?? 700, - ), - AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: isVisible ? - appConfigProvider.showingSnackbar - ? 70 : (Platform.isIOS ? 40 : 20) - : -70, - right: 20, - child: FloatingActionButton( - onPressed: openAddServerModal, - child: const Icon(Icons.add), + body: SafeArea( + child: Stack( + children: [ + ServersList( + context: context, + controllers: expandableControllerList, + onChange: expandOrContract, + scrollController: scrollController, + breakingWidth: widget.breakingWidth ?? 700, ), - ), - ], + AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: isVisible ? + appConfigProvider.showingSnackbar + ? 70 : (Platform.isIOS ? 40 : 20) + : -70, + right: 20, + child: FloatingActionButton( + onPressed: openAddServerModal, + child: const Icon(Icons.add), + ), + ), + ], + ), ), ); } diff --git a/lib/screens/settings/access_settings/add_client_modal.dart b/lib/screens/settings/access_settings/add_client_modal.dart index 014babd..bb0385a 100644 --- a/lib/screens/settings/access_settings/add_client_modal.dart +++ b/lib/screens/settings/access_settings/add_client_modal.dart @@ -44,9 +44,11 @@ class AddClientModal extends StatelessWidget { topRight: Radius.circular(28) ) ), - child: _Content( - type: type, - onConfirm: onConfirm, + child: SafeArea( + child: _Content( + type: type, + onConfirm: onConfirm, + ), ) ), ); diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 39a93e3..9483cd8 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -11,7 +11,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class AdvancedSettings extends StatelessWidget { - const AdvancedSettings({Key? key}) : super(key: key); + const AdvancedSettings({super.key}); @override Widget build(BuildContext context) { @@ -46,31 +46,33 @@ class AdvancedSettings extends StatelessWidget { title: Text(AppLocalizations.of(context)!.advancedSettings), surfaceTintColor: isDesktop(width) ? Colors.transparent : null, ), - body: ListView( - children: [ - CustomListTile( - icon: Icons.lock, - title: AppLocalizations.of(context)!.dontCheckCertificate, - subtitle: AppLocalizations.of(context)!.dontCheckCertificateDescription, - trailing: Switch( - value: appConfigProvider.overrideSslCheck, - onChanged: (value) => updateSettings( - newStatus: value, + body: SafeArea( + child: ListView( + children: [ + CustomListTile( + icon: Icons.lock, + title: AppLocalizations.of(context)!.dontCheckCertificate, + subtitle: AppLocalizations.of(context)!.dontCheckCertificateDescription, + trailing: Switch( + value: appConfigProvider.overrideSslCheck, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setOverrideSslCheck + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.overrideSslCheck, function: appConfigProvider.setOverrideSslCheck ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 20, + right: 10 + ) ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.overrideSslCheck, - function: appConfigProvider.setOverrideSslCheck - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 20, - right: 10 - ) - ), - ], + ], + ), ) ); } diff --git a/lib/screens/settings/customization/customization.dart b/lib/screens/settings/customization/customization.dart index 6ddd5e4..fb4526b 100644 --- a/lib/screens/settings/customization/customization.dart +++ b/lib/screens/settings/customization/customization.dart @@ -14,7 +14,7 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/colors.dart'; class Customization extends StatelessWidget { - const Customization({Key? key}) : super(key: key); + const Customization({super.key}); @override Widget build(BuildContext context) { @@ -65,152 +65,154 @@ class _CustomizationWidgetState extends State { centerTitle: false, surfaceTintColor: isDesktop(width) ? Colors.transparent : null, ), - body: ListView( - children: [ - SectionLabel( - label: AppLocalizations.of(context)!.theme, - padding: const EdgeInsets.only(top: 10, left: 16, right: 16, bottom: 5), - ), - Column( - children: [ - CustomSwitchListTile( - value: selectedTheme == 0 ? true : false, - onChanged: (value) { - selectedTheme = value == true ? 0 : 1; - appConfigProvider.setSelectedTheme(value == true ? 0 : 1); - }, - title: AppLocalizations.of(context)!.systemDefined, - ), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ThemeModeButton( - icon: Icons.light_mode, - value: 1, - selected: selectedTheme, - label: AppLocalizations.of(context)!.light, - onChanged: (value) { - selectedTheme = value; - appConfigProvider.setSelectedTheme(value); - }, - disabled: selectedTheme == 0 ? true : false, - ), - ThemeModeButton( - icon: Icons.dark_mode, - value: 2, - selected: selectedTheme, - label: AppLocalizations.of(context)!.dark, - onChanged: (value) { - selectedTheme = value; - appConfigProvider.setSelectedTheme(value); - }, - disabled: selectedTheme == 0 ? true : false, - ), - ], - ), - ], - ), - SectionLabel( - label: AppLocalizations.of(context)!.color, - padding: const EdgeInsets.only(top: 45, left: 16, right: 16, bottom: 5), - ), - if (appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31) CustomSwitchListTile( - value: dynamicColor, - onChanged: (value) { - setState(() => dynamicColor = value); - appConfigProvider.setUseDynamicColor(value); - }, - title: AppLocalizations.of(context)!.useDynamicTheme, - ), - if (!(appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31)) const SizedBox(height: 20), - if (dynamicColor == false) ...[ - SizedBox( - width: MediaQuery.of(context).size.width, - height: 70, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: colors.length, - itemBuilder: (context, index) { - if (index == 0) { - return Row( - children: [ - const SizedBox(width: 15), - ColorItem( - color: colors[index], - numericValue: index, - selectedValue: selectedColor, - onChanged: (value) { - setState(() => selectedColor = value); - appConfigProvider.setStaticColor(value); - } - ), - Container( - margin: const EdgeInsets.symmetric(horizontal: 10), - width: 1, - height: 60, - decoration: BoxDecoration( - color: Colors.grey, - borderRadius: BorderRadius.circular(1) - ), - ) - ], - ); - } - else if (index == colors.length-1) { - return Row( - children: [ - ColorItem( - color: colors[index], - numericValue: index, - selectedValue: selectedColor, - onChanged: (value) { - setState(() => selectedColor = value); - appConfigProvider.setStaticColor(value); - } - ), - const SizedBox(width: 15) - ], - ); - } - else { - return ColorItem( - color: colors[index], - numericValue: index, - selectedValue: selectedColor, - onChanged: (value) { - setState(() => selectedColor = value); - appConfigProvider.setStaticColor(value); - } - ); - } - }, - ), + body: SafeArea( + child: ListView( + children: [ + SectionLabel( + label: AppLocalizations.of(context)!.theme, + padding: const EdgeInsets.only(top: 10, left: 16, right: 16, bottom: 5), ), - Padding( - padding: const EdgeInsets.only( - left: 25, - top: 10 - ), - child: Text( - colorTranslation(context, selectedColor), - style: TextStyle( - color: Theme.of(context).listTileTheme.iconColor, - fontSize: 16 + Column( + children: [ + CustomSwitchListTile( + value: selectedTheme == 0 ? true : false, + onChanged: (value) { + selectedTheme = value == true ? 0 : 1; + appConfigProvider.setSelectedTheme(value == true ? 0 : 1); + }, + title: AppLocalizations.of(context)!.systemDefined, + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ThemeModeButton( + icon: Icons.light_mode, + value: 1, + selected: selectedTheme, + label: AppLocalizations.of(context)!.light, + onChanged: (value) { + selectedTheme = value; + appConfigProvider.setSelectedTheme(value); + }, + disabled: selectedTheme == 0 ? true : false, + ), + ThemeModeButton( + icon: Icons.dark_mode, + value: 2, + selected: selectedTheme, + label: AppLocalizations.of(context)!.dark, + onChanged: (value) { + selectedTheme = value; + appConfigProvider.setSelectedTheme(value); + }, + disabled: selectedTheme == 0 ? true : false, + ), + ], + ), + ], + ), + SectionLabel( + label: AppLocalizations.of(context)!.color, + padding: const EdgeInsets.only(top: 45, left: 16, right: 16, bottom: 5), + ), + if (appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31) CustomSwitchListTile( + value: dynamicColor, + onChanged: (value) { + setState(() => dynamicColor = value); + appConfigProvider.setUseDynamicColor(value); + }, + title: AppLocalizations.of(context)!.useDynamicTheme, + ), + if (!(appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31)) const SizedBox(height: 20), + if (dynamicColor == false) ...[ + SizedBox( + width: MediaQuery.of(context).size.width, + height: 70, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: colors.length, + itemBuilder: (context, index) { + if (index == 0) { + return Row( + children: [ + const SizedBox(width: 15), + ColorItem( + color: colors[index], + numericValue: index, + selectedValue: selectedColor, + onChanged: (value) { + setState(() => selectedColor = value); + appConfigProvider.setStaticColor(value); + } + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 10), + width: 1, + height: 60, + decoration: BoxDecoration( + color: Colors.grey, + borderRadius: BorderRadius.circular(1) + ), + ) + ], + ); + } + else if (index == colors.length-1) { + return Row( + children: [ + ColorItem( + color: colors[index], + numericValue: index, + selectedValue: selectedColor, + onChanged: (value) { + setState(() => selectedColor = value); + appConfigProvider.setStaticColor(value); + } + ), + const SizedBox(width: 15) + ], + ); + } + else { + return ColorItem( + color: colors[index], + numericValue: index, + selectedValue: selectedColor, + onChanged: (value) { + setState(() => selectedColor = value); + appConfigProvider.setStaticColor(value); + } + ); + } + }, ), ), + Padding( + padding: const EdgeInsets.only( + left: 25, + top: 10 + ), + child: Text( + colorTranslation(context, selectedColor), + style: TextStyle( + color: Theme.of(context).listTileTheme.iconColor, + fontSize: 16 + ), + ), + ) + ], + CustomSwitchListTile( + value: useThemeColorInsteadGreenRed, + onChanged: (value) { + setState(() => useThemeColorInsteadGreenRed = value); + appConfigProvider.setUseThemeColorForStatus(value); + }, + title: AppLocalizations.of(context)!.useThemeColorStatus, + subtitle: AppLocalizations.of(context)!.useThemeColorStatusDescription, ) ], - CustomSwitchListTile( - value: useThemeColorInsteadGreenRed, - onChanged: (value) { - setState(() => useThemeColorInsteadGreenRed = value); - appConfigProvider.setUseThemeColorForStatus(value); - }, - title: AppLocalizations.of(context)!.useThemeColorStatus, - subtitle: AppLocalizations.of(context)!.useThemeColorStatusDescription, - ) - ], + ), ), ); } diff --git a/lib/screens/settings/dhcp/add_static_lease_modal.dart b/lib/screens/settings/dhcp/add_static_lease_modal.dart index fd222d3..c80e848 100644 --- a/lib/screens/settings/dhcp/add_static_lease_modal.dart +++ b/lib/screens/settings/dhcp/add_static_lease_modal.dart @@ -3,7 +3,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; -class AddStaticLeaseModal extends StatefulWidget { +class AddStaticLeaseModal extends StatelessWidget { final void Function(Lease) onConfirm; final bool dialog; @@ -14,10 +14,49 @@ class AddStaticLeaseModal extends StatefulWidget { }); @override - State createState() => _AddStaticLeaseModalState(); + Widget build(BuildContext context) { + if (dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400 + ), + child: _Content(onConfirm: onConfirm) + ), + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).dialogBackgroundColor, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28) + ) + ), + child: SafeArea( + child: _Content(onConfirm: onConfirm) + ) + ), + ); + } + } } -class _AddStaticLeaseModalState extends State { +class _Content extends StatefulWidget { + final void Function(Lease) onConfirm; + + const _Content({ + required this.onConfirm + }); + + @override + State<_Content> createState() => __ContentState(); +} + +class __ContentState extends State<_Content> { final TextEditingController macController = TextEditingController(); String? macError; final TextEditingController ipController = TextEditingController(); @@ -67,175 +106,147 @@ class _AddStaticLeaseModalState extends State { @override Widget build(BuildContext context) { - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Flexible( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.add, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.addStaticLease, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only( - left: 24, right: 24, bottom: 12 - ), - child: TextFormField( - controller: macController, - onChanged: validateMac, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.smartphone_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: macError, - labelText: AppLocalizations.of(context)!.macAddress, - ), - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - child: TextFormField( - controller: ipController, - onChanged: validateIp, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: ipError, - labelText: AppLocalizations.of(context)!.ipAddress, - ), - ), - ), - Padding( - padding: const EdgeInsets.only( - left: 24, right: 24, top: 12 - ), - child: TextFormField( - controller: hostNameController, - onChanged: (value) { - if (value != '') { - setState(() => hostNameError = null); - } - else { - setState(() => hostNameError = AppLocalizations.of(context)!.hostNameError); - } - validateData(); - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.badge_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: hostNameError, - labelText: AppLocalizations.of(context)!.hostName, - ), - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel), + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.add, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.addStaticLease, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ), + ], + ), ), - const SizedBox(width: 20), - TextButton( - onPressed: validData == true - ? () { - Navigator.pop(context); - widget.onConfirm( - Lease( - mac: macController.text, - hostname: hostNameController.text, - ip: ipController.text + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, bottom: 12 + ), + child: TextFormField( + controller: macController, + onChanged: validateMac, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.smartphone_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) ) - ); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: validData == true - ? Theme.of(context).colorScheme.primary - : Colors.grey + ), + errorText: macError, + labelText: AppLocalizations.of(context)!.macAddress, + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + child: TextFormField( + controller: ipController, + onChanged: validateIp, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipError, + labelText: AppLocalizations.of(context)!.ipAddress, + ), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 24, right: 24, top: 12 + ), + child: TextFormField( + controller: hostNameController, + onChanged: (value) { + if (value != '') { + setState(() => hostNameError = null); + } + else { + setState(() => hostNameError = AppLocalizations.of(context)!.hostNameError); + } + validateData(); + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.badge_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: hostNameError, + labelText: AppLocalizations.of(context)!.hostName, ), ), ), ], ), - ) - ], - ); - } - - if (widget.dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 400 ), - child: content(), ), - ); - } - else { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ) + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel), + ), + const SizedBox(width: 20), + TextButton( + onPressed: validData == true + ? () { + Navigator.pop(context); + widget.onConfirm( + Lease( + mac: macController.text, + hostname: hostNameController.text, + ip: ipController.text + ) + ); + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, + style: TextStyle( + color: validData == true + ? Theme.of(context).colorScheme.primary + : Colors.grey + ), + ), + ), + ], ), - child: content() - ), - ); - } + ) + ], + ); } } \ No newline at end of file diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index fff464e..75d1856 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -411,328 +411,330 @@ class _DhcpScreenState extends State { const SizedBox(width: 10) ] : null, ), - body: Builder( - builder: (context) { - switch (dhcpProvider.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingDhcp, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - if (selectedInterface != null) { - return SingleChildScrollView( - child: Wrap( + body: SafeArea( + child: Builder( + builder: (context) { + switch (dhcpProvider.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - DhcpMainButton( - selectedInterface: selectedInterface, - enabled: enabled, - setEnabled: (v) => setState(() => enabled = v) - ), - if (selectedInterface!.ipv4Addresses.isNotEmpty) ...[ - SectionLabel( - label: AppLocalizations.of(context)!.ipv4settings, - padding: const EdgeInsets.only( - top: 24, left: 16, right: 16, bottom: 8 - ) + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingDhcp, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - _DhcpField( - icon: Icons.skip_previous_rounded, - label: AppLocalizations.of(context)!.startOfRange, - controller: ipv4StartRangeController, - onChanged: (value) => validateIpV4(value, 'ipv4StartRangeError', AppLocalizations.of(context)!.ipNotValid), - error: ipv4StartRangeError - ), - _DhcpField( - icon: Icons.skip_next_rounded, - label: AppLocalizations.of(context)!.endOfRange, - controller: ipv4EndRangeController, - onChanged: (value) => validateIpV4(value, 'ipv4EndRangeError', AppLocalizations.of(context)!.ipNotValid), - error: ipv4EndRangeError - ), - _DhcpField( - icon: Icons.hub_rounded, - label: AppLocalizations.of(context)!.subnetMask, - controller: ipv4SubnetMaskController, - onChanged: (value) => validateIpV4(value, 'ipv4SubnetMaskError', AppLocalizations.of(context)!.subnetMaskNotValid), - error: ipv4SubnetMaskError - ), - _DhcpField( - icon: Icons.router_rounded, - label: AppLocalizations.of(context)!.gateway, - controller: ipv4GatewayController, - onChanged: (value) => validateIpV4(value, 'ipv4GatewayError', AppLocalizations.of(context)!.gatewayNotValid), - error: ipv4GatewayError - ), - _DhcpField( - icon: Icons.timer, - label: AppLocalizations.of(context)!.leaseTime, - controller: ipv4LeaseTimeController, - onChanged: (value) { - if (int.tryParse(value).runtimeType == int) { - setState(() => ipv4LeaseTimeError = null); - } - else { - setState(() => ipv4LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); - } - }, - error: ipv4LeaseTimeError - ), - ], - if (selectedInterface!.ipv6Addresses.isNotEmpty) ...[ - SectionLabel( - label: AppLocalizations.of(context)!.ipv6settings, - padding: const EdgeInsets.all(16) - ), - _DhcpField( - icon: Icons.skip_next_rounded, - label: AppLocalizations.of(context)!.startOfRange, - controller: ipv6StartRangeController, - onChanged: (value) => validateIpV6(value, 'ipv6StartRangeError', AppLocalizations.of(context)!.ipNotValid), - error: ipv6StartRangeError - ), - _DhcpField( - icon: Icons.skip_previous_rounded, - label: AppLocalizations.of(context)!.endOfRange, - controller: ipv6EndRangeController, - onChanged: (value) => validateIpV6(value, 'ipv6EndRangeError', AppLocalizations.of(context)!.ipNotValid), - error: ipv6EndRangeError - ), - _DhcpField( - icon: Icons.timer, - label: AppLocalizations.of(context)!.leaseTime, - controller: ipv6LeaseTimeController, - onChanged: (value) { - if (int.tryParse(value).runtimeType == int) { - setState(() => ipv6LeaseTimeError = null); - } - else { - setState(() => ipv6LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); - } - }, - error: ipv6LeaseTimeError - ) - ], - const SizedBox(height: 20), - SectionLabel( - label: AppLocalizations.of(context)!.dhcpLeases, - padding: const EdgeInsets.all(16), - ), - if (width <= 900) Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus!.leases, - staticLeases: false, - ) - ) - ); - }, - child: Container( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.dhcpLeases, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - Icon( - Icons.arrow_forward_rounded, - color: Theme.of(context).colorScheme.onSurface, - ) - ], - ), - ), - ), - ), - if (width <= 900) Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, - staticLeases: true, - ) - ) - ); - }, - child: Container( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.dhcpStatic, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - Icon( - Icons.arrow_forward_rounded, - color: Theme.of(context).colorScheme.onSurface, - ) - ], - ), - ), - ), - ), - if (width > 900) Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ElevatedButton( - onPressed: () { - if (!(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push( - DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus!.leases, - staticLeases: false, - ) - ); - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus!.leases, - staticLeases: false, - ) - ) - ); - } - }, - child: Row( - children: [ - Text(AppLocalizations.of(context)!.dhcpLeases), - const SizedBox(width: 8), - const Icon(Icons.arrow_forward_rounded) - ], - ) - ), - ElevatedButton( - onPressed: () { - if (!(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push( - DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, - staticLeases: true, - ) - ); - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => DhcpLeases( - items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, - staticLeases: true, - ) - ) - ); - } - }, - child: Row( - children: [ - Text(AppLocalizations.of(context)!.dhcpStatic), - const SizedBox(width: 8), - const Icon(Icons.arrow_forward_rounded) - ], - ) - ), - ], - ), - const SizedBox(height: 10) + ) ], ), ); - } - else { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Flexible( - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.neededSelectInterface, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5) + + case LoadStatus.loaded: + if (selectedInterface != null) { + return SingleChildScrollView( + child: Wrap( + children: [ + DhcpMainButton( + selectedInterface: selectedInterface, + enabled: enabled, + setEnabled: (v) => setState(() => enabled = v) + ), + if (selectedInterface!.ipv4Addresses.isNotEmpty) ...[ + SectionLabel( + label: AppLocalizations.of(context)!.ipv4settings, + padding: const EdgeInsets.only( + top: 24, left: 16, right: 16, bottom: 8 + ) + ), + _DhcpField( + icon: Icons.skip_previous_rounded, + label: AppLocalizations.of(context)!.startOfRange, + controller: ipv4StartRangeController, + onChanged: (value) => validateIpV4(value, 'ipv4StartRangeError', AppLocalizations.of(context)!.ipNotValid), + error: ipv4StartRangeError + ), + _DhcpField( + icon: Icons.skip_next_rounded, + label: AppLocalizations.of(context)!.endOfRange, + controller: ipv4EndRangeController, + onChanged: (value) => validateIpV4(value, 'ipv4EndRangeError', AppLocalizations.of(context)!.ipNotValid), + error: ipv4EndRangeError + ), + _DhcpField( + icon: Icons.hub_rounded, + label: AppLocalizations.of(context)!.subnetMask, + controller: ipv4SubnetMaskController, + onChanged: (value) => validateIpV4(value, 'ipv4SubnetMaskError', AppLocalizations.of(context)!.subnetMaskNotValid), + error: ipv4SubnetMaskError + ), + _DhcpField( + icon: Icons.router_rounded, + label: AppLocalizations.of(context)!.gateway, + controller: ipv4GatewayController, + onChanged: (value) => validateIpV4(value, 'ipv4GatewayError', AppLocalizations.of(context)!.gatewayNotValid), + error: ipv4GatewayError + ), + _DhcpField( + icon: Icons.timer, + label: AppLocalizations.of(context)!.leaseTime, + controller: ipv4LeaseTimeController, + onChanged: (value) { + if (int.tryParse(value).runtimeType == int) { + setState(() => ipv4LeaseTimeError = null); + } + else { + setState(() => ipv4LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); + } + }, + error: ipv4LeaseTimeError + ), + ], + if (selectedInterface!.ipv6Addresses.isNotEmpty) ...[ + SectionLabel( + label: AppLocalizations.of(context)!.ipv6settings, + padding: const EdgeInsets.all(16) + ), + _DhcpField( + icon: Icons.skip_next_rounded, + label: AppLocalizations.of(context)!.startOfRange, + controller: ipv6StartRangeController, + onChanged: (value) => validateIpV6(value, 'ipv6StartRangeError', AppLocalizations.of(context)!.ipNotValid), + error: ipv6StartRangeError + ), + _DhcpField( + icon: Icons.skip_previous_rounded, + label: AppLocalizations.of(context)!.endOfRange, + controller: ipv6EndRangeController, + onChanged: (value) => validateIpV6(value, 'ipv6EndRangeError', AppLocalizations.of(context)!.ipNotValid), + error: ipv6EndRangeError + ), + _DhcpField( + icon: Icons.timer, + label: AppLocalizations.of(context)!.leaseTime, + controller: ipv6LeaseTimeController, + onChanged: (value) { + if (int.tryParse(value).runtimeType == int) { + setState(() => ipv6LeaseTimeError = null); + } + else { + setState(() => ipv6LeaseTimeError = AppLocalizations.of(context)!.leaseTimeNotValid); + } + }, + error: ipv6LeaseTimeError + ) + ], + const SizedBox(height: 20), + SectionLabel( + label: AppLocalizations.of(context)!.dhcpLeases, + padding: const EdgeInsets.all(16), + ), + if (width <= 900) Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus!.leases, + staticLeases: false, + ) + ) + ); + }, + child: Container( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.dhcpLeases, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + Icon( + Icons.arrow_forward_rounded, + color: Theme.of(context).colorScheme.onSurface, + ) + ], ), ), ), - const SizedBox(height: 30), - ElevatedButton( - onPressed: selectInterface, - child: Text(AppLocalizations.of(context)!.selectInterface) + ), + if (width <= 900) Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, + staticLeases: true, + ) + ) + ); + }, + child: Container( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.dhcpStatic, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + Icon( + Icons.arrow_forward_rounded, + color: Theme.of(context).colorScheme.onSurface, + ) + ], + ), + ), ), - ], - ), + ), + if (width > 900) Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () { + if (!(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push( + DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus!.leases, + staticLeases: false, + ) + ); + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus!.leases, + staticLeases: false, + ) + ) + ); + } + }, + child: Row( + children: [ + Text(AppLocalizations.of(context)!.dhcpLeases), + const SizedBox(width: 8), + const Icon(Icons.arrow_forward_rounded) + ], + ) + ), + ElevatedButton( + onPressed: () { + if (!(Platform.isAndroid || Platform.isIOS)) { + SplitView.of(context).push( + DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, + staticLeases: true, + ) + ); + } + else { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => DhcpLeases( + items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, + staticLeases: true, + ) + ) + ); + } + }, + child: Row( + children: [ + Text(AppLocalizations.of(context)!.dhcpStatic), + const SizedBox(width: 8), + const Icon(Icons.arrow_forward_rounded) + ], + ) + ), + ], + ), + const SizedBox(height: 10) + ], ), - ], + ); + } + else { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.neededSelectInterface, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5) + ), + ), + ), + const SizedBox(height: 30), + ElevatedButton( + onPressed: selectInterface, + child: Text(AppLocalizations.of(context)!.selectInterface) + ), + ], + ), + ), + ], + ); + } + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.dhcpSettingsNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), ); - } - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.dhcpSettingsNotLoaded, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - }, + + default: + return const SizedBox(); + } + }, + ), ) ); } diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index 91bd1cf..9bb1fe3 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -22,10 +22,10 @@ class DhcpLeases extends StatelessWidget { final bool staticLeases; const DhcpLeases({ - Key? key, + super.key, required this.items, required this.staticLeases, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -130,32 +130,34 @@ class DhcpLeases extends StatelessWidget { ), ), body: items.isNotEmpty - ? ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: items.length, - itemBuilder: (context, index) => ListTile( - isThreeLine: true, - title: Text(items[index].ip), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(items[index].mac), - Text(items[index].hostname), - ], + ? SafeArea( + child: ListView.builder( + padding: const EdgeInsets.only(top: 0), + itemCount: items.length, + itemBuilder: (context, index) => ListTile( + isThreeLine: true, + title: Text(items[index].ip), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(items[index].mac), + Text(items[index].hostname), + ], + ), + trailing: staticLeases == true + ? IconButton( + onPressed: () { + showModal( + context: context, + builder: (context) => DeleteStaticLeaseModal( + onConfirm: () => deleteLease(items[index]) + ) + ); + }, + icon: const Icon(Icons.delete) + ) + : null, ), - trailing: staticLeases == true - ? IconButton( - onPressed: () { - showModal( - context: context, - builder: (context) => DeleteStaticLeaseModal( - onConfirm: () => deleteLease(items[index]) - ) - ); - }, - icon: const Icon(Icons.delete) - ) - : null, ), ) : Center( diff --git a/lib/screens/settings/dhcp/select_interface_modal.dart b/lib/screens/settings/dhcp/select_interface_modal.dart index e2dc26d..a9c9c67 100644 --- a/lib/screens/settings/dhcp/select_interface_modal.dart +++ b/lib/screens/settings/dhcp/select_interface_modal.dart @@ -137,16 +137,17 @@ class SelectInterfaceModal extends StatelessWidget { ), ), Expanded( - child: ListView.builder( - controller: controller, - itemCount: interfaces.length, - itemBuilder: (context, index) => DhcpInterfaceItem( - networkInterface: interfaces[index], - onSelect: onSelect - ) + child: SafeArea( + child: ListView.builder( + controller: controller, + itemCount: interfaces.length, + itemBuilder: (context, index) => DhcpInterfaceItem( + networkInterface: interfaces[index], + onSelect: onSelect + ) + ), ) ), - const SizedBox(height: 16) ], ), ); diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index 2ae3f4f..c970f34 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -117,105 +117,107 @@ class _BootstrapDnsScreenState extends State { const SizedBox(width: 10) ], ), - body: ListView( - padding: const EdgeInsets.only(top: 10), - children: [ - Card( - margin: const EdgeInsets.only( - left: 16, right: 16, bottom: 20 - ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Row( - children: [ - Icon( - Icons.info_rounded, - color: Theme.of(context).listTileTheme.iconColor, - ), - const SizedBox(width: 20), - Flexible( - child: Text( - AppLocalizations.of(context)!.bootstrapDnsServersInfo, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), + body: SafeArea( + child: ListView( + padding: const EdgeInsets.only(top: 10), + children: [ + Card( + margin: const EdgeInsets.only( + left: 16, right: 16, bottom: 20 + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).listTileTheme.iconColor, + ), + const SizedBox(width: 20), + Flexible( + child: Text( + AppLocalizations.of(context)!.bootstrapDnsServersInfo, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) ) - ) - ], + ], + ), ), ), - ), - const SizedBox(height: 10), - if (bootstrapControllers.isEmpty) Column( - children: [ - Padding( - padding: const EdgeInsets.all(10), - child: Center( - child: Text( - AppLocalizations.of(context)!.noBootstrapDns, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant, - fontSize: 16 + const SizedBox(height: 10), + if (bootstrapControllers.isEmpty) Column( + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: Center( + child: Text( + AppLocalizations.of(context)!.noBootstrapDns, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontSize: 16 + ), ), ), ), - ), - const SizedBox(height: 20), - ], - ), - ...bootstrapControllers.map((c) => Padding( - padding: const EdgeInsets.only( - left: 16, right: 6, bottom: 20 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: TextFormField( - controller: c['controller'], - onChanged: (value) => validateIp(c, value), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.dns_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: c['error'], - labelText: AppLocalizations.of(context)!.dnsServer, - ) - ), - ), - const SizedBox(width: 8), - IconButton( - onPressed: () { - setState(() => bootstrapControllers = bootstrapControllers.where((con) => con != c).toList()); - checkValidValues(); - }, - icon: const Icon(Icons.remove_circle_outline) - ) + const SizedBox(height: 20), ], ), - )).toList(), - Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - ElevatedButton.icon( - onPressed: () { - setState(() => bootstrapControllers.add({ - 'controller': TextEditingController(), - 'error': null - })); - checkValidValues(); - }, - icon: const Icon(Icons.add), - label: Text(AppLocalizations.of(context)!.addItem) + ...bootstrapControllers.map((c) => Padding( + padding: const EdgeInsets.only( + left: 16, right: 6, bottom: 20 ), - ], - ), - const SizedBox(height: 20) - ], + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextFormField( + controller: c['controller'], + onChanged: (value) => validateIp(c, value), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.dns_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: c['error'], + labelText: AppLocalizations.of(context)!.dnsServer, + ) + ), + ), + const SizedBox(width: 8), + IconButton( + onPressed: () { + setState(() => bootstrapControllers = bootstrapControllers.where((con) => con != c).toList()); + checkValidValues(); + }, + icon: const Icon(Icons.remove_circle_outline) + ) + ], + ), + )).toList(), + Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton.icon( + onPressed: () { + setState(() => bootstrapControllers.add({ + 'controller': TextEditingController(), + 'error': null + })); + checkValidValues(); + }, + icon: const Icon(Icons.add), + label: Text(AppLocalizations.of(context)!.addItem) + ), + ], + ), + const SizedBox(height: 20) + ], + ), ), ); } diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index 7f6f63a..40a99f8 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -169,81 +169,83 @@ class _CacheConfigDnsScreenState extends State { const SizedBox(width: 10) ], ), - body: ListView( - padding: const EdgeInsets.only(top: 10), - children: [ - numericField( - controller: cacheSizeController, - label: AppLocalizations.of(context)!.cacheSize, - helper: AppLocalizations.of(context)!.inBytes, - error: cacheSizeError, - onChanged: (value) { - if (int.tryParse(value) != null) { - setState(() => cacheSizeError = null); + body: SafeArea( + child: ListView( + padding: const EdgeInsets.only(top: 10), + children: [ + numericField( + controller: cacheSizeController, + label: AppLocalizations.of(context)!.cacheSize, + helper: AppLocalizations.of(context)!.inBytes, + error: cacheSizeError, + onChanged: (value) { + if (int.tryParse(value) != null) { + setState(() => cacheSizeError = null); + } + else { + setState(() => cacheSizeError = AppLocalizations.of(context)!.valueNotNumber); + } + checkValidData(); } - else { - setState(() => cacheSizeError = AppLocalizations.of(context)!.valueNotNumber); + ), + const SizedBox(height: 30), + numericField( + controller: overrideMinTtlController, + label: AppLocalizations.of(context)!.overrideMinimumTtl, + helper: AppLocalizations.of(context)!.overrideMinimumTtlDescription, + error: overrideMinTtlError, + onChanged: (value) { + if (int.tryParse(value) != null) { + setState(() => overrideMinTtlError = null); + } + else { + setState(() => overrideMinTtlError = AppLocalizations.of(context)!.valueNotNumber); + } + checkValidData(); } - checkValidData(); - } - ), - const SizedBox(height: 30), - numericField( - controller: overrideMinTtlController, - label: AppLocalizations.of(context)!.overrideMinimumTtl, - helper: AppLocalizations.of(context)!.overrideMinimumTtlDescription, - error: overrideMinTtlError, - onChanged: (value) { - if (int.tryParse(value) != null) { - setState(() => overrideMinTtlError = null); + ), + const SizedBox(height: 30), + numericField( + controller: overrideMaxTtlController, + label: AppLocalizations.of(context)!.overrideMaximumTtl, + helper: AppLocalizations.of(context)!.overrideMaximumTtlDescription, + error: overrideMaxTtlError, + onChanged: (value) { + if (int.tryParse(value) != null) { + setState(() => overrideMaxTtlError = null); + } + else { + setState(() => overrideMaxTtlError = AppLocalizations.of(context)!.valueNotNumber); + } + checkValidData(); } - else { - setState(() => overrideMinTtlError = AppLocalizations.of(context)!.valueNotNumber); - } - checkValidData(); - } - ), - const SizedBox(height: 30), - numericField( - controller: overrideMaxTtlController, - label: AppLocalizations.of(context)!.overrideMaximumTtl, - helper: AppLocalizations.of(context)!.overrideMaximumTtlDescription, - error: overrideMaxTtlError, - onChanged: (value) { - if (int.tryParse(value) != null) { - setState(() => overrideMaxTtlError = null); - } - else { - setState(() => overrideMaxTtlError = AppLocalizations.of(context)!.valueNotNumber); - } - checkValidData(); - } - ), - const SizedBox(height: 10), - CustomSwitchListTile( - value: optimisticCache, - onChanged: (value) => setState(() => optimisticCache = value), - title: AppLocalizations.of(context)!.optimisticCaching, - subtitle: AppLocalizations.of(context)!.optimisticCachingDescription, - ), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ElevatedButton.icon( - onPressed: () => showDialog( - context: context, - builder: (context) => ClearDnsCacheDialog( - onConfirm: clearCache - ) - ), - icon: const Icon(Icons.delete_rounded), - label: Text(AppLocalizations.of(context)!.clearDnsCache), - ), - ], - ), - const SizedBox(height: 16) - ], + ), + const SizedBox(height: 10), + CustomSwitchListTile( + value: optimisticCache, + onChanged: (value) => setState(() => optimisticCache = value), + title: AppLocalizations.of(context)!.optimisticCaching, + subtitle: AppLocalizations.of(context)!.optimisticCachingDescription, + ), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton.icon( + onPressed: () => showDialog( + context: context, + builder: (context) => ClearDnsCacheDialog( + onConfirm: clearCache + ) + ), + icon: const Icon(Icons.delete_rounded), + label: Text(AppLocalizations.of(context)!.clearDnsCache), + ), + ], + ), + const SizedBox(height: 16) + ], + ), ), ); } diff --git a/lib/screens/settings/dns/comment_modal.dart b/lib/screens/settings/dns/comment_modal.dart index a9dd60d..92d4c0f 100644 --- a/lib/screens/settings/dns/comment_modal.dart +++ b/lib/screens/settings/dns/comment_modal.dart @@ -1,141 +1,30 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -class CommentModal extends StatefulWidget { +class CommentModal extends StatelessWidget { final String? comment; final void Function(String) onConfirm; final bool dialog; const CommentModal({ - Key? key, + super.key, this.comment, required this.onConfirm, required this.dialog - }) : super(key: key); - - @override - State createState() => _CommentModalState(); -} - -class _CommentModalState extends State { - final TextEditingController commentController = TextEditingController(); - - bool validData = false; - - @override - void initState() { - if (widget.comment != null) { - commentController.text = widget.comment!.replaceFirst(RegExp(r'#(\s)?'), ""); - } - super.initState(); - } + }); @override Widget build(BuildContext context) { - Widget content() { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.comment_rounded, - size: 24, - color: Theme.of(context).colorScheme.secondary, - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.comment, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - ], - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: commentController, - onChanged: (value) { - if (value != '') { - setState(() => validData = true); - } - else { - setState(() => validData = false); - } - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.comment_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.comment, - helperText: AppLocalizations.of(context)!.commentsDescription, - helperMaxLines: 3 - ) - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ), - const SizedBox(width: 20), - TextButton( - onPressed: validData == true - ? () { - Navigator.pop(context); - widget.onConfirm("# ${commentController.text}"); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: validData == true - ? Theme.of(context).colorScheme.primary - : Colors.grey - ), - ) - ), - ], - ), - ) - ], - ); - } - - if (widget.dialog == true) { + if (dialog == true) { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( maxWidth: 400 ), - child: content() + child: _Content( + comment: comment, + onConfirm: onConfirm, + ) ), ); } @@ -150,9 +39,139 @@ class _CommentModalState extends State { ), color: Theme.of(context).dialogBackgroundColor ), - child: content() + child: SafeArea( + child: _Content( + comment: comment, + onConfirm: onConfirm, + ), + ) ), ); } } +} + +class _Content extends StatefulWidget { + final String? comment; + final void Function(String) onConfirm; + + const _Content({ + required this.comment, + required this.onConfirm + }); + + @override + State<_Content> createState() => __ContentState(); +} + +class __ContentState extends State<_Content> { + final TextEditingController commentController = TextEditingController(); + + bool validData = false; + + @override + void initState() { + if (widget.comment != null) { + commentController.text = widget.comment!.replaceFirst(RegExp(r'#(\s)?'), ""); + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 24), + child: Icon( + Icons.comment_rounded, + size: 24, + color: Theme.of(context).colorScheme.secondary, + ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.comment, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 16), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: commentController, + onChanged: (value) { + if (value != '') { + setState(() => validData = true); + } + else { + setState(() => validData = false); + } + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.comment_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.comment, + helperText: AppLocalizations.of(context)!.commentsDescription, + helperMaxLines: 3 + ) + ), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + const SizedBox(width: 20), + TextButton( + onPressed: validData == true + ? () { + Navigator.pop(context); + widget.onConfirm("# ${commentController.text}"); + } + : null, + child: Text( + AppLocalizations.of(context)!.confirm, + style: TextStyle( + color: validData == true + ? Theme.of(context).colorScheme.primary + : Colors.grey + ), + ) + ), + ], + ), + ) + ], + ); + } } \ No newline at end of file diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 02ec5d6..2c711d6 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -25,9 +25,9 @@ class DnsSettings extends StatefulWidget { final bool splitView; const DnsSettings({ - Key? key, + super.key, required this.splitView, - }) : super(key: key); + }); @override State createState() => _DnsSettingsState(); @@ -118,95 +118,97 @@ class _DnsSettingsState extends State { const SizedBox(width: 10) ], ), - body: Builder( - builder: (context) { - switch (dnsProvider.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + body: SafeArea( + child: Builder( + builder: (context) { + switch (dnsProvider.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingDnsConfig, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ) + ); + + case LoadStatus.loaded: + return ListView( children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingDnsConfig, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ) - ); - - case LoadStatus.loaded: - return ListView( - children: [ - CustomListTile( - title: AppLocalizations.of(context)!.upstreamDns, - subtitle: AppLocalizations.of(context)!.upstreamDnsDescription, - onTap: () => navigate(const UpstreamDnsScreen()), - icon: Icons.upload_rounded, - ), - CustomListTile( - title: AppLocalizations.of(context)!.bootstrapDns, - subtitle: AppLocalizations.of(context)!.bootstrapDnsDescription, - onTap: () => navigate(const BootstrapDnsScreen()), - icon: Icons.dns_rounded, - ), - CustomListTile( - title: AppLocalizations.of(context)!.privateReverseDnsServers, - subtitle: AppLocalizations.of(context)!.privateReverseDnsDescription, - onTap: () => navigate(const PrivateReverseDnsServersScreen()), - icon: Icons.person_rounded, - ), - CustomListTile( - title: AppLocalizations.of(context)!.dnsServerSettings, - subtitle: AppLocalizations.of(context)!.dnsServerSettingsDescription, - onTap: () => navigate(const DnsServerSettingsScreen()), - icon: Icons.settings, - ), - CustomListTile( - title: AppLocalizations.of(context)!.dnsCacheConfig, - subtitle: AppLocalizations.of(context)!.dnsCacheConfigDescription, - onTap: () => navigate(const CacheConfigDnsScreen()), - icon: Icons.storage_rounded, - ), - ], - ); - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, + CustomListTile( + title: AppLocalizations.of(context)!.upstreamDns, + subtitle: AppLocalizations.of(context)!.upstreamDnsDescription, + onTap: () => navigate(const UpstreamDnsScreen()), + icon: Icons.upload_rounded, + ), + CustomListTile( + title: AppLocalizations.of(context)!.bootstrapDns, + subtitle: AppLocalizations.of(context)!.bootstrapDnsDescription, + onTap: () => navigate(const BootstrapDnsScreen()), + icon: Icons.dns_rounded, + ), + CustomListTile( + title: AppLocalizations.of(context)!.privateReverseDnsServers, + subtitle: AppLocalizations.of(context)!.privateReverseDnsDescription, + onTap: () => navigate(const PrivateReverseDnsServersScreen()), + icon: Icons.person_rounded, + ), + CustomListTile( + title: AppLocalizations.of(context)!.dnsServerSettings, + subtitle: AppLocalizations.of(context)!.dnsServerSettingsDescription, + onTap: () => navigate(const DnsServerSettingsScreen()), + icon: Icons.settings, + ), + CustomListTile( + title: AppLocalizations.of(context)!.dnsCacheConfig, + subtitle: AppLocalizations.of(context)!.dnsCacheConfigDescription, + onTap: () => navigate(const CacheConfigDnsScreen()), + icon: Icons.storage_rounded, ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.dnsConfigNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) ], - ), - ); - - default: - return const SizedBox(); - } - }, + ); + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.dnsConfigNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ), ) ); } diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index 777821f..4cc650a 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -167,141 +167,143 @@ class _DnsServerSettingsScreenState extends State { const SizedBox(width: 10) ], ), - body: ListView( - padding: const EdgeInsets.only(top: 10), - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: limitRequestsController, - onChanged: (value) { - if (int.tryParse(value) != null) { - setState(() => limitRequestsError = null); - } - else { - setState(() => limitRequestsError = AppLocalizations.of(context)!.valueNotNumber); - } - validateData(); - }, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.looks_one_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.limitRequestsSecond, - errorText: limitRequestsError - ), - keyboardType: TextInputType.number, - ), - ), - const SizedBox(height: 10), - CustomSwitchListTile( - value: enableEdns, - onChanged: (value) => setState(() => enableEdns = value), - title: AppLocalizations.of(context)!.enableEdns, - subtitle: AppLocalizations.of(context)!.enableEdnsDescription, - ), - CustomSwitchListTile( - value: enableDnssec, - onChanged: (value) => setState(() => enableDnssec = value), - title: AppLocalizations.of(context)!.enableDnssec, - subtitle: AppLocalizations.of(context)!.enableDnssecDescription, - ), - CustomSwitchListTile( - value: disableIpv6Resolving, - onChanged: (value) => setState(() => disableIpv6Resolving = value), - title: AppLocalizations.of(context)!.disableResolvingIpv6, - subtitle: AppLocalizations.of(context)!.disableResolvingIpv6Description, - ), - SectionLabel(label: AppLocalizations.of(context)!.blockingMode), - CustomRadioListTile( - groupValue: blockingMode, - value: "default", - radioBackgroundColor: Theme.of(context).dialogBackgroundColor, - title: AppLocalizations.of(context)!.defaultMode, - subtitle: AppLocalizations.of(context)!.defaultDescription, - onChanged: updateBlockingMode, - ), - CustomRadioListTile( - groupValue: blockingMode, - value: "refused", - radioBackgroundColor: Theme.of(context).dialogBackgroundColor, - title: "REFUSED", - subtitle: AppLocalizations.of(context)!.refusedDescription, - onChanged: updateBlockingMode, - ), - CustomRadioListTile( - groupValue: blockingMode, - value: "nxdomain", - radioBackgroundColor: Theme.of(context).dialogBackgroundColor, - title: "NXDOMAIN", - subtitle: AppLocalizations.of(context)!.nxdomainDescription, - onChanged: updateBlockingMode, - ), - CustomRadioListTile( - groupValue: blockingMode, - value: "null_ip", - radioBackgroundColor: Theme.of(context).dialogBackgroundColor, - title: AppLocalizations.of(context)!.nullIp, - subtitle: AppLocalizations.of(context)!.nullIpDescription, - onChanged: updateBlockingMode, - ), - CustomRadioListTile( - groupValue: blockingMode, - value: "custom_ip", - radioBackgroundColor: Theme.of(context).dialogBackgroundColor, - title: AppLocalizations.of(context)!.customIp, - subtitle: AppLocalizations.of(context)!.customIpDescription, - onChanged: updateBlockingMode, - ), - const SizedBox(height: 10), - if (blockingMode == 'custom_ip') ...[ + body: SafeArea( + child: ListView( + padding: const EdgeInsets.only(top: 10), + children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), + padding: const EdgeInsets.symmetric(horizontal: 16), child: TextFormField( - controller: ipv4controller, - onChanged: validateIpv4, + controller: limitRequestsController, + onChanged: (value) { + if (int.tryParse(value) != null) { + setState(() => limitRequestsError = null); + } + else { + setState(() => limitRequestsError = AppLocalizations.of(context)!.valueNotNumber); + } + validateData(); + }, decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), + prefixIcon: const Icon(Icons.looks_one_rounded), border: const OutlineInputBorder( borderRadius: BorderRadius.all( Radius.circular(10) ) ), - errorText: ipv4error, - helperText: AppLocalizations.of(context)!.blockingIpv4Description, - helperMaxLines: 10, - labelText: AppLocalizations.of(context)!.blockingIpv4, + labelText: AppLocalizations.of(context)!.limitRequestsSecond, + errorText: limitRequestsError ), keyboardType: TextInputType.number, ), ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: ipv6controller, - onChanged: validateIpv6, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) + const SizedBox(height: 10), + CustomSwitchListTile( + value: enableEdns, + onChanged: (value) => setState(() => enableEdns = value), + title: AppLocalizations.of(context)!.enableEdns, + subtitle: AppLocalizations.of(context)!.enableEdnsDescription, + ), + CustomSwitchListTile( + value: enableDnssec, + onChanged: (value) => setState(() => enableDnssec = value), + title: AppLocalizations.of(context)!.enableDnssec, + subtitle: AppLocalizations.of(context)!.enableDnssecDescription, + ), + CustomSwitchListTile( + value: disableIpv6Resolving, + onChanged: (value) => setState(() => disableIpv6Resolving = value), + title: AppLocalizations.of(context)!.disableResolvingIpv6, + subtitle: AppLocalizations.of(context)!.disableResolvingIpv6Description, + ), + SectionLabel(label: AppLocalizations.of(context)!.blockingMode), + CustomRadioListTile( + groupValue: blockingMode, + value: "default", + radioBackgroundColor: Theme.of(context).dialogBackgroundColor, + title: AppLocalizations.of(context)!.defaultMode, + subtitle: AppLocalizations.of(context)!.defaultDescription, + onChanged: updateBlockingMode, + ), + CustomRadioListTile( + groupValue: blockingMode, + value: "refused", + radioBackgroundColor: Theme.of(context).dialogBackgroundColor, + title: "REFUSED", + subtitle: AppLocalizations.of(context)!.refusedDescription, + onChanged: updateBlockingMode, + ), + CustomRadioListTile( + groupValue: blockingMode, + value: "nxdomain", + radioBackgroundColor: Theme.of(context).dialogBackgroundColor, + title: "NXDOMAIN", + subtitle: AppLocalizations.of(context)!.nxdomainDescription, + onChanged: updateBlockingMode, + ), + CustomRadioListTile( + groupValue: blockingMode, + value: "null_ip", + radioBackgroundColor: Theme.of(context).dialogBackgroundColor, + title: AppLocalizations.of(context)!.nullIp, + subtitle: AppLocalizations.of(context)!.nullIpDescription, + onChanged: updateBlockingMode, + ), + CustomRadioListTile( + groupValue: blockingMode, + value: "custom_ip", + radioBackgroundColor: Theme.of(context).dialogBackgroundColor, + title: AppLocalizations.of(context)!.customIp, + subtitle: AppLocalizations.of(context)!.customIpDescription, + onChanged: updateBlockingMode, + ), + const SizedBox(height: 10), + if (blockingMode == 'custom_ip') ...[ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: ipv4controller, + onChanged: validateIpv4, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv4error, + helperText: AppLocalizations.of(context)!.blockingIpv4Description, + helperMaxLines: 10, + labelText: AppLocalizations.of(context)!.blockingIpv4, ), - errorText: ipv6error, - helperText: AppLocalizations.of(context)!.blockingIpv6Description, - helperMaxLines: 10, - labelText: AppLocalizations.of(context)!.blockingIpv6, + keyboardType: TextInputType.number, ), - keyboardType: TextInputType.number, ), - ), - const SizedBox(height: 30) - ] - ], + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: ipv6controller, + onChanged: validateIpv6, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ipv6error, + helperText: AppLocalizations.of(context)!.blockingIpv6Description, + helperMaxLines: 10, + labelText: AppLocalizations.of(context)!.blockingIpv6, + ), + keyboardType: TextInputType.number, + ), + ), + const SizedBox(height: 30) + ] + ], + ), ), ); } diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index f91c593..a9419e9 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -13,7 +13,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class PrivateReverseDnsServersScreen extends StatefulWidget { - const PrivateReverseDnsServersScreen({Key? key}) : super(key: key); + const PrivateReverseDnsServersScreen({super.key}); @override State createState() => _PrivateReverseDnsServersScreenState(); @@ -149,107 +149,40 @@ class _PrivateReverseDnsServersScreenState extends State item).join(', ').toString().replaceAll(RegExp(r'\(|\)'), '')}", - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant, - fontSize: 16 + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).listTileTheme.iconColor, + ), + const SizedBox(width: 16), + Flexible( + child: Text( + AppLocalizations.of(context)!.privateReverseDnsServersDescription, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ) + ], ), ), ), - Padding( - padding: const EdgeInsets.only(top: 10, bottom: 20), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ElevatedButton.icon( - onPressed: () { - setState(() => editReverseResolvers = true); - checkDataValid(); - }, - icon: const Icon(Icons.edit), - label: Text(AppLocalizations.of(context)!.edit) - ), - ], - ), - ) - ], - if (editReverseResolvers == true) ...[ - const SizedBox(height: 20), - ...reverseResolversControllers.map((c) => Padding( - padding: const EdgeInsets.only( - left: 16, right: 6, bottom: 20 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: TextFormField( - controller: c['controller'], - onChanged: (value) => validateAddress(c, value), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.dns_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: c['error'], - labelText: AppLocalizations.of(context)!.serverAddress, - ) - ), - ), - const SizedBox(width: 8), - IconButton( - onPressed: () { - setState(() => reverseResolversControllers = reverseResolversControllers.where((con) => con != c).toList()); - checkDataValid(); - }, - icon: const Icon(Icons.remove_circle_outline) - ) - ], - ), - )), - if (reverseResolversControllers.isEmpty) Padding( - padding: const EdgeInsets.only( - left: 20, right: 20, bottom: 20 - ), - child: Center( + if (editReverseResolvers == false) ...[ + Padding( + padding: const EdgeInsets.all(20), child: Text( - AppLocalizations.of(context)!.noServerAddressesAdded, + "${AppLocalizations.of(context)!.reverseDnsDefault}:\n\n${defaultReverseResolvers.map((item) => item).join(', ').toString().replaceAll(RegExp(r'\(|\)'), '')}", textAlign: TextAlign.center, style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant, @@ -257,41 +190,110 @@ class _PrivateReverseDnsServersScreenState extends State reverseResolversControllers.add({ - 'controller': TextEditingController(), - 'error': null - })); - checkDataValid(); - }, - icon: const Icon(Icons.add), - label: Text(AppLocalizations.of(context)!.addItem) + Padding( + padding: const EdgeInsets.only(top: 10, bottom: 20), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton.icon( + onPressed: () { + setState(() => editReverseResolvers = true); + checkDataValid(); + }, + icon: const Icon(Icons.edit), + label: Text(AppLocalizations.of(context)!.edit) + ), + ], + ), + ) + ], + if (editReverseResolvers == true) ...[ + const SizedBox(height: 20), + ...reverseResolversControllers.map((c) => Padding( + padding: const EdgeInsets.only( + left: 16, right: 6, bottom: 20 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextFormField( + controller: c['controller'], + onChanged: (value) => validateAddress(c, value), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.dns_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: c['error'], + labelText: AppLocalizations.of(context)!.serverAddress, + ) + ), + ), + const SizedBox(width: 8), + IconButton( + onPressed: () { + setState(() => reverseResolversControllers = reverseResolversControllers.where((con) => con != c).toList()); + checkDataValid(); + }, + icon: const Icon(Icons.remove_circle_outline) + ) + ], + ), + )), + if (reverseResolversControllers.isEmpty) Padding( + padding: const EdgeInsets.only( + left: 20, right: 20, bottom: 20 + ), + child: Center( + child: Text( + AppLocalizations.of(context)!.noServerAddressesAdded, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontSize: 16 + ), ), - ], + ), ), + Padding( + padding: const EdgeInsets.only(bottom: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton.icon( + onPressed: () { + setState(() => reverseResolversControllers.add({ + 'controller': TextEditingController(), + 'error': null + })); + checkDataValid(); + }, + icon: const Icon(Icons.add), + label: Text(AppLocalizations.of(context)!.addItem) + ), + ], + ), + ), + ], + CustomSwitchListTile( + value: usePrivateReverseDnsResolvers, + onChanged: (value) => setState(() => usePrivateReverseDnsResolvers = value), + title: AppLocalizations.of(context)!.usePrivateReverseDnsResolvers, + subtitle: AppLocalizations.of(context)!.usePrivateReverseDnsResolversDescription + ), + CustomSwitchListTile( + value: enableReverseResolve, + onChanged: (value) => setState(() => enableReverseResolve = value), + title: AppLocalizations.of(context)!.enableReverseResolving, + subtitle: AppLocalizations.of(context)!.enableReverseResolvingDescription ), ], - CustomSwitchListTile( - value: usePrivateReverseDnsResolvers, - onChanged: (value) => setState(() => usePrivateReverseDnsResolvers = value), - title: AppLocalizations.of(context)!.usePrivateReverseDnsResolvers, - subtitle: AppLocalizations.of(context)!.usePrivateReverseDnsResolversDescription - ), - CustomSwitchListTile( - value: enableReverseResolve, - onChanged: (value) => setState(() => enableReverseResolve = value), - title: AppLocalizations.of(context)!.enableReverseResolving, - subtitle: AppLocalizations.of(context)!.enableReverseResolvingDescription - ), - ], + ), ), ); } diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 5dd2acb..f952110 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -189,129 +189,131 @@ class _UpstreamDnsScreenState extends State { const SizedBox(width: 10) ], ), - body: ListView( - padding: const EdgeInsets.only(top: 10), - children: [ - if (dnsServers.isEmpty) Column( - children: [ - Padding( - padding: const EdgeInsets.all(10), - child: Center( - child: Text( - AppLocalizations.of(context)!.noUpstreamDns, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant, - fontSize: 16 + body: SafeArea( + child: ListView( + padding: const EdgeInsets.only(top: 10), + children: [ + if (dnsServers.isEmpty) Column( + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: Center( + child: Text( + AppLocalizations.of(context)!.noUpstreamDns, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontSize: 16 + ), ), ), ), - ), - const SizedBox(height: 20), - ], - ), - ...dnsServers.map((item) => Padding( - padding: const EdgeInsets.only( - left: 16, right: 6, bottom: 24 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (item['controller'] != null) Expanded( - child: TextFormField( - controller: item['controller'], - onChanged: (_) => checkValidValues(), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.dns_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.dnsServer, - ) - ), - ), - const SizedBox(width: 8), - if (item['comment'] != null) Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - item['comment'], - style: TextStyle( - fontSize: 16, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - IconButton( - onPressed: () => openEditCommentModal(item, dnsServers.indexOf(item)), - icon: const Icon(Icons.edit), - tooltip: AppLocalizations.of(context)!.edit, - ) - ], - ), - ), - IconButton( - onPressed: () { - setState(() => dnsServers = dnsServers.where((i) => i != item).toList()); - checkValidValues(); - }, - icon: const Icon(Icons.remove_circle_outline), - tooltip: AppLocalizations.of(context)!.remove, - ), - const SizedBox(width: 4), + const SizedBox(height: 20), ], ), - )).toList(), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.min, - children: [ - ElevatedButton.icon( - onPressed: openAddCommentModal, - icon: const Icon(Icons.add), - label: Text(AppLocalizations.of(context)!.comment) + ...dnsServers.map((item) => Padding( + padding: const EdgeInsets.only( + left: 16, right: 6, bottom: 24 ), - ElevatedButton.icon( - onPressed: () { - setState(() => dnsServers.add({ - 'controller': TextEditingController() - })); - checkValidValues(); - }, - icon: const Icon(Icons.add), - label: Text(AppLocalizations.of(context)!.address) + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (item['controller'] != null) Expanded( + child: TextFormField( + controller: item['controller'], + onChanged: (_) => checkValidValues(), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.dns_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.dnsServer, + ) + ), + ), + const SizedBox(width: 8), + if (item['comment'] != null) Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + item['comment'], + style: TextStyle( + fontSize: 16, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + IconButton( + onPressed: () => openEditCommentModal(item, dnsServers.indexOf(item)), + icon: const Icon(Icons.edit), + tooltip: AppLocalizations.of(context)!.edit, + ) + ], + ), + ), + IconButton( + onPressed: () { + setState(() => dnsServers = dnsServers.where((i) => i != item).toList()); + checkValidValues(); + }, + icon: const Icon(Icons.remove_circle_outline), + tooltip: AppLocalizations.of(context)!.remove, + ), + const SizedBox(width: 4), + ], ), - ], - ), - const SizedBox(height: 16), - SectionLabel(label: AppLocalizations.of(context)!.dnsMode), - CustomRadioListTile( - groupValue: upstreamMode, - value: "", - 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", - 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_addr", - radioBackgroundColor: Theme.of(context).dialogBackgroundColor, - title: AppLocalizations.of(context)!.fastestIpAddress, - subtitle: AppLocalizations.of(context)!.fastestIpAddressDescription, - onChanged: (value) => setState(() => upstreamMode = value), - ), - ], + )).toList(), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton.icon( + onPressed: openAddCommentModal, + icon: const Icon(Icons.add), + label: Text(AppLocalizations.of(context)!.comment) + ), + ElevatedButton.icon( + onPressed: () { + setState(() => dnsServers.add({ + 'controller': TextEditingController() + })); + checkValidValues(); + }, + icon: const Icon(Icons.add), + label: Text(AppLocalizations.of(context)!.address) + ), + ], + ), + const SizedBox(height: 16), + SectionLabel(label: AppLocalizations.of(context)!.dnsMode), + CustomRadioListTile( + groupValue: upstreamMode, + value: "", + 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", + 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_addr", + radioBackgroundColor: Theme.of(context).dialogBackgroundColor, + title: AppLocalizations.of(context)!.fastestIpAddress, + subtitle: AppLocalizations.of(context)!.fastestIpAddressDescription, + onChanged: (value) => setState(() => upstreamMode = value), + ), + ], + ), ), ); } diff --git a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart index fcd62d7..439455c 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart @@ -46,10 +46,12 @@ class DnsRewriteModal extends StatelessWidget { ), color: Theme.of(context).dialogBackgroundColor, ), - child: _Content( - onConfirm: onConfirm, - onDelete: onDelete, - rule: rule, + child: SafeArea( + child: _Content( + onConfirm: onConfirm, + onDelete: onDelete, + rule: rule, + ), ) ), ); diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 8b5ee0d..301c3a1 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -136,239 +136,241 @@ class _DnsRewritesScreenState extends State { surfaceTintColor: isDesktop(width) ? Colors.transparent : null, centerTitle: false, ), - body: Stack( - children: [ - Builder( - builder: (context) { - switch (rewriteRulesProvider.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingRewriteRules, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - if (rewriteRulesProvider.rewriteRules!.isNotEmpty) { - return RefreshIndicator( - onRefresh: () async { - final result = await rewriteRulesProvider.fetchRules(); - if (result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.rewriteRulesNotLoaded, - color: Colors.red - ); - } - }, - child: ListView.builder( - controller: scrollController, - padding: const EdgeInsets.only(top: 0), - itemCount: rewriteRulesProvider.rewriteRules!.length, - itemBuilder: (context, index) => Card( - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: InkWell( - onTap: () => { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => DnsRewriteModal( - onConfirm: updateRewriteRule, - dialog: true, - rule: rewriteRulesProvider.rewriteRules![index], - onDelete: (rule) => showDialog( - context: context, - builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(rule) - ) - ), - ), - ) - } - else { - showModalBottomSheet( - context: context, - useRootNavigator: true, - builder: (context) => DnsRewriteModal( - onConfirm: updateRewriteRule, - dialog: false, - rule: rewriteRulesProvider.rewriteRules![index], - onDelete: (rule) => showDialog( - context: context, - builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(rule) - ) - ), - ), - backgroundColor: Colors.transparent, - isScrollControlled: true, - ) - } - }, - borderRadius: BorderRadius.circular(10), - child: Padding( - padding: const EdgeInsets.only( - left: 16, top: 16, bottom: 16, right: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.domain}: ", - style: TextStyle( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Text( - rewriteRulesProvider.rewriteRules![index].domain, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], + body: SafeArea( + child: Stack( + children: [ + Builder( + builder: (context) { + switch (rewriteRulesProvider.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingRewriteRules, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + if (rewriteRulesProvider.rewriteRules!.isNotEmpty) { + return RefreshIndicator( + onRefresh: () async { + final result = await rewriteRulesProvider.fetchRules(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.rewriteRulesNotLoaded, + color: Colors.red + ); + } + }, + child: ListView.builder( + controller: scrollController, + padding: const EdgeInsets.only(top: 0), + itemCount: rewriteRulesProvider.rewriteRules!.length, + itemBuilder: (context, index) => Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: InkWell( + onTap: () => { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => DnsRewriteModal( + onConfirm: updateRewriteRule, + dialog: true, + rule: rewriteRulesProvider.rewriteRules![index], + onDelete: (rule) => showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rule) + ) ), - const SizedBox(height: 3), - Row( - children: [ - Text( - "${AppLocalizations.of(context)!.answer}: ", - style: TextStyle( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Text( - rewriteRulesProvider.rewriteRules![index].answer, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ], - ), - Icon( - Icons.keyboard_arrow_right_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ) - ], + } + else { + showModalBottomSheet( + context: context, + useRootNavigator: true, + builder: (context) => DnsRewriteModal( + onConfirm: updateRewriteRule, + dialog: false, + rule: rewriteRulesProvider.rewriteRules![index], + onDelete: (rule) => showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rule) + ) + ), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + ) + } + }, + borderRadius: BorderRadius.circular(10), + child: Padding( + padding: const EdgeInsets.only( + left: 16, top: 16, bottom: 16, right: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.domain}: ", + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Text( + rewriteRulesProvider.rewriteRules![index].domain, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + const SizedBox(height: 3), + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.answer}: ", + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Text( + rewriteRulesProvider.rewriteRules![index].answer, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ], + ), + Icon( + Icons.keyboard_arrow_right_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ) + ], + ), ), ), - ), - ) - ), - ); - } - else { - return Center( - child: Text( - AppLocalizations.of(context)!.noRewriteRules, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, + ) ), - ), - ); - } - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.rewriteRulesNotLoaded, - textAlign: TextAlign.center, + ); + } + else { + return Center( + child: Text( + AppLocalizations.of(context)!.noRewriteRules, style: TextStyle( fontSize: 22, color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - }, - ), - AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: isVisible ? - appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, - right: 20, - child: FloatingActionButton( - onPressed: () => { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => DnsRewriteModal( - onConfirm: addDnsRewrite, - dialog: true, - onDelete: (rule) => showDialog( - context: context, - builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(rule) - ) ), - ), - ) - } - else { - showModalBottomSheet( - context: context, - useRootNavigator: true, - builder: (context) => DnsRewriteModal( - onConfirm: addDnsRewrite, - dialog: false, - onDelete: (rule) => showDialog( - context: context, - builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(rule) + ); + } + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.rewriteRulesNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ) - ), + ], ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ) - } - }, - child: const Icon(Icons.add), - ), - ) - ], + ); + + default: + return const SizedBox(); + } + }, + ), + AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: isVisible ? + appConfigProvider.showingSnackbar + ? 70 : 20 + : -70, + right: 20, + child: FloatingActionButton( + onPressed: () => { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => DnsRewriteModal( + onConfirm: addDnsRewrite, + dialog: true, + onDelete: (rule) => showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rule) + ) + ), + ), + ) + } + else { + showModalBottomSheet( + context: context, + useRootNavigator: true, + builder: (context) => DnsRewriteModal( + onConfirm: addDnsRewrite, + dialog: false, + onDelete: (rule) => showDialog( + context: context, + builder: (context) => DeleteDnsRewrite( + onConfirm: () => deleteDnsRewrite(rule) + ) + ), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true + ) + } + }, + child: const Icon(Icons.add), + ), + ) + ], + ), ), ); } diff --git a/lib/screens/settings/dns_rewrites/rule_modal.dart b/lib/screens/settings/dns_rewrites/rule_modal.dart deleted file mode 100644 index e69de29..0000000 diff --git a/lib/screens/settings/dns_rewrites/server_version_needed.dart b/lib/screens/settings/dns_rewrites/server_version_needed.dart index 88888c6..68ea426 100644 --- a/lib/screens/settings/dns_rewrites/server_version_needed.dart +++ b/lib/screens/settings/dns_rewrites/server_version_needed.dart @@ -4,6 +4,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class ServerVersionNeeded extends StatelessWidget { final String version; + // ignore: use_super_parameters const ServerVersionNeeded({ Key? key, required this.version diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index f47a63d..e11047e 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -283,376 +283,378 @@ class _EncryptionSettingsState extends State { const SizedBox(width: 10), ], ), - body: Builder( - builder: (context) { - switch (loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingEncryptionSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ) - ); - - case LoadStatus.loaded: - return ListView( - children: [ - EncryptionMasterSwitch( - value: enabled, - onChange: (value) { - setState(() => enabled = value); - onEditValidate(); - } - ), - SectionLabel( - label: AppLocalizations.of(context)!.serverConfiguration, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), - ), - EncryptionTextField( - enabled: enabled, - controller: domainNameController, - icon: Icons.link_rounded, - onChanged: (value) { - setState(() => domainError = validateDomain(context, value)); - onEditValidate(); - }, - errorText: domainError, - label: AppLocalizations.of(context)!.domainName, - helperText: AppLocalizations.of(context)!.domainNameDescription, - ), - const SizedBox(height: 10), - CustomSwitchListTile( - value: redirectHttps, - onChanged: (value) { - setState(() => redirectHttps = value); - onEditValidate(); - }, - title: AppLocalizations.of(context)!.redirectHttps, - disabled: !enabled, - ), - const SizedBox(height: 10), - Wrap( + body: SafeArea( + child: Builder( + builder: (context) { + switch (loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - FractionallySizedBox( - widthFactor: width > 900 ? 0.33 : 1, - child: EncryptionTextField( - enabled: enabled, - controller: httpsPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => httpsPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: httpsPortError, - label: AppLocalizations.of(context)!.httpsPort, - keyboardType: TextInputType.number, + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingEncryptionSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ), - Padding( - padding: width <= 900 - ? const EdgeInsets.symmetric(vertical: 24) - : const EdgeInsets.all(0), - child: FractionallySizedBox( + ) + ], + ) + ); + + case LoadStatus.loaded: + return ListView( + children: [ + EncryptionMasterSwitch( + value: enabled, + onChange: (value) { + setState(() => enabled = value); + onEditValidate(); + } + ), + SectionLabel( + label: AppLocalizations.of(context)!.serverConfiguration, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + ), + EncryptionTextField( + enabled: enabled, + controller: domainNameController, + icon: Icons.link_rounded, + onChanged: (value) { + setState(() => domainError = validateDomain(context, value)); + onEditValidate(); + }, + errorText: domainError, + label: AppLocalizations.of(context)!.domainName, + helperText: AppLocalizations.of(context)!.domainNameDescription, + ), + const SizedBox(height: 10), + CustomSwitchListTile( + value: redirectHttps, + onChanged: (value) { + setState(() => redirectHttps = value); + onEditValidate(); + }, + title: AppLocalizations.of(context)!.redirectHttps, + disabled: !enabled, + ), + const SizedBox(height: 10), + Wrap( + children: [ + FractionallySizedBox( widthFactor: width > 900 ? 0.33 : 1, child: EncryptionTextField( enabled: enabled, - controller: tlsPortController, + controller: httpsPortController, icon: Icons.numbers_rounded, onChanged: (value) { - setState(() => tlsPortError = validatePort(context, value)); + setState(() => httpsPortError = validatePort(context, value)); onEditValidate(); }, - errorText: tlsPortError, - label: AppLocalizations.of(context)!.tlsPort, + errorText: httpsPortError, + label: AppLocalizations.of(context)!.httpsPort, keyboardType: TextInputType.number, ), ), - ), - FractionallySizedBox( - widthFactor: width > 900 ? 0.33 : 1, - child: EncryptionTextField( - enabled: enabled, - controller: dnsOverQuicPortController, - icon: Icons.numbers_rounded, - onChanged: (value) { - setState(() => dnsOverQuicPortError = validatePort(context, value)); - onEditValidate(); - }, - errorText: dnsOverQuicPortError, - label: AppLocalizations.of(context)!.dnsOverQuicPort, - keyboardType: TextInputType.number, + Padding( + padding: width <= 900 + ? const EdgeInsets.symmetric(vertical: 24) + : const EdgeInsets.all(0), + child: FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: tlsPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => tlsPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: tlsPortError, + label: AppLocalizations.of(context)!.tlsPort, + keyboardType: TextInputType.number, + ), + ), + ), + FractionallySizedBox( + widthFactor: width > 900 ? 0.33 : 1, + child: EncryptionTextField( + enabled: enabled, + controller: dnsOverQuicPortController, + icon: Icons.numbers_rounded, + onChanged: (value) { + setState(() => dnsOverQuicPortError = validatePort(context, value)); + onEditValidate(); + }, + errorText: dnsOverQuicPortError, + label: AppLocalizations.of(context)!.dnsOverQuicPort, + keyboardType: TextInputType.number, + ), + ), + ], + ), + SectionLabel( + label: AppLocalizations.of(context)!.certificates, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 16), + child: Padding( + padding: const EdgeInsets.all(20), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).listTileTheme.iconColor, + ), + const SizedBox(width: 20), + Flexible( + child: Text( + AppLocalizations.of(context)!.certificatesDescription, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ) + ) + ], ), ), - ], - ), - SectionLabel( - label: AppLocalizations.of(context)!.certificates, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), - ), - Card( - margin: const EdgeInsets.symmetric(horizontal: 16), - child: Padding( - padding: const EdgeInsets.all(20), - child: Row( - children: [ - Icon( - Icons.info_rounded, - color: Theme.of(context).listTileTheme.iconColor, - ), - const SizedBox(width: 20), - Flexible( - child: Text( - AppLocalizations.of(context)!.certificatesDescription, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - ), - ) - ) - ], - ), ), - ), - const SizedBox(height: 20), - RadioListTile( - value: 0, - groupValue: certificateOption, - onChanged: enabled == true - ? (value) { - setState(() => certificateOption = int.parse(value.toString())); - onEditValidate(); - } - : null, - title: Text( - AppLocalizations.of(context)!.certificateFilePath, - style: const TextStyle( - fontWeight: FontWeight.normal - ), - ), - ), - RadioListTile( - value: 1, - groupValue: certificateOption, - onChanged: enabled == true - ? (value) { - setState(() => certificateOption = int.parse(value.toString())); - onEditValidate(); - } - : null, - title: Text( - AppLocalizations.of(context)!.pasteCertificateContent, - style: const TextStyle( - fontWeight: FontWeight.normal - ), - ), - ), - const SizedBox(height: 10), - if (certificateOption == 0) EncryptionTextField( - enabled: enabled, - controller: certificatePathController, - icon: Icons.description_rounded, - onChanged: (value) { - setState(() => certificatePathError = validatePath(context, value)); - onEditValidate(); - }, - label: AppLocalizations.of(context)!.certificatePath, - errorText: certificatePathError, - ), - if (certificateOption == 1) EncryptionTextField( - enabled: enabled, - controller: certificateContentController, - icon: Icons.description_rounded, - onChanged: (value) { - setState(() => certificateContentError = validateCertificate(context, value)); - onEditValidate(); - }, - label: AppLocalizations.of(context)!.certificateContent, - errorText: certificateContentError, - multiline: true, - keyboardType: TextInputType.multiline, - ), - if (certKeyValid != null && (certificateContentController.text != '' || certificatePathController.text != '')) ...[ const SizedBox(height: 20), - if (certKeyValid!.validChain != null) ...[ - Status( - valid: certKeyValid!.validChain ?? false, - label: certKeyValid!.validChain == true - ? AppLocalizations.of(context)!.validCertificateChain - : AppLocalizations.of(context)!.invalidCertificateChain, + RadioListTile( + value: 0, + groupValue: certificateOption, + onChanged: enabled == true + ? (value) { + setState(() => certificateOption = int.parse(value.toString())); + onEditValidate(); + } + : null, + title: Text( + AppLocalizations.of(context)!.certificateFilePath, + style: const TextStyle( + fontWeight: FontWeight.normal + ), ), - const SizedBox(height: 10), - ], - if (certKeyValid!.subject != null) ...[ - Status( + ), + RadioListTile( + value: 1, + groupValue: certificateOption, + onChanged: enabled == true + ? (value) { + setState(() => certificateOption = int.parse(value.toString())); + onEditValidate(); + } + : null, + title: Text( + AppLocalizations.of(context)!.pasteCertificateContent, + style: const TextStyle( + fontWeight: FontWeight.normal + ), + ), + ), + const SizedBox(height: 10), + if (certificateOption == 0) EncryptionTextField( + enabled: enabled, + controller: certificatePathController, + icon: Icons.description_rounded, + onChanged: (value) { + setState(() => certificatePathError = validatePath(context, value)); + onEditValidate(); + }, + label: AppLocalizations.of(context)!.certificatePath, + errorText: certificatePathError, + ), + if (certificateOption == 1) EncryptionTextField( + enabled: enabled, + controller: certificateContentController, + icon: Icons.description_rounded, + onChanged: (value) { + setState(() => certificateContentError = validateCertificate(context, value)); + onEditValidate(); + }, + label: AppLocalizations.of(context)!.certificateContent, + errorText: certificateContentError, + multiline: true, + keyboardType: TextInputType.multiline, + ), + if (certKeyValid != null && (certificateContentController.text != '' || certificatePathController.text != '')) ...[ + const SizedBox(height: 20), + if (certKeyValid!.validChain != null) ...[ + Status( + valid: certKeyValid!.validChain ?? false, + label: certKeyValid!.validChain == true + ? AppLocalizations.of(context)!.validCertificateChain + : AppLocalizations.of(context)!.invalidCertificateChain, + ), + const SizedBox(height: 10), + ], + if (certKeyValid!.subject != null) ...[ + Status( + valid: true, + label: "${AppLocalizations.of(context)!.subject}: ${certKeyValid?.subject}" + ), + const SizedBox(height: 10), + ], + if (certKeyValid!.issuer != null) ...[ + Status( valid: true, - label: "${AppLocalizations.of(context)!.subject}: ${certKeyValid?.subject}" + label: "${AppLocalizations.of(context)!.issuer}: ${certKeyValid?.issuer}" ), - const SizedBox(height: 10), + const SizedBox(height: 10), + ], + if (certKeyValid!.notAfter != null) ...[ + Status( + valid: true, + label: "${AppLocalizations.of(context)!.expirationDate}: ${certKeyValid?.notAfter}" + ), + const SizedBox(height: 10), + ], + if (certKeyValid!.dnsNames != null) ...[ + Status( + valid: true, + label: "${AppLocalizations.of(context)!.hostNames}: ${certKeyValid?.dnsNames?.join(', ')}" + ), + const SizedBox(height: 10), + ], ], - if (certKeyValid!.issuer != null) ...[ - Status( - valid: true, - label: "${AppLocalizations.of(context)!.issuer}: ${certKeyValid?.issuer}" + SectionLabel( + label: AppLocalizations.of(context)!.privateKey, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), ), - const SizedBox(height: 10), - ], - if (certKeyValid!.notAfter != null) ...[ - Status( - valid: true, - label: "${AppLocalizations.of(context)!.expirationDate}: ${certKeyValid?.notAfter}" - ), - const SizedBox(height: 10), - ], - if (certKeyValid!.dnsNames != null) ...[ - Status( - valid: true, - label: "${AppLocalizations.of(context)!.hostNames}: ${certKeyValid?.dnsNames?.join(', ')}" - ), - const SizedBox(height: 10), - ], - ], - SectionLabel( - label: AppLocalizations.of(context)!.privateKey, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), - ), - RadioListTile( - value: 0, - groupValue: privateKeyOption, - onChanged: enabled == true - ? (value) { - setState(() => privateKeyOption = int.parse(value.toString())); - onEditValidate(); - } - : null, - title: Text( - AppLocalizations.of(context)!.privateKeyFile, - style: const TextStyle( - fontWeight: FontWeight.normal + RadioListTile( + value: 0, + groupValue: privateKeyOption, + onChanged: enabled == true + ? (value) { + setState(() => privateKeyOption = int.parse(value.toString())); + onEditValidate(); + } + : null, + title: Text( + AppLocalizations.of(context)!.privateKeyFile, + style: const TextStyle( + fontWeight: FontWeight.normal + ), ), ), - ), - RadioListTile( - value: 1, - groupValue: privateKeyOption, - onChanged: enabled == true - ? (value) { - setState(() => privateKeyOption = int.parse(value.toString())); - onEditValidate(); - } - : null, - title: Text( - AppLocalizations.of(context)!.pastePrivateKey, - style: const TextStyle( - fontWeight: FontWeight.normal + RadioListTile( + value: 1, + groupValue: privateKeyOption, + onChanged: enabled == true + ? (value) { + setState(() => privateKeyOption = int.parse(value.toString())); + onEditValidate(); + } + : null, + title: Text( + AppLocalizations.of(context)!.pastePrivateKey, + style: const TextStyle( + fontWeight: FontWeight.normal + ), ), ), - ), - if (privateKeyOption == 0) const SizedBox(height: 10), - if (privateKeyOption == 1) ...[ - CustomSwitchListTile( - value: usePreviouslySavedKey, - onChanged: (value) => setState(() => usePreviouslySavedKey = value), - title: AppLocalizations.of(context)!.usePreviousKey, - ), - const SizedBox(height: 10) - ], - if (privateKeyOption == 0) EncryptionTextField( - enabled: enabled, - controller: privateKeyPathController, - icon: Icons.description_rounded, - onChanged: (value) { - setState(() => privateKeyPathError = validatePath(context, value)); - onEditValidate(); - }, - label: AppLocalizations.of(context)!.privateKeyPath, - errorText: privateKeyPathError, - ), - if (privateKeyOption == 1) EncryptionTextField( - enabled: enabled == true - ? !usePreviouslySavedKey - : false, - controller: pastePrivateKeyController, - icon: Icons.description_rounded, - onChanged: (value) { - setState(() => pastePrivateKeyError = validatePrivateKey(context, value)); - onEditValidate(); - }, - label: AppLocalizations.of(context)!.pastePrivateKey, - errorText: pastePrivateKeyError, - keyboardType: TextInputType.multiline, - multiline: true, - ), - const SizedBox(height: 20), - if (certKeyValid != null && (privateKeyPathController.text != '' || pastePrivateKeyController.text != '' || usePreviouslySavedKey == true)) ...[ - if (certKeyValid!.validKey != null) ...[ - Status( - valid: certKeyValid!.validKey ?? false, - label: certKeyValid!.validKey == true - ? AppLocalizations.of(context)!.validPrivateKey - : AppLocalizations.of(context)!.invalidPrivateKey, + if (privateKeyOption == 0) const SizedBox(height: 10), + if (privateKeyOption == 1) ...[ + CustomSwitchListTile( + value: usePreviouslySavedKey, + onChanged: (value) => setState(() => usePreviouslySavedKey = value), + title: AppLocalizations.of(context)!.usePreviousKey, ), const SizedBox(height: 10) ], - if (certKeyValid!.validPair != null && certKeyValid!.validPair == false) ...[ - Status( - valid: false, - label: AppLocalizations.of(context)!.keysNotMatch, - ), - const SizedBox(height: 10) - ], - if (certKeyValid!.keyType != null) ...[ - Status( - valid: true, - label: "${AppLocalizations.of(context)!.keyType}: ${certKeyValid!.keyType}" - ), - const SizedBox(height: 10), - ], - const SizedBox(height: 10) - ] - ], - ); - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, + if (privateKeyOption == 0) EncryptionTextField( + enabled: enabled, + controller: privateKeyPathController, + icon: Icons.description_rounded, + onChanged: (value) { + setState(() => privateKeyPathError = validatePath(context, value)); + onEditValidate(); + }, + label: AppLocalizations.of(context)!.privateKeyPath, + errorText: privateKeyPathError, ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.encryptionSettingsNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) + if (privateKeyOption == 1) EncryptionTextField( + enabled: enabled == true + ? !usePreviouslySavedKey + : false, + controller: pastePrivateKeyController, + icon: Icons.description_rounded, + onChanged: (value) { + setState(() => pastePrivateKeyError = validatePrivateKey(context, value)); + onEditValidate(); + }, + label: AppLocalizations.of(context)!.pastePrivateKey, + errorText: pastePrivateKeyError, + keyboardType: TextInputType.multiline, + multiline: true, + ), + const SizedBox(height: 20), + if (certKeyValid != null && (privateKeyPathController.text != '' || pastePrivateKeyController.text != '' || usePreviouslySavedKey == true)) ...[ + if (certKeyValid!.validKey != null) ...[ + Status( + valid: certKeyValid!.validKey ?? false, + label: certKeyValid!.validKey == true + ? AppLocalizations.of(context)!.validPrivateKey + : AppLocalizations.of(context)!.invalidPrivateKey, + ), + const SizedBox(height: 10) + ], + if (certKeyValid!.validPair != null && certKeyValid!.validPair == false) ...[ + Status( + valid: false, + label: AppLocalizations.of(context)!.keysNotMatch, + ), + const SizedBox(height: 10) + ], + if (certKeyValid!.keyType != null) ...[ + Status( + valid: true, + label: "${AppLocalizations.of(context)!.keyType}: ${certKeyValid!.keyType}" + ), + const SizedBox(height: 10), + ], + const SizedBox(height: 10) + ] ], - ), - ); - - default: - return const SizedBox(); - } - }, + ); + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.encryptionSettingsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, + ), ) ); } diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index 20e13e8..74cc752 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -124,173 +124,175 @@ class _GeneralSettingsState extends State { title: Text(AppLocalizations.of(context)!.generalSettings), surfaceTintColor: isDesktop(width) ? Colors.transparent : null, ), - body: ListView( - children: [ - SectionLabel(label: AppLocalizations.of(context)!.home), - CustomListTile( - icon: Icons.exposure_zero_rounded, - title: AppLocalizations.of(context)!.hideZeroValues, - subtitle: AppLocalizations.of(context)!.hideZeroValuesDescription, - trailing: Switch( - value: appConfigProvider.hideZeroValues, - onChanged: (value) => updateSettings( - newStatus: value, + body: SafeArea( + child: ListView( + children: [ + SectionLabel(label: AppLocalizations.of(context)!.home), + CustomListTile( + icon: Icons.exposure_zero_rounded, + title: AppLocalizations.of(context)!.hideZeroValues, + subtitle: AppLocalizations.of(context)!.hideZeroValuesDescription, + trailing: Switch( + value: appConfigProvider.hideZeroValues, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setHideZeroValues + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.hideZeroValues, function: appConfigProvider.setHideZeroValues ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.hideZeroValues, - function: appConfigProvider.setHideZeroValues - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - CustomListTile( - icon: Icons.show_chart_rounded, - title: AppLocalizations.of(context)!.combinedChart, - subtitle: AppLocalizations.of(context)!.combinedChartDescription, - trailing: Switch( - value: appConfigProvider.combinedChartHome, - onChanged: (value) => updateSettings( - newStatus: value, + CustomListTile( + icon: Icons.show_chart_rounded, + title: AppLocalizations.of(context)!.combinedChart, + subtitle: AppLocalizations.of(context)!.combinedChartDescription, + trailing: Switch( + value: appConfigProvider.combinedChartHome, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setCombinedChartHome + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.combinedChartHome, function: appConfigProvider.setCombinedChartHome ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.combinedChartHome, - function: appConfigProvider.setCombinedChartHome - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - CustomListTile( - icon: Icons.remove_red_eye_rounded, - title: AppLocalizations.of(context)!.hideServerAddress, - subtitle: AppLocalizations.of(context)!.hideServerAddressDescription, - trailing: Switch( - value: appConfigProvider.hideServerAddress, - onChanged: (value) => updateSettings( - newStatus: value, + CustomListTile( + icon: Icons.remove_red_eye_rounded, + title: AppLocalizations.of(context)!.hideServerAddress, + subtitle: AppLocalizations.of(context)!.hideServerAddressDescription, + trailing: Switch( + value: appConfigProvider.hideServerAddress, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setHideServerAddress + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.hideServerAddress, function: appConfigProvider.setHideServerAddress ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.hideServerAddress, - function: appConfigProvider.setHideServerAddress + CustomListTile( + icon: Icons.reorder_rounded, + title: AppLocalizations.of(context)!.topItemsOrder, + subtitle: AppLocalizations.of(context)!.topItemsOrderDescription, + onTap: () => widget.splitView == true + ? SplitView.of(context).push(const ReorderableTopItemsHome()) + : Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const ReorderableTopItemsHome() + ) + ) ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - CustomListTile( - icon: Icons.reorder_rounded, - title: AppLocalizations.of(context)!.topItemsOrder, - subtitle: AppLocalizations.of(context)!.topItemsOrderDescription, - onTap: () => widget.splitView == true - ? SplitView.of(context).push(const ReorderableTopItemsHome()) - : Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const ReorderableTopItemsHome() - ) - ) - ), - CustomListTile( - icon: Icons.donut_large_rounded, - title: AppLocalizations.of(context)!.showTopItemsChart, - subtitle: AppLocalizations.of(context)!.showTopItemsChartDescription, - trailing: Switch( - value: appConfigProvider.showTopItemsChart, - onChanged: (value) => updateSettings( - newStatus: value, + CustomListTile( + icon: Icons.donut_large_rounded, + title: AppLocalizations.of(context)!.showTopItemsChart, + subtitle: AppLocalizations.of(context)!.showTopItemsChartDescription, + trailing: Switch( + value: appConfigProvider.showTopItemsChart, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setShowTopItemsChart + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.showTopItemsChart, function: appConfigProvider.setShowTopItemsChart ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.showTopItemsChart, - function: appConfigProvider.setShowTopItemsChart - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - SectionLabel(label: AppLocalizations.of(context)!.logs), - CustomListTile( - icon: Icons.timer_rounded, - title: AppLocalizations.of(context)!.timeLogs, - subtitle: AppLocalizations.of(context)!.timeLogsDescription, - trailing: Switch( - value: appConfigProvider.showTimeLogs, - onChanged: (value) => updateSettings( - newStatus: value, + SectionLabel(label: AppLocalizations.of(context)!.logs), + CustomListTile( + icon: Icons.timer_rounded, + title: AppLocalizations.of(context)!.timeLogs, + subtitle: AppLocalizations.of(context)!.timeLogsDescription, + trailing: Switch( + value: appConfigProvider.showTimeLogs, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setshowTimeLogs + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.showTimeLogs, function: appConfigProvider.setshowTimeLogs ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.showTimeLogs, - function: appConfigProvider.setshowTimeLogs - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - CustomListTile( - icon: Icons.more, - title: AppLocalizations.of(context)!.ipLogs, - subtitle: AppLocalizations.of(context)!.ipLogsDescription, - trailing: Switch( - value: appConfigProvider.showIpLogs, - onChanged: (value) => updateSettings( - newStatus: value, + CustomListTile( + icon: Icons.more, + title: AppLocalizations.of(context)!.ipLogs, + subtitle: AppLocalizations.of(context)!.ipLogsDescription, + trailing: Switch( + value: appConfigProvider.showIpLogs, + onChanged: (value) => updateSettings( + newStatus: value, + function: appConfigProvider.setShowIpLogs + ), + ), + onTap: () => updateSettings( + newStatus: !appConfigProvider.showIpLogs, function: appConfigProvider.setShowIpLogs ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 16, + right: 10 + ) ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.showIpLogs, - function: appConfigProvider.setShowIpLogs - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), - if ( - !(Platform.isAndroid || Platform.isIOS) || - (Platform.isAndroid && ( - appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || - appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || - appConfigProvider.installationSource == Source.UNKNOWN - )) - ) ...[ - SectionLabel(label: AppLocalizations.of(context)!.application), - CustomListTile( - icon: Icons.system_update_rounded, - title: AppLocalizations.of(context)!.appUpdates, - subtitle: appConfigProvider.appUpdatesAvailable != null - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.usingLatestVersion, - trailing: generateAppUpdateStatus() - ) - ] - ], + if ( + !(Platform.isAndroid || Platform.isIOS) || + (Platform.isAndroid && ( + appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || + appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || + appConfigProvider.installationSource == Source.UNKNOWN + )) + ) ...[ + SectionLabel(label: AppLocalizations.of(context)!.application), + CustomListTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.appUpdates, + subtitle: appConfigProvider.appUpdatesAvailable != null + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.usingLatestVersion, + trailing: generateAppUpdateStatus() + ) + ] + ], + ), ) ); } diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 99f6ad7..793a1c2 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -14,7 +14,7 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class SafeSearchSettingsScreen extends StatefulWidget { - const SafeSearchSettingsScreen({Key? key}) : super(key: key); + const SafeSearchSettingsScreen({super.key}); @override State createState() => _SafeSearchSettingsScreenState(); @@ -123,166 +123,168 @@ class _SafeSearchSettingsScreenState extends State { const SizedBox(width: 8) ], ), - body: Builder( - builder: (context) { - switch (statusProvider.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingSafeSearchSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - return RefreshIndicator( - onRefresh: requestSafeSearchSettings, - child: ListView( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 16, - left: 16, - right: 16, - bottom: 8 - ), - child: Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(28), - child: InkWell( + body: SafeArea( + child: Builder( + builder: (context) { + switch (statusProvider.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingSafeSearchSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + return RefreshIndicator( + onRefresh: requestSafeSearchSettings, + child: ListView( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 16, + left: 16, + right: 16, + bottom: 8 + ), + child: Material( + color: Colors.transparent, borderRadius: BorderRadius.circular(28), - onTap: () => setState(() => generalEnabled = !generalEnabled), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 12 - ), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(28) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Text( - AppLocalizations.of(context)!.enableSafeSearch, - style: const TextStyle( - fontSize: 18 + child: InkWell( + borderRadius: BorderRadius.circular(28), + onTap: () => setState(() => generalEnabled = !generalEnabled), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 12 + ), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(28) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + AppLocalizations.of(context)!.enableSafeSearch, + style: const TextStyle( + fontSize: 18 + ), ), ), - ), - Switch( - value: generalEnabled, - onChanged: (value) => setState(() => generalEnabled = value) - ) - ], + Switch( + value: generalEnabled, + onChanged: (value) => setState(() => generalEnabled = value) + ) + ], + ), ), ), ), ), - ), - CustomCheckboxListTile( - value: bingEnabled, - onChanged: (value) => setState(() => bingEnabled = value), - title: "Bing", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 + CustomCheckboxListTile( + value: bingEnabled, + onChanged: (value) => setState(() => bingEnabled = value), + title: "Bing", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: duckduckgoEnabled, - onChanged: (value) => setState(() => duckduckgoEnabled = value), - title: "DuckDuckGo", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 + CustomCheckboxListTile( + value: duckduckgoEnabled, + onChanged: (value) => setState(() => duckduckgoEnabled = value), + title: "DuckDuckGo", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: googleEnabled, - onChanged: (value) => setState(() => googleEnabled = value), - title: "Google", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 + CustomCheckboxListTile( + value: googleEnabled, + onChanged: (value) => setState(() => googleEnabled = value), + title: "Google", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: pixabayEnabled, - onChanged: (value) => setState(() => pixabayEnabled = value), - title: "Pixabay", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 + CustomCheckboxListTile( + value: pixabayEnabled, + onChanged: (value) => setState(() => pixabayEnabled = value), + title: "Pixabay", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: yandexEnabled, - onChanged: (value) => setState(() => yandexEnabled = value), - title: "Yandex", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 + CustomCheckboxListTile( + value: yandexEnabled, + onChanged: (value) => setState(() => yandexEnabled = value), + title: "Yandex", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, ), - disabled: !generalEnabled, - ), - CustomCheckboxListTile( - value: youtubeEnabled, - onChanged: (value) => setState(() => youtubeEnabled = value), - title: "YouTube", - padding: const EdgeInsets.only( - top: 8, left: 40, right: 40, bottom: 8 + CustomCheckboxListTile( + value: youtubeEnabled, + onChanged: (value) => setState(() => youtubeEnabled = value), + title: "YouTube", + padding: const EdgeInsets.only( + top: 8, left: 40, right: 40, bottom: 8 + ), + disabled: !generalEnabled, ), - disabled: !generalEnabled, - ), - ], - ), - ); - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.safeSearchSettingsNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, + ], + ), + ); + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, ), - ) - ], - ), - ); - - - default: - return const SizedBox(); - } - }, + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.safeSearchSettingsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + + default: + return const SizedBox(); + } + }, + ), ) ); } diff --git a/lib/screens/settings/server_info/server_info.dart b/lib/screens/settings/server_info/server_info.dart index 3032dcf..b15d8e0 100644 --- a/lib/screens/settings/server_info/server_info.dart +++ b/lib/screens/settings/server_info/server_info.dart @@ -51,114 +51,116 @@ class _ServerInformationState extends State { surfaceTintColor: isDesktop(width) ? Colors.transparent : null, centerTitle: false, ), - body: Builder( - builder: (context) { - switch (serverInfo.loadStatus) { - case LoadStatus.loading: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + body: SafeArea( + child: Builder( + builder: (context) { + switch (serverInfo.loadStatus) { + case LoadStatus.loading: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.loadingServerInfo, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + return ListView( children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.loadingServerInfo, + CustomListTile( + title: AppLocalizations.of(context)!.dnsAddresses, + subtitle: AppLocalizations.of(context)!.seeDnsAddresses, + onTap: () { + showModal( + context: context, + builder: (context) => DnsAddressesModal( + dnsAddresses: serverInfo.data!.dnsAddresses + ) + ); + }, + ), + CustomListTile( + title: AppLocalizations.of(context)!.dnsPort, + subtitle: serverInfo.data!.dnsPort.toString(), + ), + CustomListTile( + title: AppLocalizations.of(context)!.httpPort, + subtitle: serverInfo.data!.httpPort.toString(), + ), + CustomListTile( + title: AppLocalizations.of(context)!.protectionEnabled, + subtitle: serverInfo.data!.protectionEnabled == true + ? AppLocalizations.of(context)!.yes + : AppLocalizations.of(context)!.no, + ), + CustomListTile( + title: AppLocalizations.of(context)!.dhcpAvailable, + subtitle: serverInfo.data!.dhcpAvailable == true + ? AppLocalizations.of(context)!.yes + : AppLocalizations.of(context)!.no, + ), + CustomListTile( + title: AppLocalizations.of(context)!.serverRunning, + subtitle: serverInfo.data!.running == true + ? AppLocalizations.of(context)!.yes + : AppLocalizations.of(context)!.no, + ), + CustomListTile( + title: AppLocalizations.of(context)!.serverVersion, + subtitle: serverInfo.data!.version, + ), + CustomListTile( + title: AppLocalizations.of(context)!.serverLanguage, + subtitle: serverInfo.data!.language, + ), + ] + ); + + case LoadStatus.error: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.serverInfoNotLoaded, textAlign: TextAlign.center, style: TextStyle( fontSize: 22, color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - return ListView( - children: [ - CustomListTile( - title: AppLocalizations.of(context)!.dnsAddresses, - subtitle: AppLocalizations.of(context)!.seeDnsAddresses, - onTap: () { - showModal( - context: context, - builder: (context) => DnsAddressesModal( - dnsAddresses: serverInfo.data!.dnsAddresses - ) - ); - }, + ) + ], ), - CustomListTile( - title: AppLocalizations.of(context)!.dnsPort, - subtitle: serverInfo.data!.dnsPort.toString(), - ), - CustomListTile( - title: AppLocalizations.of(context)!.httpPort, - subtitle: serverInfo.data!.httpPort.toString(), - ), - CustomListTile( - title: AppLocalizations.of(context)!.protectionEnabled, - subtitle: serverInfo.data!.protectionEnabled == true - ? AppLocalizations.of(context)!.yes - : AppLocalizations.of(context)!.no, - ), - CustomListTile( - title: AppLocalizations.of(context)!.dhcpAvailable, - subtitle: serverInfo.data!.dhcpAvailable == true - ? AppLocalizations.of(context)!.yes - : AppLocalizations.of(context)!.no, - ), - CustomListTile( - title: AppLocalizations.of(context)!.serverRunning, - subtitle: serverInfo.data!.running == true - ? AppLocalizations.of(context)!.yes - : AppLocalizations.of(context)!.no, - ), - CustomListTile( - title: AppLocalizations.of(context)!.serverVersion, - subtitle: serverInfo.data!.version, - ), - CustomListTile( - title: AppLocalizations.of(context)!.serverLanguage, - subtitle: serverInfo.data!.language, - ), - ] - ); - - case LoadStatus.error: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.serverInfoNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - }, + ); + + default: + return const SizedBox(); + } + }, + ), ) ); } diff --git a/lib/screens/settings/theme_modal.dart b/lib/screens/settings/theme_modal.dart index 4d8f2fe..fac867e 100644 --- a/lib/screens/settings/theme_modal.dart +++ b/lib/screens/settings/theme_modal.dart @@ -14,10 +14,10 @@ class ThemeModal extends StatefulWidget { final int selectedTheme; const ThemeModal({ - Key? key, + super.key, required this.statusBarHeight, required this.selectedTheme, - }) : super(key: key); + }); @override State createState() => _ThemeModalState(); diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index dd91f6e..d1f8d95 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -17,7 +17,7 @@ import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class UpdateScreen extends StatelessWidget { - const UpdateScreen({Key? key}) : super(key: key); + const UpdateScreen({super.key}); @override Widget build(BuildContext context) { @@ -166,33 +166,38 @@ class UpdateScreen extends StatelessWidget { ); } - final changelog = serversProvider.updateAvailable.loadStatus == LoadStatus.loaded && serversProvider.updateAvailable.data!.changelog != null - ? ListView( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text( - "Changelog ${serversProvider.updateAvailable.data!.canAutoupdate == true - ? serversProvider.updateAvailable.data!.newVersion - : serversProvider.updateAvailable.data!.currentVersion}", - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurfaceVariant + final SafeArea? changelog; + if (serversProvider.updateAvailable.loadStatus == LoadStatus.loaded && serversProvider.updateAvailable.data!.changelog != null) { + changelog = SafeArea( + child: ListView( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + "Changelog ${serversProvider.updateAvailable.data!.canAutoupdate == true + ? serversProvider.updateAvailable.data!.newVersion + : serversProvider.updateAvailable.data!.currentVersion}", + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), ), ), - ), - const SizedBox(height: 8), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Html( - data: html.parse(md.markdownToHtml(serversProvider.updateAvailable.data!.changelog!)).outerHtml, - onLinkTap: (url, context, attributes) => url != null ? openUrl(url) : null, + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Html( + data: html.parse(md.markdownToHtml(serversProvider.updateAvailable.data!.changelog!)).outerHtml, + onLinkTap: (url, context, attributes) => url != null ? openUrl(url) : null, + ) ) - ) - ], - ) - : null; + ], + ), + ); + } else { + changelog = null; + } return Scaffold( body: Column( diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index 59e8a55..e30d1e0 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -550,8 +550,10 @@ class _AddServerModalState extends State { const SizedBox(width: 8) ], ), - body: ListView( - children: form() + body: SafeArea( + child: ListView( + children: form() + ), ), ), ); diff --git a/lib/widgets/system_ui_overlay_style.dart b/lib/widgets/system_ui_overlay_style.dart index 83557f1..ab5b8d0 100644 --- a/lib/widgets/system_ui_overlay_style.dart +++ b/lib/widgets/system_ui_overlay_style.dart @@ -5,12 +5,14 @@ class OverlayStyle extends StatelessWidget { final Widget child; const OverlayStyle({ - Key? key, + super.key, required this.child - }) : super(key: key); + }); @override Widget build(BuildContext context) { + final systemGestureInsets = MediaQuery.of(context).systemGestureInsets; + return AnnotatedRegion( value: SystemUiOverlayStyle( statusBarColor: Colors.transparent, @@ -20,7 +22,13 @@ class OverlayStyle extends StatelessWidget { statusBarIconBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light, - systemNavigationBarColor: Theme.of(context).colorScheme.background, + systemNavigationBarColor: systemGestureInsets.left > 0 // If true gestures navigation + ? Colors.transparent + : ElevationOverlay.applySurfaceTint( + Theme.of(context).colorScheme.surface, + Theme.of(context).colorScheme.surfaceTint, + 3 + ), systemNavigationBarIconBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light, diff --git a/lib/widgets/tab_content_list.dart b/lib/widgets/tab_content_list.dart index d1f2ad0..92b7913 100644 --- a/lib/widgets/tab_content_list.dart +++ b/lib/widgets/tab_content_list.dart @@ -19,7 +19,7 @@ class CustomTabContentList extends StatelessWidget { final EdgeInsets? listPadding; const CustomTabContentList({ - Key? key, + super.key, required this.loadingGenerator, required this.itemsCount, required this.contentWidget, @@ -32,7 +32,7 @@ class CustomTabContentList extends StatelessWidget { this.fabVisible, this.noSliver, this.listPadding - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -49,7 +49,6 @@ class CustomTabContentList extends StatelessWidget { else { return SafeArea( top: false, - bottom: false, child: Builder( builder: (BuildContext context) => CustomScrollView( slivers: [ @@ -72,41 +71,45 @@ class CustomTabContentList extends StatelessWidget { case LoadStatus.loaded: if (noSliver == true) { if (itemsCount > 0) { - return Stack( - children: [ - ListView.builder( - padding: listPadding, - itemCount: itemsCount, - itemBuilder: (context, index) => contentWidget(index), - ), - if (fab != null) AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: fabVisible != null && fabVisible == true ? - appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, - right: 20, - child: fab! - ), - ], + return SafeArea( + child: Stack( + children: [ + ListView.builder( + padding: listPadding, + itemCount: itemsCount, + itemBuilder: (context, index) => contentWidget(index), + ), + if (fab != null) AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: fabVisible != null && fabVisible == true ? + appConfigProvider.showingSnackbar + ? 70 : 20 + : -70, + right: 20, + child: fab! + ), + ], + ), ); } else { - return Stack( - children: [ - noData, - if (fab != null) AnimatedPositioned( - duration: const Duration(milliseconds: 100), - curve: Curves.easeInOut, - bottom: fabVisible != null && fabVisible == true ? - appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, - right: 20, - child: fab! - ), - ], + return SafeArea( + child: Stack( + children: [ + noData, + if (fab != null) AnimatedPositioned( + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + bottom: fabVisible != null && fabVisible == true ? + appConfigProvider.showingSnackbar + ? 70 : 20 + : -70, + right: 20, + child: fab! + ), + ], + ), ); } } @@ -146,10 +149,10 @@ class CustomTabContentList extends StatelessWidget { curve: Curves.easeInOut, bottom: fabVisible != null && fabVisible == true ? appConfigProvider.showingSnackbar - ? 70 : 20 - : -70, + ? 90 : 20 + : -90, right: 20, - child: fab! + child: SafeArea(child: fab!) ), ], ); @@ -169,7 +172,6 @@ class CustomTabContentList extends StatelessWidget { else { return SafeArea( top: false, - bottom: false, child: Builder( builder: (BuildContext context) => CustomScrollView( slivers: [ From 33611cb89594e6405c52ece0f0165fa1e1ecc834 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Dec 2023 04:06:35 +0100 Subject: [PATCH 451/676] Improvements --- lib/screens/settings/encryption/encryption.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index e11047e..28c1d95 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -82,10 +82,10 @@ class _EncryptionSettingsState extends State { final result = await Provider.of(context, listen: false).apiClient2!.getEncryptionSettings(); if (!mounted) return; - - final data = result.content as EncryptionData; if (result.successful == true) { + final data = result.content as EncryptionData; + await checkValidDataApi(data: data.toJson()); if (!mounted) return; From 5a12c4c11186a1c99b832d4e675b9e3dabef378e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Dec 2023 04:07:47 +0100 Subject: [PATCH 452/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 32d01fc..1ad22e1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.12.3+114 +version: 2.12.4+115 environment: sdk: '>=2.18.1 <3.0.0' From c1e2a796af498233b8a09d19c6939be76dd5ac2d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 13:33:01 +0100 Subject: [PATCH 453/676] Add refresh button desktop --- lib/screens/home/appbar.dart | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 365e606..52ff350 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -16,9 +18,9 @@ class HomeAppBar extends StatelessWidget { final bool innerBoxScrolled; const HomeAppBar({ - Key? key, + super.key, required this.innerBoxScrolled - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -118,6 +120,14 @@ class HomeAppBar extends StatelessWidget { ], ), actions: [ + if (!(Platform.isAndroid || Platform.isIOS)) ...[ + IconButton( + onPressed: () => statusProvider.getServerStatus(), + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ), + const SizedBox(width: 8), + ], PopupMenuButton( itemBuilder: (context) => [ PopupMenuItem( From 3aa36c89aaa4e1ffb57e1521a62d2e2b11c7bd51 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 13:54:47 +0100 Subject: [PATCH 454/676] Added reset encryption settings --- lib/l10n/app_en.arb | 7 +- lib/l10n/app_es.arb | 7 +- .../settings/encryption/encryption.dart | 78 ++++++++++++++++--- .../encryption/reset_settings_modal.dart | 52 +++++++++++++ 4 files changed, 130 insertions(+), 14 deletions(-) create mode 100644 lib/screens/settings/encryption/reset_settings_modal.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index fb875cc..11f04c3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -690,5 +690,10 @@ "topUpstreams": "Top upstreams", "averageUpstreamResponseTime": "Average upstream response time", "dhcpNotAvailable": "The DHCP server is not available.", - "osServerInstalledIncompatible": "The OS where the server is installed is not compatible with this feature." + "osServerInstalledIncompatible": "The OS where the server is installed is not compatible with this feature.", + "resetSettings": "Reset settings", + "resetEncryptionSettingsDescription": "Are you sure you want to reset to default values the encryption settings?", + "resettingConfig": "Resetting configuration...", + "configurationResetSuccessfully": "Configuration resetted successfully", + "configurationResetError": "The configuration couldn't be resetted" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index cf328dc..94f4299 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -690,5 +690,10 @@ "topUpstreams": "DNS de subida más frecuentes", "averageUpstreamResponseTime": "Tiempo promedio de respuesta upstream", "dhcpNotAvailable": "El servidor DHCP no está disponible.", - "osServerInstalledIncompatible": "El SO donde el servidor está instalado no es compatible con esta característica." + "osServerInstalledIncompatible": "El SO donde el servidor está instalado no es compatible con esta característica.", + "resetSettings": "Resetear configuración", + "resetEncryptionSettingsDescription": "Estás seguro que deseas restaurar a valores por defecto la configuración de encriptación?", + "resettingConfig": "Reseteando configuración...", + "configurationResetSuccessfully": "Configuración reseteada correctamente", + "configurationResetError": "La configuración no ha podido ser reseteada" } \ No newline at end of file diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 28c1d95..1efdad4 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -6,8 +6,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; -import 'package:adguard_home_manager/screens/settings/encryption/config_error_modal.dart'; import 'package:adguard_home_manager/screens/settings/encryption/status.dart'; +import 'package:adguard_home_manager/screens/settings/encryption/reset_settings_modal.dart'; import 'package:adguard_home_manager/screens/settings/encryption/custom_text_field.dart'; import 'package:adguard_home_manager/screens/settings/encryption/master_switch.dart'; import 'package:adguard_home_manager/screens/settings/encryption/encryption_functions.dart'; @@ -254,6 +254,45 @@ class _EncryptionSettingsState extends State { } } + void resetSettings() async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.resettingConfig); + + final result = await serversProvider.apiClient2!.saveEncryptionSettings( + data: { + "enabled": false, + "server_name": "", + "force_https": false, + "port_https": 443, + "port_dns_over_tls": 853, + "port_dns_over_quic": 853, + "certificate_chain": "", + "private_key": "", + "private_key_saved": false, + "certificate_path": "", + "private_key_path": "", + } + ); + if (!mounted) return; + + processModal.close(); + + if (result.successful == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.configurationResetSuccessfully, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.configurationResetError, + color: Colors.red + ); + } + } + return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.encryptionSettings), @@ -261,17 +300,12 @@ class _EncryptionSettingsState extends State { centerTitle: false, actions: [ IconButton( - onPressed: certKeyValidApi == 2 && (validDataError != null || encryptionResultMessage != null) - ? () => { - showDialog( - context: context, - builder: (context) => EncryptionErrorModal( - error: validDataError ?? encryptionResultMessage ?? AppLocalizations.of(context)!.unknownError - ) - ) - } : null, - icon: generateStatus(context, appConfigProvider, localValidationValid, certKeyValidApi, formEdited), - tooltip: generateStatusString(context, localValidationValid, certKeyValidApi) + onPressed: () => showDialog( + context: context, + builder: (ctx) => ResetSettingsModal(onConfirm: resetSettings) + ), + icon: const Icon(Icons.restore_rounded), + tooltip: AppLocalizations.of(context)!.resetSettings, ), IconButton( onPressed: localValidationValid ? @@ -311,6 +345,26 @@ class _EncryptionSettingsState extends State { case LoadStatus.loaded: return ListView( children: [ + if (certKeyValidApi == 2 && (validDataError != null || encryptionResultMessage != null)) Card( + margin: const EdgeInsets.all(16), + color: Colors.red.withOpacity(0.2), + elevation: 0, + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.error_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 16), + Expanded( + child: Text(validDataError ?? encryptionResultMessage ?? AppLocalizations.of(context)!.unknownError) + ) + ], + ), + ), + ), EncryptionMasterSwitch( value: enabled, onChange: (value) { diff --git a/lib/screens/settings/encryption/reset_settings_modal.dart b/lib/screens/settings/encryption/reset_settings_modal.dart new file mode 100644 index 0000000..4429162 --- /dev/null +++ b/lib/screens/settings/encryption/reset_settings_modal.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class ResetSettingsModal extends StatelessWidget { + final void Function() onConfirm; + + const ResetSettingsModal({ + super.key, + required this.onConfirm, + }); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Column( + children: [ + Icon( + Icons.restore_rounded, + size: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.resetSettings, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: Text( + AppLocalizations.of(context)!.resetEncryptionSettingsDescription, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + TextButton( + onPressed: () { + onConfirm(); + Navigator.pop(context); + }, + child: Text(AppLocalizations.of(context)!.confirm) + ), + ], + ); + } +} \ No newline at end of file From c3f55e9ce9c6a9d586b1aaf9916a44986bbd6873 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 14:29:08 +0100 Subject: [PATCH 455/676] Added test upstream dns servers --- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/screens/settings/dns/dns.dart | 9 + .../settings/dns/test_upstream_dns_modal.dart | 168 ++++++++++++++++++ lib/screens/settings/dns/upstream_dns.dart | 2 +- lib/services/api_client.dart | 14 ++ 6 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 lib/screens/settings/dns/test_upstream_dns_modal.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 11f04c3..1e9271d 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -695,5 +695,7 @@ "resetEncryptionSettingsDescription": "Are you sure you want to reset to default values the encryption settings?", "resettingConfig": "Resetting configuration...", "configurationResetSuccessfully": "Configuration resetted successfully", - "configurationResetError": "The configuration couldn't be resetted" + "configurationResetError": "The configuration couldn't be resetted", + "testUpstreamDnsServers": "Test upstream DNS servers", + "errorTestUpstreamDns": "Error when testing upstream DNS servers." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 94f4299..f649320 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -695,5 +695,7 @@ "resetEncryptionSettingsDescription": "Estás seguro que deseas restaurar a valores por defecto la configuración de encriptación?", "resettingConfig": "Reseteando configuración...", "configurationResetSuccessfully": "Configuración reseteada correctamente", - "configurationResetError": "La configuración no ha podido ser reseteada" + "configurationResetError": "La configuración no ha podido ser reseteada", + "testUpstreamDnsServers": "Probar servidores DNS de subida", + "errorTestUpstreamDns": "Error al probar los servidores DNS de subida." } \ No newline at end of file diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 2c711d6..c22572d 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -5,6 +5,7 @@ import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/settings/dns/test_upstream_dns_modal.dart'; import 'package:adguard_home_manager/screens/settings/dns/clear_dns_cache_dialog.dart'; import 'package:adguard_home_manager/screens/settings/dns/cache_config.dart'; import 'package:adguard_home_manager/screens/settings/dns/dns_server_settings.dart'; @@ -84,6 +85,14 @@ class _DnsSettingsState extends State { title: Text(AppLocalizations.of(context)!.dnsSettings), surfaceTintColor: isDesktop(width) ? Colors.transparent : null, actions: [ + IconButton( + onPressed: () => showDialog( + context: context, + builder: (ctx) => const TestUpstreamDnsModal() + ), + icon: const Icon(Icons.upload_rounded), + tooltip: AppLocalizations.of(context)!.testUpstreamDnsServers, + ), PopupMenuButton( itemBuilder: (context) => [ PopupMenuItem( diff --git a/lib/screens/settings/dns/test_upstream_dns_modal.dart b/lib/screens/settings/dns/test_upstream_dns_modal.dart new file mode 100644 index 0000000..8410334 --- /dev/null +++ b/lib/screens/settings/dns/test_upstream_dns_modal.dart @@ -0,0 +1,168 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class _Item { + final String url; + final bool value; + + const _Item({ + required this.url, + required this.value + }); +} + +class TestUpstreamDnsModal extends StatefulWidget { + const TestUpstreamDnsModal({super.key}); + + @override + State createState() => _TestUpstreamDnsModalState(); +} + +class _TestUpstreamDnsModalState extends State { + LoadStatus loadStatus = LoadStatus.loading; + List<_Item>? values; + + void checkDns() async { + final dnsProvider = Provider.of(context, listen: false); + final result = await Provider.of(context, listen: false).apiClient2!.testUpstreamDns( + body: { + "bootstrap_dns": dnsProvider.dnsInfo!.bootstrapDns, + "fallback_dns": [], + "private_upstream": dnsProvider.dnsInfo!.defaultLocalPtrUpstreams, + "upstream_dns": dnsProvider.dnsInfo!.upstreamDns + } + ); + if (!mounted) return; + if (result.successful == true) { + setState(() { + values = List<_Item>.from( + (result.content as Map).entries.map((e) => _Item( + url: e.key, + value: e.value == "OK" ? true : false + )) + ); + loadStatus = LoadStatus.loaded; + }); + } + else { + setState(() => loadStatus = LoadStatus.error); + } + } + + @override + void initState() { + checkDns(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Column( + children: [ + Icon( + Icons.upload_rounded, + size: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.testUpstreamDnsServers, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Builder( + builder: (context) { + switch (loadStatus) { + case LoadStatus.loading: + return const Padding( + padding: EdgeInsets.symmetric(vertical: 16), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + CircularProgressIndicator() + ], + ), + ); + + case LoadStatus.loaded: + return SingleChildScrollView( + child: Wrap( + children: values!.map((v) => Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + v.url, + overflow: TextOverflow.ellipsis, + ), + ), + ...[ + const SizedBox(width: 8), + if (v.value == true) const Icon( + Icons.check_circle_rounded, + color: Colors.green, + size: 16, + ), + if (v.value == false) const Icon( + Icons.cancel_rounded, + color: Colors.red, + ) + ] + ], + ), + )).toList(), + ), + ); + + case LoadStatus.error: + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.error_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + size: 30, + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.errorTestUpstreamDns, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ); + + default: + return const SizedBox(); + } + }, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close) + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index f952110..e540053 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -186,7 +186,7 @@ class _UpstreamDnsScreenState extends State { icon: const Icon(Icons.save_rounded), tooltip: AppLocalizations.of(context)!.save, ), - const SizedBox(width: 10) + const SizedBox(width: 8) ], ), body: SafeArea( diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index f626f75..c2e1fca 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -853,4 +853,18 @@ class ApiClientV2 { ); return ApiResponse(successful: result.successful); } + + Future testUpstreamDns({ + required Map body + }) async { + final result = await HttpRequestClient.post( + urlPath: '/test_upstream_dns', + server: server, + body: body + ); + return ApiResponse( + successful: result.successful, + content: result.body != null ? jsonDecode(result.body!) : null + ); + } } \ No newline at end of file From 6973eae0dea7608bd849f1a92dfdaaf2090eefdf Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 15:48:01 +0100 Subject: [PATCH 456/676] Added custom ip edns field --- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/models/dns_info.dart | 8 ++ .../settings/dns/dns_server_settings.dart | 96 ++++++++++++++++++- 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 1e9271d..15da154 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -697,5 +697,7 @@ "configurationResetSuccessfully": "Configuration resetted successfully", "configurationResetError": "The configuration couldn't be resetted", "testUpstreamDnsServers": "Test upstream DNS servers", - "errorTestUpstreamDns": "Error when testing upstream DNS servers." + "errorTestUpstreamDns": "Error when testing upstream DNS servers.", + "useCustomIpEdns": "Use custom IP for EDNS", + "useCustomIpEdnsDescription": "Allow to use custom IP for EDNS" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index f649320..c226a91 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -697,5 +697,7 @@ "configurationResetSuccessfully": "Configuración reseteada correctamente", "configurationResetError": "La configuración no ha podido ser reseteada", "testUpstreamDnsServers": "Probar servidores DNS de subida", - "errorTestUpstreamDns": "Error al probar los servidores DNS de subida." + "errorTestUpstreamDns": "Error al probar los servidores DNS de subida.", + "useCustomIpEdns": "Usar IP personalizada para EDNS", + "useCustomIpEdnsDescription": "Permitir usar IP personalizada para EDNS" } \ No newline at end of file diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 4e85400..0d3aa83 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -6,6 +6,8 @@ class DnsInfo { int ratelimit; String blockingMode; bool ednsCsEnabled; + bool? ednsCsUseCustom; + String? ednsCsCustomIp; bool dnssecEnabled; bool disableIpv6; String? upstreamMode; @@ -28,6 +30,8 @@ class DnsInfo { required this.ratelimit, required this.blockingMode, required this.ednsCsEnabled, + required this.ednsCsUseCustom, + required this.ednsCsCustomIp, required this.dnssecEnabled, required this.disableIpv6, required this.upstreamMode, @@ -51,6 +55,8 @@ class DnsInfo { ratelimit: json["ratelimit"], blockingMode: json["blocking_mode"], ednsCsEnabled: json["edns_cs_enabled"], + ednsCsUseCustom: json["edns_cs_use_custom"], + ednsCsCustomIp: json["edns_cs_custom_ip"], dnssecEnabled: json["dnssec_enabled"], disableIpv6: json["disable_ipv6"], upstreamMode: json["upstream_mode"], @@ -74,6 +80,8 @@ class DnsInfo { "ratelimit": ratelimit, "blocking_mode": blockingMode, "edns_cs_enabled": ednsCsEnabled, + "edns_cs_use_custom": ednsCsUseCustom, + "edns_cs_custom_ip": ednsCsCustomIp, "dnssec_enabled": dnssecEnabled, "disable_ipv6": disableIpv6, "upstream_mode": upstreamMode, diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index 4cc650a..19f6c09 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -1,5 +1,6 @@ // ignore_for_file: use_build_context_synchronously +import 'package:expandable/expandable.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -24,7 +25,12 @@ class DnsServerSettingsScreen extends StatefulWidget { class _DnsServerSettingsScreenState extends State { final TextEditingController limitRequestsController = TextEditingController(); String? limitRequestsError; + final _expandableCustomEdns = ExpandableController(); + final _expandableEdnsIp = ExpandableController(); bool enableEdns = false; + bool useCustomIpEdns = false; + final _customIpEdnsController = TextEditingController(); + String? ednsIpError; bool enableDnssec = false; bool disableIpv6Resolving = false; @@ -48,6 +54,17 @@ class _DnsServerSettingsScreenState extends State { validateData(); } + void validateEdns(String value) { + RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); + if (ipAddress.hasMatch(value) == true) { + setState(() => ednsIpError = null); + } + else { + setState(() => ednsIpError = AppLocalizations.of(context)!.ipNotValid); + } + validateData(); + } + void validateIpv6(String value) { RegExp ipAddress = RegExp(r'(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$)'); if (ipAddress.hasMatch(value) == true) { @@ -72,7 +89,8 @@ class _DnsServerSettingsScreenState extends State { ipv6controller.text != '' && ipv6error == null ) - ) == true + ) == true && + ednsIpError == null ) { setState(() => isDataValid = true); } @@ -87,6 +105,10 @@ class _DnsServerSettingsScreenState extends State { limitRequestsController.text = dnsProvider.dnsInfo!.ratelimit.toString(); enableEdns = dnsProvider.dnsInfo!.ednsCsEnabled; + useCustomIpEdns = dnsProvider.dnsInfo!.ednsCsUseCustom ?? false; + _customIpEdnsController.text = dnsProvider.dnsInfo!.ednsCsCustomIp ?? ""; + if (dnsProvider.dnsInfo!.ednsCsEnabled == true) _expandableCustomEdns.toggle(); + if (dnsProvider.dnsInfo!.ednsCsUseCustom == true) _expandableEdnsIp.toggle(); enableDnssec = dnsProvider.dnsInfo!.dnssecEnabled; disableIpv6Resolving = dnsProvider.dnsInfo!.disableIpv6; blockingMode = dnsProvider.dnsInfo!.blockingMode; @@ -109,6 +131,8 @@ class _DnsServerSettingsScreenState extends State { final result = await dnsProvider.saveDnsServerConfig({ "ratelimit": int.parse(limitRequestsController.text), "edns_cs_enabled": enableEdns, + "edns_cs_use_custom": useCustomIpEdns, + "edns_cs_custom_ip": _customIpEdnsController.text, "dnssec_enabled": enableDnssec, "disable_ipv6": disableIpv6Resolving, "blocking_mode": blockingMode, @@ -200,10 +224,78 @@ class _DnsServerSettingsScreenState extends State { const SizedBox(height: 10), CustomSwitchListTile( value: enableEdns, - onChanged: (value) => setState(() => enableEdns = value), + onChanged: (value) => setState(() { + enableEdns = value; + _expandableCustomEdns.toggle(); + if (value == false) { + useCustomIpEdns = false; + if (_expandableEdnsIp.expanded == true) _expandableEdnsIp.toggle(); + _customIpEdnsController.text = ""; + ednsIpError = null; + } + validateData(); + }), title: AppLocalizations.of(context)!.enableEdns, subtitle: AppLocalizations.of(context)!.enableEdnsDescription, ), + ExpandableNotifier( + controller: _expandableCustomEdns, + child: Expandable( + collapsed: const SizedBox(), + expanded: Column( + children: [ + CustomSwitchListTile( + padding: const EdgeInsets.only( + left: 50, + top: 12, + bottom: 12, + right: 16 + ), + value: useCustomIpEdns, + onChanged: (value) => setState(() { + useCustomIpEdns = value; + _expandableEdnsIp.toggle(); + if (useCustomIpEdns == false) { + _customIpEdnsController.text = ""; + ednsIpError = null; + } + validateData(); + }), + title: AppLocalizations.of(context)!.useCustomIpEdns, + subtitle: AppLocalizations.of(context)!.useCustomIpEdnsDescription, + ), + ExpandableNotifier( + controller: _expandableEdnsIp, + child: Expandable( + collapsed: const SizedBox(), + expanded: Padding( + padding: const EdgeInsets.only( + top: 16, + bottom: 16, + right: 16, + left: 70 + ), + child: TextFormField( + controller: _customIpEdnsController, + onChanged: validateEdns, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: ednsIpError, + labelText: AppLocalizations.of(context)!.ipAddress, + ), + ), + ), + ) + ), + ], + ), + ) + ), CustomSwitchListTile( value: enableDnssec, onChanged: (value) => setState(() => enableDnssec = value), From c3530f17abfd403cd4a63f194672f25972337478 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 18:32:28 +0100 Subject: [PATCH 457/676] Sort top items --- lib/l10n/app_en.arb | 5 +- lib/l10n/app_es.arb | 5 +- .../home/top_items/top_items_screen.dart | 58 ++++++++++++++++++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 15da154..2ae59bf 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -699,5 +699,8 @@ "testUpstreamDnsServers": "Test upstream DNS servers", "errorTestUpstreamDns": "Error when testing upstream DNS servers.", "useCustomIpEdns": "Use custom IP for EDNS", - "useCustomIpEdnsDescription": "Allow to use custom IP for EDNS" + "useCustomIpEdnsDescription": "Allow to use custom IP for EDNS", + "sortingOptions": "Sorting options", + "fromHighestToLowest": "From highest to lowest", + "fromLowestToHighest": "From lowest to highest" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index c226a91..1917370 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -699,5 +699,8 @@ "testUpstreamDnsServers": "Probar servidores DNS de subida", "errorTestUpstreamDns": "Error al probar los servidores DNS de subida.", "useCustomIpEdns": "Usar IP personalizada para EDNS", - "useCustomIpEdnsDescription": "Permitir usar IP personalizada para EDNS" + "useCustomIpEdnsDescription": "Permitir usar IP personalizada para EDNS", + "sortingOptions": "Opciones de ordenación", + "fromHighestToLowest": "De mayor a menor", + "fromLowestToHighest": "De menor a mayor" } \ No newline at end of file diff --git a/lib/screens/home/top_items/top_items_screen.dart b/lib/screens/home/top_items/top_items_screen.dart index 7e7e623..f2f9b4d 100644 --- a/lib/screens/home/top_items/top_items_screen.dart +++ b/lib/screens/home/top_items/top_items_screen.dart @@ -15,6 +15,8 @@ import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; +enum _SortingOptions { highestToLowest, lowestToHighest } + class TopItemsScreen extends StatefulWidget { final HomeTopItems type; final String title; @@ -44,6 +46,7 @@ class TopItemsScreen extends StatefulWidget { } class _TopItemsScreenState extends State { + _SortingOptions _sortingOptions = _SortingOptions.highestToLowest; bool searchActive = false; final TextEditingController searchController = TextEditingController(); @@ -68,6 +71,10 @@ class _TopItemsScreenState extends State { for (var element in data) { total = total + double.parse(element.values.toList()[0].toString()); } + + final sortedValues = _sortingOptions == _SortingOptions.lowestToHighest + ? screenData.reversed.toList() + : screenData.toList(); if (widget.isFullscreen == true) { return Dialog.fullscreen( @@ -119,6 +126,53 @@ class _TopItemsScreenState extends State { icon: const Icon(Icons.clear_rounded), tooltip: AppLocalizations.of(context)!.clearSearch, ), + PopupMenuButton( + icon: const Icon(Icons.sort_rounded), + itemBuilder: (context) => [ + PopupMenuItem( + onTap: () => setState(() => _sortingOptions = _SortingOptions.highestToLowest), + child: Row( + children: [ + const Icon(Icons.arrow_downward_rounded), + const SizedBox(width: 8), + Expanded( + child: Text(AppLocalizations.of(context)!.fromHighestToLowest) + ), + const SizedBox(width: 16), + Icon( + _sortingOptions == _SortingOptions.highestToLowest + ? Icons.radio_button_checked_rounded + : Icons.radio_button_unchecked_rounded, + color: _sortingOptions == _SortingOptions.highestToLowest + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant, + ) + ], + ) + ), + PopupMenuItem( + onTap: () => setState(() => _sortingOptions = _SortingOptions.lowestToHighest), + child: Row( + children: [ + const Icon(Icons.arrow_upward_rounded), + const SizedBox(width: 8), + Expanded( + child: Text(AppLocalizations.of(context)!.fromLowestToHighest) + ), + const SizedBox(width: 16), + Icon( + _sortingOptions == _SortingOptions.lowestToHighest + ? Icons.radio_button_checked_rounded + : Icons.radio_button_unchecked_rounded, + color: _sortingOptions == _SortingOptions.lowestToHighest + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant, + ) + ], + ) + ), + ], + ), const SizedBox(width: 8) ], ), @@ -128,7 +182,7 @@ class _TopItemsScreenState extends State { isClient: widget.isClient, onTapEntry: widget.onTapEntry, options: widget.options, - screenData: screenData, + screenData: sortedValues, total: total, withProgressBar: widget.withProgressBar, ), @@ -193,7 +247,7 @@ class _TopItemsScreenState extends State { isClient: widget.isClient, onTapEntry: widget.onTapEntry, options: widget.options, - screenData: screenData, + screenData: sortedValues, total: total, withProgressBar: widget.withProgressBar, ), From cc12a8504eb667fa3b6ff245cc2c096b1d3b1024 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 21:49:47 +0100 Subject: [PATCH 458/676] Added client queries and statistics settings --- lib/l10n/app_en.arb | 6 +++- lib/l10n/app_es.arb | 6 +++- lib/models/clients.dart | 10 +++++- lib/screens/clients/added_list.dart | 6 ++-- lib/screens/clients/client/client_form.dart | 31 +++++++++++++++++++ lib/screens/clients/client/client_screen.dart | 17 +++++++++- 6 files changed, 69 insertions(+), 7 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 2ae59bf..1a4cdb4 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -702,5 +702,9 @@ "useCustomIpEdnsDescription": "Allow to use custom IP for EDNS", "sortingOptions": "Sorting options", "fromHighestToLowest": "From highest to lowest", - "fromLowestToHighest": "From lowest to highest" + "fromLowestToHighest": "From lowest to highest", + "queryLogsAndStatistics": "Query logs and statistics", + "ignoreClientQueryLog": "Ignore this client in query log", + "ignoreClientStatistics": "Ignore this client in statistics", + "savingChanges": "Saving changes..." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 1917370..e0e57c1 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -702,5 +702,9 @@ "useCustomIpEdnsDescription": "Permitir usar IP personalizada para EDNS", "sortingOptions": "Opciones de ordenación", "fromHighestToLowest": "De mayor a menor", - "fromLowestToHighest": "De menor a mayor" + "fromLowestToHighest": "De menor a mayor", + "queryLogsAndStatistics": "Registro de consultas y estadísticas", + "ignoreClientQueryLog": "Ignorar este cliente en el registro de consultas", + "ignoreClientStatistics": "Ignorar este cliente en las estadísticas", + "savingChanges": "Guardando cambios..." } \ No newline at end of file diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 1472a0f..5808391 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -87,6 +87,8 @@ class Client { final bool useGlobalBlockedServices; final bool useGlobalSettings; final SafeSearch? safeSearch; + final bool? ignoreQuerylog; + final bool? ignoreStatistics; Client({ required this.name, @@ -100,6 +102,8 @@ class Client { required this.useGlobalBlockedServices, required this.useGlobalSettings, required this.safeSearch, + required this.ignoreQuerylog, + required this.ignoreStatistics, }); factory Client.fromJson(Map json) => Client( @@ -115,7 +119,9 @@ class Client { useGlobalSettings: json["use_global_settings"], safeSearch: json["safe_search"] != null ? SafeSearch.fromJson(json["safe_search"]) - : null + : null, + ignoreQuerylog: json["ignore_querylog"], + ignoreStatistics: json["ignore_statistics"] ); Map toJson() => { @@ -130,5 +136,7 @@ class Client { "safe_search": safeSearch, "use_global_blocked_services": useGlobalBlockedServices, "use_global_settings": useGlobalSettings, + "ignore_querylog": ignoreQuerylog, + "ignore_statistics": ignoreStatistics, }; } \ No newline at end of file diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 0a0bc08..aa86785 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -29,13 +29,13 @@ class AddedList extends StatefulWidget { final bool splitView; const AddedList({ - Key? key, + super.key, required this.scrollController, required this.data, required this.onClientSelected, this.selectedClient, required this.splitView - }) : super(key: key); + }); @override State createState() => _AddedListState(); @@ -75,7 +75,7 @@ class _AddedListState extends State { void confirmEditClient(Client client) async { ProcessModal processModal = ProcessModal(); - processModal.open(AppLocalizations.of(context)!.addingClient); + processModal.open(AppLocalizations.of(context)!.savingChanges); final result = await clientsProvider.editClient(client); diff --git a/lib/screens/clients/client/client_form.dart b/lib/screens/clients/client/client_form.dart index 2151288..5c164af 100644 --- a/lib/screens/clients/client/client_form.dart +++ b/lib/screens/clients/client/client_form.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -45,6 +46,10 @@ class ClientForm extends StatelessWidget { final void Function(bool) updateEnableSafeSearch; final void Function(SafeSearch) updateSafeSearch; final void Function(bool) updateUseGlobalSettingsServices; + final bool ignoreClientQueryLog; + final void Function(bool) updateIgnoreClientQueryLog; + final bool ignoreClientStatistics; + final void Function(bool) updateIgnoreClientStatistics; const ClientForm({ super.key, @@ -75,6 +80,10 @@ class ClientForm extends StatelessWidget { required this.updateEnableSafeSearch, required this.updateSafeSearch, required this.updateUseGlobalSettingsServices, + required this.ignoreClientQueryLog, + required this.ignoreClientStatistics, + required this.updateIgnoreClientQueryLog, + required this.updateIgnoreClientStatistics, }); @override @@ -217,6 +226,28 @@ class ClientForm extends StatelessWidget { ) : null, ), + SectionLabel( + label: AppLocalizations.of(context)!.queryLogsAndStatistics, + padding: const EdgeInsets.all(24), + ), + CustomSwitchListTile( + title: AppLocalizations.of(context)!.ignoreClientQueryLog, + value: ignoreClientQueryLog, + onChanged: updateIgnoreClientQueryLog, + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 4 + ), + ), + CustomSwitchListTile( + title: AppLocalizations.of(context)!.ignoreClientStatistics, + value: ignoreClientStatistics, + onChanged: updateIgnoreClientStatistics, + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 4 + ), + ), SectionLabel( label: AppLocalizations.of(context)!.blockedServices, padding: const EdgeInsets.all(24), diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index d4628e7..9a16e1a 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -73,6 +73,9 @@ class _ClientScreenState extends State { List upstreamServers = []; + bool _ignoreClientQueryLog = false; + bool _ignoreClientStatistics = false; + void enableDisableGlobalSettingsFiltering() { if (useGlobalSettingsFiltering == true) { setState(() { @@ -120,6 +123,8 @@ class _ClientScreenState extends State { id: uuid.v4(), controller: TextEditingController(text: e) )).toList(); + _ignoreClientQueryLog = widget.client!.ignoreQuerylog ?? false; + _ignoreClientStatistics = widget.client!.ignoreStatistics ?? false; } super.initState(); } @@ -140,7 +145,9 @@ class _ClientScreenState extends State { useGlobalBlockedServices: useGlobalSettingsServices, blockedServices: blockedServices, upstreams: List.from(upstreamServers.map((e) => e.controller.text)), - tags: selectedTags + tags: selectedTags, + ignoreQuerylog: _ignoreClientQueryLog, + ignoreStatistics: _ignoreClientStatistics ); widget.onConfirm(client); } @@ -214,6 +221,10 @@ class _ClientScreenState extends State { updateEnableSafeSearch: (v) => setState(() => enableSafeSearch = v), updateSafeSearch: (v) => setState(() => safeSearch = v), updateUseGlobalSettingsServices: (v) => setState(() => useGlobalSettingsServices = v), + ignoreClientQueryLog: _ignoreClientQueryLog, + ignoreClientStatistics: _ignoreClientStatistics, + updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v), + updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v), ), ), ), @@ -281,6 +292,10 @@ class _ClientScreenState extends State { updateEnableSafeSearch: (v) => setState(() => enableSafeSearch = v), updateSafeSearch: (v) => setState(() => safeSearch = v), updateUseGlobalSettingsServices: (v) => setState(() => useGlobalSettingsServices = v), + ignoreClientQueryLog: _ignoreClientQueryLog, + ignoreClientStatistics: _ignoreClientStatistics, + updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v), + updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v), ), ) ], From ddf9683e88c56cfba2f171ffafd2775173d43208 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 21:49:52 +0100 Subject: [PATCH 459/676] Updated libraries --- pubspec.lock | 42 +++++++++++++++++++++--------------------- pubspec.yaml | 10 +++++----- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 274cfb3..963ce6f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: "direct main" description: name: animations - sha256: ef57563eed3620bd5d75ad96189846aca1e033c0c45fc9a7d26e80ab02b88a70 + sha256: "708e4b68c23228c264b038fe7003a2f5d01ce85fc64d8cae090e86b27fcea6c5" url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "2.0.10" ansicolor: dependency: transitive description: @@ -271,10 +271,10 @@ packages: dependency: "direct dev" description: name: flutter_native_splash - sha256: c4d899312b36e7454bedfd0a4740275837b99e532d81c8477579d8183db1de6c + sha256: "141b20f15a2c4fe6e33c49257ca1bc114fc5c500b04fcbc8d75016bb86af672f" url: "https://pub.dev" source: hosted - version: "2.3.6" + version: "2.3.8" flutter_reorderable_list: dependency: "direct main" description: @@ -330,10 +330,10 @@ packages: dependency: "direct main" description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.2" http_parser: dependency: transitive description: @@ -474,10 +474,10 @@ packages: dependency: transitive description: name: petitparser - sha256: eeb2d1428ee7f4170e2bd498827296a18d4e7fc462b71727d111c0ac7707cfa6 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "6.0.1" + version: "6.0.2" pie_chart: dependency: "direct main" description: @@ -575,18 +575,18 @@ packages: dependency: "direct main" description: name: sqflite_common_ffi - sha256: "35d2fce1e971707c227cc4775cc017d5eafe06c2654c3435ebd5c3ad6c170f5f" + sha256: "873677ee78738a723d1ded4ccb23980581998d873d30ee9c331f6a81748663ff" url: "https://pub.dev" source: hosted - version: "2.3.0+4" + version: "2.3.1" sqlite3: dependency: transitive description: name: sqlite3 - sha256: db65233e6b99e99b2548932f55a987961bc06d82a31a0665451fa0b4fff4c3fb + sha256: "8922805564b78eb7aa9386c10056d377a541ac7270dc6a1589176277ebb4d15d" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" sqlite3_flutter_libs: dependency: "direct main" description: @@ -671,10 +671,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: b1c9e98774adf8820c96fbc7ae3601231d324a7d5ebd8babe27b6dfac91357ba + sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86 url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.2.2" url_launcher_android: dependency: transitive description: @@ -719,10 +719,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + sha256: "7286aec002c8feecc338cc33269e96b73955ab227456e9fb2a91f7fab8a358e9" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.2" url_launcher_windows: dependency: transitive description: @@ -783,10 +783,10 @@ packages: dependency: transitive description: name: win32 - sha256: "7c99c0e1e2fa190b48d25c81ca5e42036d5cac81430ef249027d97b0935c553f" + sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.1.1" win32_registry: dependency: transitive description: @@ -808,10 +808,10 @@ packages: dependency: transitive description: name: xml - sha256: af5e77e9b83f2f4adc5d3f0a4ece1c7f45a2467b695c2540381bac793e34e556 + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.4.2" + version: "6.5.0" yaml: dependency: transitive description: @@ -822,4 +822,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.2.0 <4.0.0" - flutter: ">=3.13.0" + flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1ad22e1..4f19f1c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,7 +44,7 @@ dependencies: package_info_plus: ^5.0.1 flutter_displaymode: ^0.6.0 dynamic_color: ^1.6.8 - animations: ^2.0.8 + animations: ^2.0.10 device_info_plus: ^9.1.1 uuid: ^4.2.1 expandable: ^5.0.1 @@ -58,7 +58,7 @@ dependencies: html: ^0.15.4 flutter_html: ^3.0.0-beta.2 sqlite3_flutter_libs: ^0.5.18 - sqflite_common_ffi: ^2.3.0+4 + sqflite_common_ffi: ^2.3.1 window_size: git: url: https://github.com/google/flutter-desktop-embedding @@ -67,7 +67,7 @@ dependencies: git: url: https://github.com/JGeek00/flutter_split_view ref: master-alt - url_launcher: ^6.1.11 + url_launcher: ^6.2.2 contextmenu: ^3.0.0 async: ^2.11.0 sentry_flutter: ^7.13.2 @@ -75,7 +75,7 @@ dependencies: flutter_reorderable_list: ^1.3.1 pie_chart: ^5.4.0 segmented_button_slide: ^1.0.4 - http: ^1.1.0 + http: ^1.1.2 dev_dependencies: flutter_test: @@ -88,7 +88,7 @@ dev_dependencies: # rules and activating additional ones. flutter_lints: ^3.0.1 flutter_launcher_icons: ^0.13.1 - flutter_native_splash: ^2.3.6 + flutter_native_splash: ^2.3.8 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From 27e0b5152ec065a297646b26c840df9b360eb3f2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 22:03:36 +0100 Subject: [PATCH 460/676] Added fallback DNS servers --- lib/l10n/app_en.arb | 6 +- lib/l10n/app_es.arb | 6 +- lib/models/dns_info.dart | 4 + lib/providers/dns_provider.dart | 16 ++ lib/screens/settings/dns/dns.dart | 7 + lib/screens/settings/dns/fallback_dns.dart | 224 +++++++++++++++++++++ 6 files changed, 261 insertions(+), 2 deletions(-) create mode 100644 lib/screens/settings/dns/fallback_dns.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 1a4cdb4..7fd17e2 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -706,5 +706,9 @@ "queryLogsAndStatistics": "Query logs and statistics", "ignoreClientQueryLog": "Ignore this client in query log", "ignoreClientStatistics": "Ignore this client in statistics", - "savingChanges": "Saving changes..." + "savingChanges": "Saving changes...", + "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." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index e0e57c1..33b69b1 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -706,5 +706,9 @@ "queryLogsAndStatistics": "Registro de consultas y estadísticas", "ignoreClientQueryLog": "Ignorar este cliente en el registro de consultas", "ignoreClientStatistics": "Ignorar este cliente en las estadísticas", - "savingChanges": "Guardando cambios..." + "savingChanges": "Guardando cambios...", + "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." } \ No newline at end of file diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 0d3aa83..20338d3 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -2,6 +2,7 @@ class DnsInfo { List upstreamDns; String? upstreamDnsFile; List bootstrapDns; + List? fallbackDns; bool protectionEnabled; int ratelimit; String blockingMode; @@ -26,6 +27,7 @@ class DnsInfo { required this.upstreamDns, required this.upstreamDnsFile, required this.bootstrapDns, + required this.fallbackDns, required this.protectionEnabled, required this.ratelimit, required this.blockingMode, @@ -51,6 +53,7 @@ class DnsInfo { upstreamDns: json["upstream_dns"] != null ? List.from(json["upstream_dns"].map((x) => x)) : [], upstreamDnsFile: json["upstream_dns_file"], bootstrapDns: json["bootstrap_dns"] != null ? List.from(json["bootstrap_dns"].map((x) => x)) : [], + fallbackDns: json["fallback_dns"] != null ? List.from(json["fallback_dns"].map((x) => x)) : [], protectionEnabled: json["protection_enabled"], ratelimit: json["ratelimit"], blockingMode: json["blocking_mode"], @@ -76,6 +79,7 @@ class DnsInfo { "upstream_dns": List.from(upstreamDns.map((x) => x)), "upstream_dns_file": upstreamDnsFile, "bootstrap_dns": List.from(bootstrapDns.map((x) => x)), + "fallback_dns": List.from(bootstrapDns.map((x) => x)), "protection_enabled": protectionEnabled, "ratelimit": ratelimit, "blocking_mode": blockingMode, diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index 0929f3a..5a91dfc 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -112,6 +112,22 @@ class DnsProvider with ChangeNotifier { } } + Future saveFallbackDnsConfig(Map value) async { + final result = await _serversProvider!.apiClient2!.setDnsConfig( + data: value + ); + + if (result.successful == true) { + DnsInfo data = dnsInfo!; + data.bootstrapDns = List.from(value['fallback_dns']); + setDnsInfoData(data); + return result; + } + else { + return result; + } + } + Future saveCacheCacheConfig(Map value) async { final result = await _serversProvider!.apiClient2!.setDnsConfig( data: value diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index c22572d..4a7c78a 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -5,6 +5,7 @@ import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/settings/dns/fallback_dns.dart'; import 'package:adguard_home_manager/screens/settings/dns/test_upstream_dns_modal.dart'; import 'package:adguard_home_manager/screens/settings/dns/clear_dns_cache_dialog.dart'; import 'package:adguard_home_manager/screens/settings/dns/cache_config.dart'; @@ -167,6 +168,12 @@ class _DnsSettingsState extends State { onTap: () => navigate(const BootstrapDnsScreen()), icon: Icons.dns_rounded, ), + if (dnsProvider.dnsInfo!.fallbackDns != null) CustomListTile( + title: AppLocalizations.of(context)!.fallbackDnsServers, + subtitle: AppLocalizations.of(context)!.fallbackDnsServersDescription, + onTap: () => navigate(const FallbackDnsScreen()), + icon: Icons.alt_route_rounded, + ), CustomListTile( title: AppLocalizations.of(context)!.privateReverseDnsServers, subtitle: AppLocalizations.of(context)!.privateReverseDnsDescription, diff --git a/lib/screens/settings/dns/fallback_dns.dart b/lib/screens/settings/dns/fallback_dns.dart new file mode 100644 index 0000000..4df30c9 --- /dev/null +++ b/lib/screens/settings/dns/fallback_dns.dart @@ -0,0 +1,224 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; + +class FallbackDnsScreen extends StatefulWidget { + const FallbackDnsScreen({super.key}); + + @override + State createState() => _FallbackDnsScreenState(); +} + +class _FallbackDnsScreenState extends State { + List> fallbackControllers = []; + + bool validValues = false; + + void validateIp(Map field, String value) { + RegExp ipAddress = RegExp(r'(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$)'); + if (ipAddress.hasMatch(value) == true) { + setState(() => field['error'] = null); + } + else { + setState(() => field['error'] = AppLocalizations.of(context)!.invalidIp); + } + checkValidValues(); + } + + void checkValidValues() { + if ( + fallbackControllers.isNotEmpty && + fallbackControllers.every((element) => element['controller'].text != '') && + fallbackControllers.every((element) => element['error'] == null) + ) { + setState(() => validValues = true); + } + else { + setState(() => validValues = false); + } + } + + @override + void initState() { + final dnsProvider = Provider.of(context, listen: false); + + for (var item in dnsProvider.dnsInfo!.fallbackDns!) { + final controller = TextEditingController(); + controller.text = item; + fallbackControllers.add({ + 'controller': controller, + 'error': null + }); + } + validValues = true; + super.initState(); + } + + @override + Widget build(BuildContext context) { + final dnsProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; + + void saveData() async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.savingConfig); + + final result = await dnsProvider.saveFallbackDnsConfig({ + "fallback_dns": fallbackControllers.map((e) => e['controller'].text).toList(), + }); + + processModal.close(); + + if (result.successful == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigSaved, + color: Colors.green + ); + } + else if (result.successful == false && result.statusCode == 400) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.someValueNotValid, + color: Colors.red + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigNotSaved, + color: Colors.red + ); + } + } + + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.fallbackDnsServers), + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, + actions: [ + IconButton( + onPressed: validValues == true + ? () => saveData() + : null, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 10) + ], + ), + body: SafeArea( + child: ListView( + padding: const EdgeInsets.only(top: 10), + children: [ + Card( + margin: const EdgeInsets.only( + left: 16, right: 16, bottom: 20 + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).listTileTheme.iconColor, + ), + const SizedBox(width: 20), + Flexible( + child: Text( + AppLocalizations.of(context)!.fallbackDnsServersInfo, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ) + ], + ), + ), + ), + const SizedBox(height: 10), + if (fallbackControllers.isEmpty) Column( + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: Center( + child: Text( + AppLocalizations.of(context)!.noFallbackDnsAdded, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontSize: 16 + ), + ), + ), + ), + const SizedBox(height: 20), + ], + ), + ...fallbackControllers.map((c) => Padding( + padding: const EdgeInsets.only( + left: 16, right: 6, bottom: 20 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextFormField( + controller: c['controller'], + onChanged: (value) => validateIp(c, value), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.dns_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: c['error'], + labelText: AppLocalizations.of(context)!.dnsServer, + ) + ), + ), + const SizedBox(width: 8), + IconButton( + onPressed: () { + setState(() => fallbackControllers = fallbackControllers.where((con) => con != c).toList()); + checkValidValues(); + }, + icon: const Icon(Icons.remove_circle_outline) + ) + ], + ), + )), + Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton.icon( + onPressed: () { + setState(() => fallbackControllers.add({ + 'controller': TextEditingController(), + 'error': null + })); + checkValidValues(); + }, + icon: const Icon(Icons.add), + label: Text(AppLocalizations.of(context)!.addItem) + ), + ], + ), + const SizedBox(height: 20) + ], + ), + ), + ); + } +} \ No newline at end of file From 304c3aba540bf9222313c1147d5da9e19de363cd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 22:24:24 +0100 Subject: [PATCH 461/676] Added blocked response ttl field --- lib/l10n/app_en.arb | 5 +- lib/l10n/app_es.arb | 5 +- lib/models/dns_info.dart | 4 ++ lib/providers/dns_provider.dart | 1 + .../settings/dns/dns_server_settings.dart | 47 +++++++++++++++++-- 5 files changed, 56 insertions(+), 6 deletions(-) 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, + ), + ), ], ), ), From 28bc01a7b3b53188745625b29d7ebd14bffa75ea Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 11 Dec 2023 22:25:44 +0100 Subject: [PATCH 462/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 4f19f1c..8672c5a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.12.4+115 +version: 2.13.0-beta.1+116 environment: sdk: '>=2.18.1 <3.0.0' From 0b0f499c4ac42a58629ffeff80710c6185bb7cfc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 12 Dec 2023 18:43:38 +0100 Subject: [PATCH 463/676] Updates --- ios/Podfile.lock | 40 ++++++++++++++++++++-------------------- macos/Podfile.lock | 4 ++-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ed1a57c..c3ba953 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -11,28 +11,28 @@ PODS: - FMDB/standard (2.7.5) - package_info_plus (0.4.5): - Flutter - - Sentry/HybridSDK (8.9.1): - - SentryPrivate (= 8.9.1) + - Sentry/HybridSDK (8.15.2): + - SentryPrivate (= 8.15.2) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.9.1) - - SentryPrivate (8.9.1) + - Sentry/HybridSDK (= 8.15.2) + - SentryPrivate (8.15.2) - sqflite (0.0.3): - Flutter - FMDB (>= 2.7.5) - - sqlite3 (3.43.1): - - sqlite3/common (= 3.43.1) - - sqlite3/common (3.43.1) - - sqlite3/fts5 (3.43.1): + - sqlite3 (3.44.0): + - sqlite3/common (= 3.44.0) + - sqlite3/common (3.44.0) + - sqlite3/fts5 (3.44.0): - sqlite3/common - - sqlite3/perf-threadsafe (3.43.1): + - sqlite3/perf-threadsafe (3.44.0): - sqlite3/common - - sqlite3/rtree (3.43.1): + - sqlite3/rtree (3.44.0): - sqlite3/common - sqlite3_flutter_libs (0.0.1): - Flutter - - sqlite3 (~> 3.43.0) + - sqlite3 (~> 3.44.0) - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree @@ -83,21 +83,21 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: - device_info_plus: 7545d84d8d1b896cb16a4ff98c19f07ec4b298ea + device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef flutter_web_browser: 7bccaafbb0c5b8862afe7bcd158f15557109f61f FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 - Sentry: e3203780941722a1fcfee99e351de14244c7f806 - sentry_flutter: 8f0ffd53088e6a4d50c095852c5cad9e4405025c - SentryPrivate: 5e3683390f66611fc7c6215e27645873adb55d13 + package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 + Sentry: 6f5742b4c47c17c9adcf265f6f328cf4a0ed1923 + sentry_flutter: 2c309a1d4b45e59d02cfa15795705687f1e2081b + SentryPrivate: b2f7996f37781080f04a946eb4e377ff63c64195 sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a - sqlite3: e0a0623a33a20a47cb5921552aebc6e9e437dc91 - sqlite3_flutter_libs: 878ccbdcfd7b7cb41a774ec238223d876880c5ec + sqlite3: 6e2d4a4879854d0ec86b476bf3c3e30870bac273 + sqlite3_flutter_libs: eb769059df0356dc52ddda040f09cacc9391a7cf store_checker: 359c5051d9ec30ff0a8fa39eb5ec9df021bb745d - url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 + url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.12.1 +COCOAPODS: 1.14.3 diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 4543f6f..32c37ec 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -88,10 +88,10 @@ SPEC CHECKSUMS: SentryPrivate: b2f7996f37781080f04a946eb4e377ff63c64195 sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea sqlite3: 6e2d4a4879854d0ec86b476bf3c3e30870bac273 - sqlite3_flutter_libs: 5b7e226d522d67be60d7ade93f5aa11ebc0cd796 + sqlite3_flutter_libs: a25f3a0f522fdcd8fef6a4a50a3d681dd43d8dea url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 -COCOAPODS: 1.12.1 +COCOAPODS: 1.14.3 From 3132957a91c3a403dc32557b4ef184a6377b0c35 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 14 Dec 2023 15:22:09 +0100 Subject: [PATCH 464/676] Fix --- .../settings/access_settings/access_settings.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index d5673f7..9c1e986 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -49,6 +49,7 @@ class _AccessSettingsState extends State with TickerProviderStat handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), sliver: SliverSafeArea( top: false, + bottom: false, sliver: SliverAppBar( title: Text(AppLocalizations.of(context)!.accessSettings), pinned: true, @@ -56,10 +57,7 @@ class _AccessSettingsState extends State with TickerProviderStat centerTitle: false, forceElevated: innerBoxIsScrolled, surfaceTintColor: isDesktop(width) ? Colors.transparent : null, - bottom: PreferredSize( - preferredSize: const Size(double.maxFinite, 50), - child: _Tabs(tabController: _tabController) - ) + bottom: _Tabs(tabController: _tabController) ), ), ) @@ -92,7 +90,7 @@ class _AccessSettingsState extends State with TickerProviderStat } } -class _Tabs extends StatelessWidget { +class _Tabs extends StatelessWidget implements PreferredSizeWidget { final TabController tabController; const _Tabs({ @@ -137,6 +135,9 @@ class _Tabs extends StatelessWidget { ] ); } + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); } class _TabsView extends StatelessWidget { From 31a37986bf8bd2fa719314624622cecf973a4e84 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 14 Dec 2023 15:24:13 +0100 Subject: [PATCH 465/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 8672c5a..9bd3484 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.13.0-beta.1+116 +version: 2.13.0+117 environment: sdk: '>=2.18.1 <3.0.0' From a3620f259fc15710d990f38278fc6d34553bb948 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 15 Dec 2023 03:03:33 +0100 Subject: [PATCH 466/676] Updated iOS stuff --- ios/.gitignore | 0 ios/Flutter/AppFrameworkInfo.plist | 0 ios/Flutter/Debug.xcconfig | 0 ios/Flutter/Release.xcconfig | 0 ios/Podfile | 0 ios/Podfile.lock | 0 ios/Runner.xcodeproj/project.pbxproj | 41 ++++++-- .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../xcshareddata/xcschemes/Runner.xcscheme | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 ios/Runner/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../Icon-App-1024x1024@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin .../Icon-App-83.5x83.5@2x.png | Bin .../LaunchBackground.imageset/Contents.json | 0 .../LaunchBackground.imageset/background.png | Bin .../darkbackground.png | Bin .../LaunchImage.imageset/Contents.json | 0 .../LaunchImage.imageset/LaunchImage.png | Bin .../LaunchImage.imageset/LaunchImage@2x.png | Bin .../LaunchImage.imageset/LaunchImage@3x.png | Bin .../LaunchImage.imageset/LaunchImageDark.png | Bin .../LaunchImageDark@2x.png | Bin .../LaunchImageDark@3x.png | Bin .../LaunchImage.imageset/README.md | 0 ios/Runner/Base.lproj/LaunchScreen.storyboard | 0 ios/Runner/Base.lproj/Main.storyboard | 0 ios/Runner/Info.plist | 98 +++++++++--------- ios/Runner/Runner-Bridging-Header.h | 0 52 files changed, 83 insertions(+), 56 deletions(-) mode change 100644 => 100755 ios/.gitignore mode change 100644 => 100755 ios/Flutter/AppFrameworkInfo.plist mode change 100644 => 100755 ios/Flutter/Debug.xcconfig mode change 100644 => 100755 ios/Flutter/Release.xcconfig mode change 100644 => 100755 ios/Podfile mode change 100644 => 100755 ios/Podfile.lock mode change 100644 => 100755 ios/Runner.xcodeproj/project.pbxproj mode change 100644 => 100755 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata mode change 100644 => 100755 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist mode change 100644 => 100755 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings mode change 100644 => 100755 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme mode change 100644 => 100755 ios/Runner.xcworkspace/contents.xcworkspacedata mode change 100644 => 100755 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist mode change 100644 => 100755 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings mode change 100644 => 100755 ios/Runner/AppDelegate.swift mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md mode change 100644 => 100755 ios/Runner/Base.lproj/LaunchScreen.storyboard mode change 100644 => 100755 ios/Runner/Base.lproj/Main.storyboard mode change 100644 => 100755 ios/Runner/Info.plist mode change 100644 => 100755 ios/Runner/Runner-Bridging-Header.h diff --git a/ios/.gitignore b/ios/.gitignore old mode 100644 new mode 100755 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist old mode 100644 new mode 100755 diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig old mode 100644 new mode 100755 diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig old mode 100644 new mode 100755 diff --git a/ios/Podfile b/ios/Podfile old mode 100644 new mode 100755 diff --git a/ios/Podfile.lock b/ios/Podfile.lock old mode 100644 new mode 100755 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj old mode 100644 new mode 100755 index 4f766b9..00edeae --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -68,7 +68,6 @@ 65533F0C0783FDE34AE79B0A /* Pods-Runner.release.xcconfig */, 69C2CC4A6DE17506FC5C0F13 /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -156,6 +155,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { @@ -325,6 +325,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -335,6 +336,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -343,7 +345,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -361,15 +363,22 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 38Z3B9TJTR; ENABLE_BITCODE = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguard_home_manager; + PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguardHomeManager; PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; @@ -397,6 +406,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -407,6 +417,7 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -421,7 +432,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -452,6 +463,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -462,6 +474,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -470,7 +483,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -490,16 +503,23 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 38Z3B9TJTR; ENABLE_BITCODE = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguard_home_manager; + PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguardHomeManager; PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -513,15 +533,22 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 38Z3B9TJTR; ENABLE_BITCODE = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguard_home_manager; + PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.adguardHomeManager; PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata old mode 100644 new mode 100755 diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist old mode 100644 new mode 100755 diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings old mode 100644 new mode 100755 diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme old mode 100644 new mode 100755 diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata old mode 100644 new mode 100755 diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist old mode 100644 new mode 100755 diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings old mode 100644 new mode 100755 diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png old mode 100644 new mode 100755 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md old mode 100644 new mode 100755 diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard old mode 100644 new mode 100755 diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard old mode 100644 new mode 100755 diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist old mode 100644 new mode 100755 index f9aeb27..55fe6b7 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -1,53 +1,53 @@ - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - AdGuard Home Manager - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - adguard_home_manager - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - UIStatusBarHidden - - + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + AdGuard Home + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + adguardHomeManager + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h old mode 100644 new mode 100755 From d2e882a0301d82526ab2bb657a66a3ecd247f915 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 17 Dec 2023 14:14:31 +0100 Subject: [PATCH 467/676] Link to logs screen from home screen --- lib/providers/logs_provider.dart | 8 +- lib/screens/home/chart.dart | 85 +++++++++++++------ lib/screens/home/home.dart | 32 +++++++ .../logs/filters/filter_status_modal.dart | 2 +- .../logs/filters/logs_filters_modal.dart | 6 +- lib/screens/logs/logs_list.dart | 4 +- lib/screens/logs/logs_list_appbar.dart | 2 +- 7 files changed, 107 insertions(+), 32 deletions(-) diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index 7861e6d..d9bc55f 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -114,9 +114,15 @@ class LogsProvider with ChangeNotifier { _offset = value; } - void setSelectedResultStatus(String value) { + void setSelectedResultStatus({ + required String value, + bool? refetch + }) { _selectedResultStatus = value; notifyListeners(); + if (refetch = true) { + filterLogs(); + } } void setSearchText(String? value) { diff --git a/lib/screens/home/chart.dart b/lib/screens/home/chart.dart index ba97f79..22c3117 100644 --- a/lib/screens/home/chart.dart +++ b/lib/screens/home/chart.dart @@ -1,17 +1,19 @@ import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; import 'package:provider/provider.dart'; import 'package:adguard_home_manager/widgets/line_chart.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class HomeChart extends StatelessWidget { +class HomeChart extends StatefulWidget { final List data; final String label; final String primaryValue; final String secondaryValue; final Color color; final int hoursInterval; + final void Function() onTapTitle; const HomeChart({ super.key, @@ -20,20 +22,28 @@ class HomeChart extends StatelessWidget { required this.primaryValue, required this.secondaryValue, required this.color, - required this.hoursInterval + required this.hoursInterval, + required this.onTapTitle, }); + @override + State createState() => _HomeChartState(); +} + +class _HomeChartState extends State { + bool _isHover = false; + @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - final bool isEmpty = data.every((i) => i == 0); + final bool isEmpty = widget.data.every((i) => i == 0); if (!(appConfigProvider.hideZeroValues == true && isEmpty == true)) { List dateTimes = []; - DateTime currentDate = DateTime.now().subtract(Duration(hours: hoursInterval*data.length+1)); - for (var i = 0; i < data.length; i++) { - currentDate = currentDate.add(Duration(hours: hoursInterval)); + DateTime currentDate = DateTime.now().subtract(Duration(hours: widget.hoursInterval*widget.data.length+1)); + for (var i = 0; i < widget.data.length; i++) { + currentDate = currentDate.add(Duration(hours: widget.hoursInterval)); dateTimes.add(currentDate); } @@ -52,13 +62,40 @@ class HomeChart extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Flexible( - child: Text( - label, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _isHover = true), + onExit: (_) => setState(() => _isHover = false), + child: GestureDetector( + onTapDown: (_) => setState(() => _isHover = true), + onTapUp: (_) => setState(() => _isHover = false), + onTap: widget.onTapTitle, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Text( + widget.label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: _isHover + ? Theme.of(context).colorScheme.onSurfaceVariant + : Theme.of(context).colorScheme.onSurface, + ), + ), + ), + const SizedBox(width: 4), + Icon( + Icons.chevron_right_rounded, + size: 20, + color: _isHover + ? Theme.of(context).colorScheme.onSurfaceVariant + : Theme.of(context).colorScheme.onSurface, + ) + ], + ), ), ), ), @@ -67,18 +104,18 @@ class HomeChart extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - primaryValue, + widget.primaryValue, style: TextStyle( - color: color, + color: widget.color, fontSize: 18, fontWeight: FontWeight.w500 ), ), Text( - secondaryValue, + widget.secondaryValue, style: TextStyle( fontSize: 12, - color: color + color: widget.color ), ) ], @@ -86,19 +123,19 @@ class HomeChart extends StatelessWidget { : Row( children: [ Text( - primaryValue, + widget.primaryValue, style: TextStyle( - color: color, + color: widget.color, fontSize: 18, fontWeight: FontWeight.w500 ), ), const SizedBox(width: 10), Text( - "($secondaryValue)", + "(${widget.secondaryValue})", style: TextStyle( fontSize: 12, - color: color + color: widget.color ), ) ], @@ -110,10 +147,10 @@ class HomeChart extends StatelessWidget { width: double.maxFinite, height: 150, child: CustomLineChart( - data: data, - color: color, + data: widget.data, + color: widget.color, dates: dateTimes, - daysInterval: hoursInterval == 24, + daysInterval: widget.hoursInterval == 24, context: context, ) ), diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 9e5de00..e7ed5c0 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -14,6 +14,7 @@ import 'package:adguard_home_manager/screens/home/appbar.dart'; import 'package:adguard_home_manager/screens/home/fab.dart'; import 'package:adguard_home_manager/screens/home/chart.dart'; +import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; @@ -61,6 +62,7 @@ class _HomeState extends State { Widget build(BuildContext context) { final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final logsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -143,6 +145,14 @@ class _HomeState extends State { secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", color: Colors.blue, hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, + onTapTitle: () { + logsProvider.setSelectedResultStatus( + value: "all", + refetch: true + ); + logsProvider.filterLogs(); + appConfigProvider.setSelectedScreen(2); + }, ), ), FractionallySizedBox( @@ -154,6 +164,13 @@ class _HomeState extends State { secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.red, hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, + onTapTitle: () { + logsProvider.setSelectedResultStatus( + value: "blocked", + refetch: true + ); + appConfigProvider.setSelectedScreen(2); + }, ), ), FractionallySizedBox( @@ -165,6 +182,13 @@ class _HomeState extends State { secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.green, hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, + onTapTitle: () { + logsProvider.setSelectedResultStatus( + value: "blocked_safebrowsing", + refetch: true + ); + appConfigProvider.setSelectedScreen(2); + }, ), ), FractionallySizedBox( @@ -176,6 +200,14 @@ class _HomeState extends State { secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.orange, hoursInterval: statusProvider.serverStatus!.stats.timeUnits == "days" ? 24 : 1, + onTapTitle: () { + logsProvider.setSelectedResultStatus( + value: "blocked_parental", + refetch: true + ); + logsProvider.filterLogs(); + appConfigProvider.setSelectedScreen(2); + }, ), ), ], diff --git a/lib/screens/logs/filters/filter_status_modal.dart b/lib/screens/logs/filters/filter_status_modal.dart index 88f782b..c08d9a8 100644 --- a/lib/screens/logs/filters/filter_status_modal.dart +++ b/lib/screens/logs/filters/filter_status_modal.dart @@ -34,7 +34,7 @@ class _FilterStatusModalState extends State { final logsProvider = Provider.of(context); void apply() async { - logsProvider.setSelectedResultStatus(selectedResultStatus); + logsProvider.setSelectedResultStatus(value: selectedResultStatus); Navigator.pop(context); } diff --git a/lib/screens/logs/filters/logs_filters_modal.dart b/lib/screens/logs/filters/logs_filters_modal.dart index 5e7e746..aec6b27 100644 --- a/lib/screens/logs/filters/logs_filters_modal.dart +++ b/lib/screens/logs/filters/logs_filters_modal.dart @@ -262,13 +262,13 @@ class _FiltersList extends StatelessWidget { FilterChip( selected: logsProvider.selectedResultStatus == "all", label: Text(AppLocalizations.of(context)!.all), - onSelected: (_) => logsProvider.setSelectedResultStatus("all") + onSelected: (_) => logsProvider.setSelectedResultStatus(value: "all") ), FilterChip( selected: logsProvider.selectedResultStatus == "processed" || logsProvider.selectedResultStatus == "whitelisted", label: Text(AppLocalizations.of(context)!.allowed), - onSelected: (_) => logsProvider.setSelectedResultStatus("processed") + onSelected: (_) => logsProvider.setSelectedResultStatus(value: "processed") ), FilterChip( selected: logsProvider.selectedResultStatus == "blocked" || @@ -276,7 +276,7 @@ class _FiltersList extends StatelessWidget { logsProvider.selectedResultStatus == "blocked_parental" || logsProvider.selectedResultStatus == "safe_search", label: Text(AppLocalizations.of(context)!.blocked), - onSelected: (_) => logsProvider.setSelectedResultStatus("blocked") + onSelected: (_) => logsProvider.setSelectedResultStatus(value: "blocked") ), ], ), diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart index ac0596a..ced94ca 100644 --- a/lib/screens/logs/logs_list.dart +++ b/lib/screens/logs/logs_list.dart @@ -22,11 +22,11 @@ class LogsListWidget extends StatefulWidget { final void Function(Log) onLogSelected; const LogsListWidget({ - Key? key, + super.key, required this.twoColumns, required this.selectedLog, required this.onLogSelected, - }) : super(key: key); + }); @override State createState() => _LogsListWidgetState(); diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index f467d26..8aeb752 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -256,7 +256,7 @@ class LogsListAppBar extends StatelessWidget { clients: logsProvider.appliedFilters.clients ) ); - logsProvider.setSelectedResultStatus('all'); + logsProvider.setSelectedResultStatus(value: 'all'); logsProvider.fetchLogs( inOffset: 0, responseStatus: 'all' From 6523229ea3082e8f43875be21b39163926704b69 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 17 Dec 2023 14:14:58 +0100 Subject: [PATCH 468/676] Removed unused imports --- lib/screens/home/chart.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/screens/home/chart.dart b/lib/screens/home/chart.dart index 22c3117..d111519 100644 --- a/lib/screens/home/chart.dart +++ b/lib/screens/home/chart.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_html/flutter_html.dart'; import 'package:provider/provider.dart'; import 'package:adguard_home_manager/widgets/line_chart.dart'; From 71b870b42ff72ae55c7bbe927e74967be80eafa0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 17 Dec 2023 14:32:46 +0100 Subject: [PATCH 469/676] Added placeholders no data charts --- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/screens/home/chart.dart | 125 +++++++++++++++++++++--------------- lib/screens/home/home.dart | 4 ++ 4 files changed, 85 insertions(+), 52 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 4fe20b3..60b94cc 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -713,5 +713,7 @@ "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" + "invalidValue": "Invalid value", + "noDataChart": "There's no data to display this chart.", + "noData": "No data" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index d3e0855..a7a9fd6 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -713,5 +713,7 @@ "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" + "invalidValue": "Valor no válido", + "noDataChart": "No hay datos para mostrar este gráfico.", + "noData": "No hay datos" } \ No newline at end of file diff --git a/lib/screens/home/chart.dart b/lib/screens/home/chart.dart index d111519..0093ae8 100644 --- a/lib/screens/home/chart.dart +++ b/lib/screens/home/chart.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/line_chart.dart'; @@ -13,6 +14,7 @@ class HomeChart extends StatefulWidget { final Color color; final int hoursInterval; final void Function() onTapTitle; + final bool isDesktop; const HomeChart({ super.key, @@ -23,6 +25,7 @@ class HomeChart extends StatefulWidget { required this.color, required this.hoursInterval, required this.onTapTitle, + required this.isDesktop, }); @override @@ -58,7 +61,9 @@ class _HomeChartState extends State { ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: isEmpty + ? CrossAxisAlignment.center + : CrossAxisAlignment.start, children: [ Flexible( child: MouseRegion( @@ -68,7 +73,7 @@ class _HomeChartState extends State { child: GestureDetector( onTapDown: (_) => setState(() => _isHover = true), onTapUp: (_) => setState(() => _isHover = false), - onTap: widget.onTapTitle, + onTap: !isEmpty ? () => widget.onTapTitle () : null, child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -79,66 +84,64 @@ class _HomeChartState extends State { style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: _isHover + color: _isHover && !isEmpty ? Theme.of(context).colorScheme.onSurfaceVariant : Theme.of(context).colorScheme.onSurface, ), ), ), - const SizedBox(width: 4), - Icon( - Icons.chevron_right_rounded, - size: 20, - color: _isHover - ? Theme.of(context).colorScheme.onSurfaceVariant - : Theme.of(context).colorScheme.onSurface, - ) + if (!isEmpty) ...[ + const SizedBox(width: 4), + Icon( + Icons.chevron_right_rounded, + size: 20, + color: _isHover && !isEmpty + ? Theme.of(context).colorScheme.onSurfaceVariant + : Theme.of(context).colorScheme.onSurface, + ) + ], ], ), ), ), ), - !isEmpty - ? Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - widget.primaryValue, - style: TextStyle( - color: widget.color, - fontSize: 18, - fontWeight: FontWeight.w500 - ), - ), - Text( - widget.secondaryValue, - style: TextStyle( - fontSize: 12, - color: widget.color - ), - ) - ], + if (!isEmpty) Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + widget.primaryValue, + style: TextStyle( + color: widget.color, + fontSize: 18, + fontWeight: FontWeight.w500 + ), + ), + Text( + widget.secondaryValue, + style: TextStyle( + fontSize: 12, + color: widget.color + ), ) - : Row( - children: [ - Text( - widget.primaryValue, - style: TextStyle( - color: widget.color, - fontSize: 18, - fontWeight: FontWeight.w500 - ), - ), - const SizedBox(width: 10), - Text( - "(${widget.secondaryValue})", - style: TextStyle( - fontSize: 12, - color: widget.color - ), - ) - ], + ], + ), + if (isEmpty && !widget.isDesktop) Column( + children: [ + Icon( + Icons.show_chart_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + size: 16, + ), + Text( + AppLocalizations.of(context)!.noData, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ) + ], + ) ], ), ), @@ -153,6 +156,28 @@ class _HomeChartState extends State { context: context, ) ), + if (isEmpty && widget.isDesktop) SizedBox( + height: 150, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.show_chart_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + size: 30, + ), + const SizedBox(height: 20), + Text( + AppLocalizations.of(context)!.noDataChart, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ), + ) ], ), ), diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index e7ed5c0..32cdb89 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -153,6 +153,7 @@ class _HomeState extends State { logsProvider.filterLogs(); appConfigProvider.setSelectedScreen(2); }, + isDesktop: width > 700, ), ), FractionallySizedBox( @@ -171,6 +172,7 @@ class _HomeState extends State { ); appConfigProvider.setSelectedScreen(2); }, + isDesktop: width > 700, ), ), FractionallySizedBox( @@ -189,6 +191,7 @@ class _HomeState extends State { ); appConfigProvider.setSelectedScreen(2); }, + isDesktop: width > 700, ), ), FractionallySizedBox( @@ -208,6 +211,7 @@ class _HomeState extends State { logsProvider.filterLogs(); appConfigProvider.setSelectedScreen(2); }, + isDesktop: width > 700, ), ), ], From 569ab7d569b5af48552743ea7c4c88eec76ba57b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 17 Dec 2023 22:09:13 +0100 Subject: [PATCH 470/676] Added option to block and unblock clients from home screen --- lib/l10n/app_en.arb | 5 +- lib/l10n/app_es.arb | 5 +- lib/models/menu_option.dart | 2 +- lib/providers/clients_provider.dart | 22 +++++ .../clients/client/active_client_tile.dart | 8 +- .../clients/client/added_client_tile.dart | 10 +-- lib/screens/clients/search_clients.dart | 6 +- .../filters/filters_triple_column.dart | 4 +- lib/screens/filters/list_options_menu.dart | 10 +-- lib/screens/home/home.dart | 4 + lib/screens/home/top_items/row_item.dart | 2 +- .../home/top_items/top_items_lists.dart | 82 +++++++++++++++---- .../home/top_items/top_items_screen.dart | 4 +- .../home/top_items/top_items_section.dart | 4 +- lib/screens/logs/log_tile.dart | 12 +-- lib/widgets/options_menu.dart | 12 +-- 16 files changed, 139 insertions(+), 53 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 60b94cc..7354d9c 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -715,5 +715,8 @@ "blockedResponseTtlDescription": "Specifies for how many seconds the clients should cache a filtered response", "invalidValue": "Invalid value", "noDataChart": "There's no data to display this chart.", - "noData": "No data" + "noData": "No data", + "unblockClient": "Unblock client", + "blockingClient": "Blocking client...", + "unblockingClient": "Unblocking client..." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index a7a9fd6..78d518f 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -715,5 +715,8 @@ "blockedResponseTtlDescription": "Especifica durante cuántos segundos los clientes deben almacenar en cache una respuesta filtrada", "invalidValue": "Valor no válido", "noDataChart": "No hay datos para mostrar este gráfico.", - "noData": "No hay datos" + "noData": "No hay datos", + "unblockClient": "Desbloquear cliente", + "blockingClient": "Bloqueando cliente...", + "unblockingClient": "Desbloqueando cliente..." } \ No newline at end of file diff --git a/lib/models/menu_option.dart b/lib/models/menu_option.dart index b89f8d9..e898514 100644 --- a/lib/models/menu_option.dart +++ b/lib/models/menu_option.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; class MenuOption { final IconData? icon; final String title; - final void Function(dynamic) action; + final void Function() action; final bool? disabled; const MenuOption({ diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart index bfcf19d..36185cc 100644 --- a/lib/providers/clients_provider.dart +++ b/lib/providers/clients_provider.dart @@ -190,6 +190,16 @@ class ClientsProvider with ChangeNotifier { "blocked_hosts": clients!.clientsAllowedBlocked?.blockedHosts ?? [], }; + if (body['allowed_clients']!.contains(item)) { + body['allowed_clients'] = body['allowed_clients']!.where((e) => e != item).toList(); + } + else if (body['disallowed_clients']!.contains(item)) { + body['disallowed_clients'] = body['disallowed_clients']!.where((e) => e != item).toList(); + } + else if (body['blocked_hosts']!.contains(item)) { + body['blocked_hosts'] = body['blocked_hosts']!.where((e) => e != item).toList(); + } + if (type == AccessSettingsList.allowed) { body['allowed_clients']!.add(item); } @@ -223,6 +233,18 @@ class ClientsProvider with ChangeNotifier { } } + AccessSettingsList? checkClientList(String client) { + if (_clients!.clientsAllowedBlocked!.allowedClients.contains(client)) { + return AccessSettingsList.allowed; + } + else if (_clients!.clientsAllowedBlocked!.disallowedClients.contains(client)) { + return AccessSettingsList.disallowed; + } + else { + return null; + } + } + Future removeClientList(String client, AccessSettingsList type) async { Map> body = { "allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [], diff --git a/lib/screens/clients/client/active_client_tile.dart b/lib/screens/clients/client/active_client_tile.dart index 76c928c..7a7a825 100644 --- a/lib/screens/clients/client/active_client_tile.dart +++ b/lib/screens/clients/client/active_client_tile.dart @@ -28,11 +28,11 @@ class ActiveClientTile extends StatelessWidget { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: OptionsMenu( - options: [ + options: (_) => [ MenuOption( icon: Icons.copy_rounded, title: AppLocalizations.of(context)!.copyClipboard, - action: (_) => copyToClipboard( + action: () => copyToClipboard( value: client.name != '' ? client.name! : client.ip, @@ -99,11 +99,11 @@ class ActiveClientTile extends StatelessWidget { } else { return OptionsMenu( - options: [ + options: (_) => [ MenuOption( icon: Icons.copy_rounded, title: AppLocalizations.of(context)!.copyClipboard, - action: (_) => copyToClipboard( + action: () => copyToClipboard( value: client.name != '' ? client.name! : client.ip, diff --git a/lib/screens/clients/client/added_client_tile.dart b/lib/screens/clients/client/added_client_tile.dart index 4f4037e..8c10fd7 100644 --- a/lib/screens/clients/client/added_client_tile.dart +++ b/lib/screens/clients/client/added_client_tile.dart @@ -46,11 +46,11 @@ class _AddedClientTileState extends State { color: Colors.transparent, borderRadius: BorderRadius.circular(28), child: OptionsMenu( - options: [ + options: (_) => [ MenuOption( icon: Icons.copy_rounded, title: AppLocalizations.of(context)!.copyClipboard, - action: (_) => copyToClipboard( + action: () => copyToClipboard( value: widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), successMessage: AppLocalizations.of(context)!.copiedClipboard, ) @@ -164,16 +164,16 @@ class _AddedClientTileState extends State { } else { return OptionsMenu( - options: [ + options: (_) => [ if (widget.onEdit != null) MenuOption( title: AppLocalizations.of(context)!.seeDetails, icon: Icons.file_open_rounded, - action: (_) => widget.onEdit!(widget.client) + action: () => widget.onEdit!(widget.client) ), MenuOption( icon: Icons.copy_rounded, title: AppLocalizations.of(context)!.copyClipboard, - action: (_) => copyToClipboard( + action: () => copyToClipboard( value: widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), successMessage: AppLocalizations.of(context)!.copiedClipboard, ) diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index d8e1104..e5b1451 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -226,16 +226,16 @@ class _SearchClientsState extends State { itemCount: clientsScreen.length, padding: const EdgeInsets.only(bottom: 0), itemBuilder: (context, index) => OptionsMenu( - options: [ + options: (v) => [ MenuOption( icon: Icons.edit_rounded, title: AppLocalizations.of(context)!.edit, - action: (v) => openClientModal(v) + action: () => openClientModal(v) ), MenuOption( icon: Icons.delete_rounded, title: AppLocalizations.of(context)!.delete, - action: (v) => openDeleteModal(v) + action: () => openDeleteModal(v) ), ], value: clientsScreen[index], diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 3401bac..7d15639 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -283,11 +283,11 @@ class FiltersTripleColumn extends StatelessWidget { ), ], child: OptionsMenu( - options: [ + options: (_) => [ MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: (_) => copyToClipboard( + action: () => copyToClipboard( value: filteringProvider.filtering!.userRules[index], successMessage: AppLocalizations.of(context)!.copiedClipboard, ) diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index 32e4610..c35d080 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -146,7 +146,7 @@ class ListOptionsMenu extends StatelessWidget { color: Colors.transparent, child: InkWell( child: OptionsMenu( - options: [ + options: (_) => [ MenuOption( title: list.enabled == true ? AppLocalizations.of(context)!.disable @@ -154,12 +154,12 @@ class ListOptionsMenu extends StatelessWidget { icon: list.enabled == true ? Icons.gpp_bad_rounded : Icons.verified_user_rounded, - action: (_) => enableDisable() + action: () => enableDisable() ), MenuOption( title: AppLocalizations.of(context)!.copyListUrl, icon: Icons.copy_rounded, - action: (_) => copyToClipboard( + action: () => copyToClipboard( value: list.url, successMessage: AppLocalizations.of(context)!.listUrlCopied ) @@ -167,12 +167,12 @@ class ListOptionsMenu extends StatelessWidget { MenuOption( title: AppLocalizations.of(context)!.openListUrl, icon: Icons.open_in_browser_rounded, - action: (_) => openUrl(list.url) + action: () => openUrl(list.url) ), MenuOption( title: AppLocalizations.of(context)!.selectionMode, icon: Icons.check_rounded, - action: (_) => Future.delayed( + action: () => Future.delayed( const Duration(milliseconds: 0), () => openSelectionMode() ) diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 32cdb89..f34a186 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -14,6 +14,7 @@ import 'package:adguard_home_manager/screens/home/appbar.dart'; import 'package:adguard_home_manager/screens/home/fab.dart'; import 'package:adguard_home_manager/screens/home/chart.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -39,6 +40,9 @@ class _HomeState extends State { withLoadingIndicator: statusProvider.serverStatus != null ? false : true ); + final clientsProvider = Provider.of(context, listen: false); + clientsProvider.fetchClients(updateLoading: false); + super.initState(); isVisible = true; diff --git a/lib/screens/home/top_items/row_item.dart b/lib/screens/home/top_items/row_item.dart index 569d30c..b323eb0 100644 --- a/lib/screens/home/top_items/row_item.dart +++ b/lib/screens/home/top_items/row_item.dart @@ -16,7 +16,7 @@ class RowItem extends StatefulWidget { final bool clients; final bool showColor; final String? unit; - final List options; + final List Function(dynamic) options; final void Function(dynamic)? onTapEntry; const RowItem({ diff --git a/lib/screens/home/top_items/top_items_lists.dart b/lib/screens/home/top_items/top_items_lists.dart index 7f230fb..758a0b6 100644 --- a/lib/screens/home/top_items/top_items_lists.dart +++ b/lib/screens/home/top_items/top_items_lists.dart @@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/home/top_items/top_items_section.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -30,6 +31,7 @@ class TopItemsLists extends StatelessWidget { final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); + final clientsProvider = Provider.of(context); List bottom = [ Padding( @@ -96,10 +98,53 @@ class TopItemsLists extends StatelessWidget { } } - void copyValueClipboard(value) { + void copyValueClipboard(dynamic value) { copyToClipboard(value: value, successMessage: AppLocalizations.of(context)!.copiedClipboard); } + void blockUnblockClient(dynamic client) async { + final currentList = clientsProvider.checkClientList(client); + final newList = currentList == AccessSettingsList.allowed || currentList == null + ? AccessSettingsList.disallowed + : AccessSettingsList.allowed; + + ProcessModal processModal = ProcessModal(); + processModal.open( + currentList == AccessSettingsList.allowed || currentList == null + ? AppLocalizations.of(context)!.blockingClient + : AppLocalizations.of(context)!.unblockingClient + ); + + final result = await clientsProvider.addClientList(client, newList); + if (!context.mounted) return; + + processModal.close(); + + if (result.successful == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientAddedSuccessfully, + color: Colors.green + ); + } + else if (result.successful == false && result.content == 'client_another_list') { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientAnotherList, + color: Colors.red + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: newList == AccessSettingsList.allowed || newList == AccessSettingsList.disallowed + ? AppLocalizations.of(context)!.clientNotRemoved + : AppLocalizations.of(context)!.domainNotAdded, + color: Colors.red + ); + } + } + return Column( children: order.asMap().entries.map((item) { switch (item.value) { @@ -113,16 +158,16 @@ class TopItemsLists extends StatelessWidget { withChart: true, withProgressBar: true, buildValue: (v) => v.toString(), - menuOptions: [ + menuOptions: (v) => [ MenuOption( title: AppLocalizations.of(context)!.blockDomain, icon: Icons.block_rounded, - action: (v) => blockUnblock(domain: v.toString(), newStatus: 'block') + action: () => blockUnblock(domain: v.toString(), newStatus: 'block') ), MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: copyValueClipboard + action: () => copyValueClipboard(v) ), ], onTapEntry: (v) => filterDomainLogs(value: v.toString()), @@ -141,16 +186,16 @@ class TopItemsLists extends StatelessWidget { withChart: true, withProgressBar: true, buildValue: (v) => v.toString(), - menuOptions: [ + menuOptions: (v) => [ MenuOption( title: AppLocalizations.of(context)!.unblockDomain, icon: Icons.check_rounded, - action: (v) => blockUnblock(domain: v, newStatus: 'unblock') + action: () => blockUnblock(domain: v, newStatus: 'unblock') ), MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: copyValueClipboard + action: () => copyValueClipboard(v) ) ], onTapEntry: (v) => filterDomainLogs(value: v), @@ -169,12 +214,21 @@ class TopItemsLists extends StatelessWidget { withChart: true, withProgressBar: true, buildValue: (v) => v.toString(), - menuOptions: [ + menuOptions: (v) => [ + if (clientsProvider.clients?.clientsAllowedBlocked != null) MenuOption( + title: clientsProvider.checkClientList(v) == AccessSettingsList.allowed || clientsProvider.checkClientList(v) == null + ? AppLocalizations.of(context)!.blockClient + : AppLocalizations.of(context)!.unblockClient, + icon: clientsProvider.checkClientList(v) == AccessSettingsList.allowed || clientsProvider.checkClientList(v) == null + ? Icons.block_rounded + : Icons.check_rounded, + action: () => blockUnblockClient(v) + ), MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: copyValueClipboard - ) + action: () => copyValueClipboard(v) + ), ], onTapEntry: (v) => filterClientLogs(value: v), ), @@ -193,11 +247,11 @@ class TopItemsLists extends StatelessWidget { withChart: true, withProgressBar: true, buildValue: (v) => v.toString(), - menuOptions: [ + menuOptions: (v) => [ MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: copyValueClipboard + action: () => copyValueClipboard(v) ) ], ), @@ -217,11 +271,11 @@ class TopItemsLists extends StatelessWidget { withChart: false, withProgressBar: false, buildValue: (v) => "${doubleFormat(v*1000, Platform.localeName)} ms", - menuOptions: [ + menuOptions: (v) => [ MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: copyValueClipboard + action: () => copyValueClipboard(v) ) ], ), diff --git a/lib/screens/home/top_items/top_items_screen.dart b/lib/screens/home/top_items/top_items_screen.dart index f2f9b4d..1070953 100644 --- a/lib/screens/home/top_items/top_items_screen.dart +++ b/lib/screens/home/top_items/top_items_screen.dart @@ -24,7 +24,7 @@ class TopItemsScreen extends StatefulWidget { final List> data; final bool withProgressBar; final String Function(dynamic) buildValue; - final List options; + final List Function(dynamic) options; final void Function(dynamic)? onTapEntry; final bool isFullscreen; @@ -263,7 +263,7 @@ class _TopItemsScreenState extends State { class _Content extends StatelessWidget { final List> screenData; final bool? isClient; - final List options; + final List Function(dynamic) options; final bool withProgressBar; final void Function(dynamic)? onTapEntry; final String Function(dynamic) buildValue; diff --git a/lib/screens/home/top_items/top_items_section.dart b/lib/screens/home/top_items/top_items_section.dart index f084b3f..bc021cf 100644 --- a/lib/screens/home/top_items/top_items_section.dart +++ b/lib/screens/home/top_items/top_items_section.dart @@ -21,7 +21,7 @@ class TopItemsSection extends StatefulWidget { final bool withChart; final bool withProgressBar; final String Function(dynamic) buildValue; - final List menuOptions; + final List Function(dynamic) menuOptions; final void Function(dynamic)? onTapEntry; const TopItemsSection({ @@ -350,7 +350,7 @@ class _ItemsList extends StatelessWidget { final HomeTopItems type; final bool showChart; final String Function(dynamic) buildValue; - final List menuOptions; + final List Function(dynamic) menuOptions; final void Function(dynamic)? onTapEntry; const _ItemsList({ diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index af130e2..6f4ea6b 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -128,7 +128,7 @@ class LogTile extends StatelessWidget { child: OptionsMenu( onTap: (_) => onLogTap(log), borderRadius: BorderRadius.circular(28), - options: [ + options: (v) => [ if (log.question.name != null) MenuOption( title: domainBlocked == true ? AppLocalizations.of(context)!.unblockDomain @@ -136,7 +136,7 @@ class LogTile extends StatelessWidget { icon: domainBlocked == true ? Icons.check_rounded : Icons.block_rounded, - action: (_) => blockUnblock( + action: () => blockUnblock( domain: log.question.name!, newStatus: domainBlocked == true ? 'unblock' : 'block' ) @@ -144,7 +144,7 @@ class LogTile extends StatelessWidget { MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: (v) => copyToClipboard(value: v, successMessage: AppLocalizations.of(context)!.copiedClipboard) + action: () => copyToClipboard(value: v, successMessage: AppLocalizations.of(context)!.copiedClipboard) ) ], child: Container( @@ -306,7 +306,7 @@ class LogTile extends StatelessWidget { color: Colors.transparent, child: OptionsMenu( onTap: (_) => onLogTap(log), - options: [ + options: (_) => [ if (log.question.name != null) MenuOption( title: domainBlocked == true ? AppLocalizations.of(context)!.unblockDomain @@ -314,7 +314,7 @@ class LogTile extends StatelessWidget { icon: domainBlocked == true ? Icons.check_rounded : Icons.block_rounded, - action: (_) => blockUnblock( + action: () => blockUnblock( domain: log.question.name!, newStatus: domainBlocked == true ? 'unblock' : 'block' ) @@ -322,7 +322,7 @@ class LogTile extends StatelessWidget { if (log.question.name != null) MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: (_) => copyToClipboard( + action: () => copyToClipboard( value: log.question.name!, successMessage: AppLocalizations.of(context)!.copiedClipboard ) diff --git a/lib/widgets/options_menu.dart b/lib/widgets/options_menu.dart index 861edab..ad91b33 100644 --- a/lib/widgets/options_menu.dart +++ b/lib/widgets/options_menu.dart @@ -11,7 +11,7 @@ import 'package:adguard_home_manager/models/menu_option.dart'; class OptionsMenu extends StatelessWidget { final Widget child; - final List options; + final List Function(dynamic) options; final dynamic value; final BorderRadius? borderRadius; final void Function(dynamic)? onTap; @@ -40,11 +40,11 @@ class OptionsMenu extends StatelessWidget { return Material( color: Colors.transparent, child: ContextMenuArea( - builder: (context) => options.map((opt) => CustomListTile( + builder: (context) => options(value).map((opt) => CustomListTile( title: opt.title, icon: opt.icon, onTap: () { - opt.action(value); + opt.action(); Navigator.pop(context); }, )).toList(), @@ -64,7 +64,7 @@ class OptionsMenu extends StatelessWidget { } class _OptionsModal extends StatelessWidget { - final List options; + final List Function(dynamic) options; final dynamic value; const _OptionsModal({ @@ -98,12 +98,12 @@ class _OptionsModal extends StatelessWidget { ), child: SingleChildScrollView( child: Wrap( - children: options.map((opt) => CustomListTileDialog( + children: options(value).map((opt) => CustomListTileDialog( title: opt.title, icon: opt.icon, onTap: () { Navigator.pop(context); - opt.action(value); + opt.action(); }, )).toList() ), From 313b76740a627eef4b67497a0e0ead63f6b9f6b3 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 18 Dec 2023 02:30:32 +0100 Subject: [PATCH 471/676] Added cache configuration and changed added client validation --- lib/l10n/app_en.arb | 9 +- lib/l10n/app_es.arb | 9 +- lib/models/clients.dart | 10 +- .../client/blocked_services_section.dart | 10 +- lib/screens/clients/client/client_form.dart | 109 ++++---- lib/screens/clients/client/client_screen.dart | 255 +++++++++++++----- .../client/client_screen_functions.dart | 22 +- .../clients/client/identifiers_section.dart | 16 +- lib/screens/clients/client/settings_tile.dart | 9 +- lib/screens/clients/client/tags_section.dart | 6 +- .../client/upstream_servers_section.dart | 14 +- 11 files changed, 302 insertions(+), 167 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 7354d9c..6bf0c27 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -718,5 +718,12 @@ "noData": "No data", "unblockClient": "Unblock 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" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 78d518f..a6a222b 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -718,5 +718,12 @@ "noData": "No hay datos", "unblockClient": "Desbloquear 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" } \ No newline at end of file diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 5808391..67740bd 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -89,6 +89,8 @@ class Client { final SafeSearch? safeSearch; final bool? ignoreQuerylog; final bool? ignoreStatistics; + final bool? upstreamsCacheEnabled; + final int? upstreamsCacheSize; Client({ required this.name, @@ -104,6 +106,8 @@ class Client { required this.safeSearch, required this.ignoreQuerylog, required this.ignoreStatistics, + required this.upstreamsCacheEnabled, + required this.upstreamsCacheSize, }); factory Client.fromJson(Map json) => Client( @@ -121,7 +125,9 @@ class Client { ? SafeSearch.fromJson(json["safe_search"]) : null, ignoreQuerylog: json["ignore_querylog"], - ignoreStatistics: json["ignore_statistics"] + ignoreStatistics: json["ignore_statistics"], + upstreamsCacheEnabled: json["upstreams_cache_enabled"], + upstreamsCacheSize: json["upstreams_cache_size"] ); Map toJson() => { @@ -138,5 +144,7 @@ class Client { "use_global_settings": useGlobalSettings, "ignore_querylog": ignoreQuerylog, "ignore_statistics": ignoreStatistics, + "upstreams_cache_enabled": upstreamsCacheEnabled, + "upstreams_cache_size": upstreamsCacheSize }; } \ No newline at end of file diff --git a/lib/screens/clients/client/blocked_services_section.dart b/lib/screens/clients/client/blocked_services_section.dart index f6effd4..4a7fc11 100644 --- a/lib/screens/clients/client/blocked_services_section.dart +++ b/lib/screens/clients/client/blocked_services_section.dart @@ -22,7 +22,7 @@ class BlockedServicesSection extends StatelessWidget { return Column( children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Material( color: Theme.of(context).colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(28), @@ -31,8 +31,8 @@ class BlockedServicesSection extends StatelessWidget { borderRadius: BorderRadius.circular(28), child: Padding( padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 5 + horizontal: 16, + vertical: 6 ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -56,7 +56,7 @@ class BlockedServicesSection extends StatelessWidget { ), ), ), - const SizedBox(height: 10), + const SizedBox(height: 12), Material( color: Colors.transparent, child: InkWell( @@ -69,7 +69,7 @@ class BlockedServicesSection extends StatelessWidget { : null, child: Padding( padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 24 + vertical: 8, horizontal: 32 ), child: Row( children: [ diff --git a/lib/screens/clients/client/client_form.dart b/lib/screens/clients/client/client_form.dart index 5c164af..e127466 100644 --- a/lib/screens/clients/client/client_form.dart +++ b/lib/screens/clients/client/client_form.dart @@ -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_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/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/section_label.dart'; @@ -22,7 +20,6 @@ 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; @@ -50,13 +47,17 @@ class ClientForm extends StatelessWidget { final void Function(bool) updateIgnoreClientQueryLog; final bool ignoreClientStatistics; 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({ super.key, required this.isFullScreen, required this.client, required this.nameController, - required this.updateValidValues, required this.identifiersControllers, required this.selectedTags, required this.useGlobalSettingsFiltering, @@ -84,26 +85,24 @@ class ClientForm extends StatelessWidget { required this.ignoreClientStatistics, required this.updateIgnoreClientQueryLog, required this.updateIgnoreClientStatistics, + required this.enableDnsCache, + required this.updateEnableDnsCache, + required this.dnsCacheField, + required this.dnsCacheError, + required this.updateDnsCacheError, }); @override Widget build(BuildContext context) { - return ListView( - padding: const EdgeInsets.only(top: 0), + return Column( children: [ - if (isFullScreen == true) const SizedBox(height: 24), - if (isFullScreen == false) const SizedBox(height: 6), + const SizedBox(height: 8), Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), + padding: const EdgeInsets.symmetric(horizontal: 16), child: TextFormField( enabled: client != null ? false : true, controller: nameController, - onChanged: (_) => updateValidValues( - checkValidValues( - identifiersControllers: identifiersControllers, - nameController: nameController - ) - ), + onChanged: (_) => {}, decoration: InputDecoration( prefixIcon: const Icon(Icons.badge_rounded), border: const OutlineInputBorder( @@ -117,7 +116,7 @@ class ClientForm extends StatelessWidget { ), SectionLabel( label: AppLocalizations.of(context)!.tags, - padding: const EdgeInsets.all(24), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), ), TagsSection( selectedTags: selectedTags, @@ -127,28 +126,17 @@ class ClientForm extends StatelessWidget { identifiersControllers: identifiersControllers, onUpdateIdentifiersControllers: (c) { updateIdentifiersControllers(c); - updateValidValues( - checkValidValues( - nameController: nameController, - identifiersControllers: identifiersControllers - ) - ); }, - onCheckValidValues: () => updateValidValues( - checkValidValues( - identifiersControllers: identifiersControllers, - nameController: nameController - ) - ), + onCheckValidValues: () => {} ), SectionLabel( label: AppLocalizations.of(context)!.settings, padding: const EdgeInsets.only( - left: 24, right: 24, top: 12, bottom: 24 + left: 16, right: 16, top: 12, bottom: 24 ) ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Material( color: Theme.of(context).colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(28), @@ -157,8 +145,8 @@ class ClientForm extends StatelessWidget { borderRadius: BorderRadius.circular(28), child: Padding( padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 5 + horizontal: 16, + vertical: 6 ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -182,7 +170,7 @@ class ClientForm extends StatelessWidget { ), ), ), - const SizedBox(height: 10), + const SizedBox(height: 8), SettingsTile( label: AppLocalizations.of(context)!.enableFiltering, value: enableFiltering, @@ -204,7 +192,7 @@ class ClientForm extends StatelessWidget { CustomListTile( title: AppLocalizations.of(context)!.safeSearch, padding: const EdgeInsets.symmetric( - horizontal: 42, + horizontal: 34, vertical: 16 ), trailing: Padding( @@ -228,15 +216,15 @@ class ClientForm extends StatelessWidget { ), SectionLabel( label: AppLocalizations.of(context)!.queryLogsAndStatistics, - padding: const EdgeInsets.all(24), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), ), CustomSwitchListTile( title: AppLocalizations.of(context)!.ignoreClientQueryLog, value: ignoreClientQueryLog, onChanged: updateIgnoreClientQueryLog, padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 4 + horizontal: 16, + vertical: 6 ), ), CustomSwitchListTile( @@ -244,13 +232,13 @@ class ClientForm extends StatelessWidget { value: ignoreClientStatistics, onChanged: updateIgnoreClientStatistics, padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 4 + horizontal: 16, + vertical: 6 ), ), SectionLabel( label: AppLocalizations.of(context)!.blockedServices, - padding: const EdgeInsets.all(24), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), ), BlockedServicesSection( useGlobalSettingsServices: useGlobalSettingsServices, @@ -260,15 +248,40 @@ class ClientForm extends StatelessWidget { ), UpstreamServersSection( upstreamServers: upstreamServers, - onCheckValidValues: () => updateValidValues( - checkValidValues( - identifiersControllers: identifiersControllers, - nameController: nameController - ) - ), + onCheckValidValues: () => {}, 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, + ), + ), ], ); } diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index 9a16e1a..f41de69 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -39,6 +39,8 @@ class ClientScreen extends StatefulWidget { } class _ClientScreenState extends State { + final _scrollController = ScrollController(); + final Uuid uuid = const Uuid(); bool validValues = false; @@ -76,6 +78,15 @@ class _ClientScreenState extends State { bool _ignoreClientQueryLog = false; bool _ignoreClientStatistics = false; + bool _enableDnsCache = false; + final _dnsCacheField = TextEditingController(); + String? _dnsCacheError; + + // VALIDATIONS + bool _nameValid = true; + bool _identifiersValid = true; + bool _dnsCacheValid = true; + void enableDisableGlobalSettingsFiltering() { if (useGlobalSettingsFiltering == true) { setState(() { @@ -125,6 +136,10 @@ class _ClientScreenState extends State { )).toList(); _ignoreClientQueryLog = widget.client!.ignoreQuerylog ?? false; _ignoreClientStatistics = widget.client!.ignoreStatistics ?? false; + _enableDnsCache = widget.client!.upstreamsCacheEnabled ?? false; + _dnsCacheField.text = widget.client!.upstreamsCacheSize != null + ? widget.client!.upstreamsCacheSize.toString() + : ""; } super.initState(); } @@ -147,20 +162,37 @@ class _ClientScreenState extends State { upstreams: List.from(upstreamServers.map((e) => e.controller.text)), tags: selectedTags, ignoreQuerylog: _ignoreClientQueryLog, - ignoreStatistics: _ignoreClientStatistics + ignoreStatistics: _ignoreClientStatistics, + upstreamsCacheEnabled: _enableDnsCache, + upstreamsCacheSize: _dnsCacheField.text != "" + ? int.parse(_dnsCacheField.text) + : null ); 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 actions() { return [ IconButton( - onPressed: validValues == true - ? () { - createClient(); - Navigator.pop(context); - } - : null, + onPressed: validateValues, icon: const Icon(Icons.save_rounded), tooltip: AppLocalizations.of(context)!.save, ), @@ -193,38 +225,52 @@ class _ClientScreenState extends State { actions: actions(), ), body: SafeArea( - child: 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), - ignoreClientQueryLog: _ignoreClientQueryLog, - ignoreClientStatistics: _ignoreClientStatistics, - updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v), - updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v), + child: ListView( + controller: _scrollController, + children: [ + if (!_nameValid || !_identifiersValid || !_dnsCacheValid) _Errors( + nameValid: _nameValid, + identifiersValid: _identifiersValid, + dnsCacheValid: _dnsCacheValid + ), + ClientForm( + isFullScreen: true, + client: widget.client, + nameController: nameController, + 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), + ignoreClientQueryLog: _ignoreClientQueryLog, + ignoreClientStatistics: _ignoreClientStatistics, + updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v), + updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v), + enableDnsCache: _enableDnsCache, + updateEnableDnsCache: (v) => setState(() => _enableDnsCache = v), + dnsCacheField: _dnsCacheField, + dnsCacheError: _dnsCacheError, + updateDnsCacheError: (v) => setState(() => _dnsCacheError = v) + ), + ], ), ), ), @@ -264,38 +310,52 @@ class _ClientScreenState extends State { ), ), Flexible( - 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), - ignoreClientQueryLog: _ignoreClientQueryLog, - ignoreClientStatistics: _ignoreClientStatistics, - updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v), - updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v), + child: ListView( + controller: _scrollController, + children: [ + if (!_nameValid || !_identifiersValid || !_dnsCacheValid) _Errors( + nameValid: _nameValid, + identifiersValid: _identifiersValid, + dnsCacheValid: _dnsCacheValid + ), + ClientForm( + isFullScreen: false, + client: widget.client, + nameController: nameController, + 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), + ignoreClientQueryLog: _ignoreClientQueryLog, + ignoreClientStatistics: _ignoreClientStatistics, + updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = 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 { } } +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 + ), + ), + ], + ), + ), + ); + } +} \ 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 1f292c6..f0338a1 100644 --- a/lib/screens/clients/client/client_screen_functions.dart +++ b/lib/screens/clients/client/client_screen_functions.dart @@ -74,22 +74,6 @@ void openSafeSearchModal({ ); } -bool checkValidValues({ - required TextEditingController nameController, - required List identifiersControllers -}) { - if ( - nameController.text != '' && - identifiersControllers.isNotEmpty && - identifiersControllers[0].controller.text != '' - ) { - return true; - } - else { - return false; - } -} - void openClientFormModal({ required BuildContext context, required double width, @@ -123,4 +107,10 @@ void openClientFormModal({ onDelete: onDelete, ), ); +} + +bool validateNumber(String value) { + if (value == "") return true; + final regexp = RegExp(r'^\d+$'); + return regexp.hasMatch(value); } \ No newline at end of file diff --git a/lib/screens/clients/client/identifiers_section.dart b/lib/screens/clients/client/identifiers_section.dart index 91a56eb..c5f9d4c 100644 --- a/lib/screens/clients/client/identifiers_section.dart +++ b/lib/screens/clients/client/identifiers_section.dart @@ -11,11 +11,11 @@ class IdentifiersSection extends StatefulWidget { final void Function() onCheckValidValues; const IdentifiersSection({ - Key? key, + super.key, required this.identifiersControllers, required this.onUpdateIdentifiersControllers, required this.onCheckValidValues - }) : super(key: key); + }); @override State createState() => _IdentifiersSectionState(); @@ -34,11 +34,11 @@ class _IdentifiersSectionState extends State { SectionLabel( label: AppLocalizations.of(context)!.identifiers, padding: const EdgeInsets.only( - left: 24, right: 24, top: 24, bottom: 12 + left: 16, right: 16, top: 24, bottom: 12 ) ), Padding( - padding: const EdgeInsets.only(right: 20), + padding: const EdgeInsets.only(right: 10), child: IconButton( onPressed: () => widget.onUpdateIdentifiersControllers([ ...widget.identifiersControllers, @@ -54,7 +54,7 @@ class _IdentifiersSectionState extends State { ), if (widget.identifiersControllers.isNotEmpty) ...widget.identifiersControllers.map((controller) => Padding( padding: const EdgeInsets.only( - top: 12, bottom: 12, left: 24, right: 20 + top: 12, bottom: 12, left: 16, right: 10 ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -75,9 +75,9 @@ class _IdentifiersSectionState extends State { ), ), ), - const SizedBox(width: 16), + const SizedBox(width: 12), Padding( - padding: const EdgeInsets.only(bottom: 25), + padding: const EdgeInsets.only(bottom: 24), child: IconButton( onPressed: () => widget.onUpdateIdentifiersControllers( widget.identifiersControllers.where((e) => e.id != controller.id).toList() @@ -87,7 +87,7 @@ class _IdentifiersSectionState extends State { ) ], ), - )).toList(), + )), if (widget.identifiersControllers.isEmpty) Container( padding: const EdgeInsets.symmetric(vertical: 16), child: Text( diff --git a/lib/screens/clients/client/settings_tile.dart b/lib/screens/clients/client/settings_tile.dart index c2d6ede..9b26b2c 100644 --- a/lib/screens/clients/client/settings_tile.dart +++ b/lib/screens/clients/client/settings_tile.dart @@ -7,12 +7,12 @@ class SettingsTile extends StatelessWidget { final bool useGlobalSettingsFiltering; const SettingsTile({ - Key? key, + super.key, required this.label, required this.value, this.onChange, required this.useGlobalSettingsFiltering - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -23,10 +23,7 @@ class SettingsTile extends StatelessWidget { ? value != null ? () => onChange!(!value!) : null : null, child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 42, - vertical: 5 - ), + padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 6), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/screens/clients/client/tags_section.dart b/lib/screens/clients/client/tags_section.dart index a6fa67c..8d63a0e 100644 --- a/lib/screens/clients/client/tags_section.dart +++ b/lib/screens/clients/client/tags_section.dart @@ -7,10 +7,10 @@ class TagsSection extends StatelessWidget { final void Function(List) onTagsSelected; const TagsSection({ - Key? key, + super.key, required this.selectedTags, required this.onTagsSelected - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -24,7 +24,7 @@ class TagsSection extends StatelessWidget { ) , child: Padding( padding: const EdgeInsets.symmetric( - vertical: 0, horizontal: 24 + vertical: 0, horizontal: 16 ), child: Row( children: [ diff --git a/lib/screens/clients/client/upstream_servers_section.dart b/lib/screens/clients/client/upstream_servers_section.dart index 97c8974..56fb7aa 100644 --- a/lib/screens/clients/client/upstream_servers_section.dart +++ b/lib/screens/clients/client/upstream_servers_section.dart @@ -11,11 +11,11 @@ class UpstreamServersSection extends StatefulWidget { final void Function(List) onUpdateUpstreamServers; const UpstreamServersSection({ - Key? key, + super.key, required this.upstreamServers, required this.onCheckValidValues, required this.onUpdateUpstreamServers - }) : super(key: key); + }); @override State createState() => _UpstreamServersSectionState(); @@ -33,10 +33,10 @@ class _UpstreamServersSectionState extends State { children: [ SectionLabel( label: AppLocalizations.of(context)!.upstreamServers, - padding: const EdgeInsets.all(24), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), ), Padding( - padding: const EdgeInsets.only(right: 20), + padding: const EdgeInsets.only(right: 12), child: IconButton( onPressed: () => setState(() => widget.upstreamServers.add( ControllerListItem( @@ -50,7 +50,7 @@ class _UpstreamServersSectionState extends State { ], ), 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( padding: const EdgeInsets.only(bottom: 20), child: Row( @@ -71,7 +71,7 @@ class _UpstreamServersSectionState extends State { ), ), ), - const SizedBox(width: 16), + const SizedBox(width: 12), IconButton( onPressed: () => widget.onUpdateUpstreamServers( widget.upstreamServers.where((e) => e.id != controller.id).toList() @@ -81,7 +81,7 @@ class _UpstreamServersSectionState extends State { ], ), ), - )).toList(), + )), if (widget.upstreamServers.isEmpty) Container( padding: const EdgeInsets.symmetric(vertical: 16), child: Column( From b7943f53057b422b41d09e0865461b46fd010001 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 18 Dec 2023 02:31:09 +0100 Subject: [PATCH 472/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 9bd3484..554b898 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.13.0+117 +version: 2.14.0-beta.1+118 environment: sdk: '>=2.18.1 <3.0.0' From 62daa56b1be646868cf39672b4066b7a01df0a6e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 20 Dec 2023 15:45:42 +0100 Subject: [PATCH 473/676] Fix copy log domain --- lib/screens/logs/log_tile.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 6f4ea6b..f5db5ee 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -128,7 +128,7 @@ class LogTile extends StatelessWidget { child: OptionsMenu( onTap: (_) => onLogTap(log), borderRadius: BorderRadius.circular(28), - options: (v) => [ + options: (_) => [ if (log.question.name != null) MenuOption( title: domainBlocked == true ? AppLocalizations.of(context)!.unblockDomain @@ -141,10 +141,10 @@ class LogTile extends StatelessWidget { newStatus: domainBlocked == true ? 'unblock' : 'block' ) ), - MenuOption( + if (log.question.name != null) MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, - action: () => copyToClipboard(value: v, successMessage: AppLocalizations.of(context)!.copiedClipboard) + action: () => copyToClipboard(value: log.question.name!, successMessage: AppLocalizations.of(context)!.copiedClipboard) ) ], child: Container( From 565494e3f992582515b4f48ab4426169a246a58d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 20 Dec 2023 15:47:12 +0100 Subject: [PATCH 474/676] Fix parse ttl client --- lib/screens/settings/dns/dns_server_settings.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index ba04422..b13f593 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -156,7 +156,7 @@ class _DnsServerSettingsScreenState extends State { "blocking_mode": blockingMode, "blocking_ipv4": ipv4controller.text, "blocking_ipv6": ipv6controller.text, - "blocked_response_ttl": int.parse(_ttlController.text) + "blocked_response_ttl": int.tryParse(_ttlController.text) }); processModal.close(); From 3c42f790bda6498e61c78bf1e7ec9c36f7202155 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 20 Dec 2023 15:50:39 +0100 Subject: [PATCH 475/676] Fix --- lib/services/api_client.dart | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index c2e1fca..b45622a 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -39,10 +39,17 @@ class ApiClientV2 { Future getServerVersion() async { final result = await HttpRequestClient.get(urlPath: '/status', server: server); if (result.successful == true) { - return ApiResponse( - successful: true, - content: jsonDecode(result.body!)['version'] - ); + try { + return ApiResponse( + successful: true, + content: jsonDecode(result.body!)['version'] + ); + } on FormatException { + return const ApiResponse(successful: false); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + return const ApiResponse(successful: false); + } } else { return const ApiResponse(successful: false); From af2b9f2704430c27493307ef645761d52258bdc1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 20 Dec 2023 15:51:17 +0100 Subject: [PATCH 476/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 554b898..5edc2c7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.14.0-beta.1+118 +version: 2.14.0+119 environment: sdk: '>=2.18.1 <3.0.0' From 9a1cefdc26aa9117552022ab34405f3f5f759e53 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 20 Dec 2023 18:23:52 +0100 Subject: [PATCH 477/676] Added redirect to https warning --- lib/l10n/app_en.arb | 3 ++- lib/l10n/app_es.arb | 3 ++- lib/widgets/add_server/add_server_modal.dart | 24 +++++++++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 6bf0c27..3778a60 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -725,5 +725,6 @@ "nameInvalid": "Name is required", "oneIdentifierRequired": "At least one identifier is required", "dnsCacheNumber": "DNS cache size must be a number", - "errors": "Errors" + "errors": "Errors", + "redirectHttpsWarning": "If you have enabled \"Redirect to HTTPS automatically\" on your AdGuard Home server, you must select an HTTPS connection and use the HTTPS port of your server." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index a6a222b..03e3440 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -725,5 +725,6 @@ "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" + "errors": "Errores", + "redirectHttpsWarning": "Si tienes activado \"Redireccionar a HTTPS automáticamente\" en tu servidor AdGuard Home, debes seleccionar una conexión HTTPS y utilizar el puerto de HTTPS de tu servidor." } \ No newline at end of file diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index e30d1e0..ac7d4a1 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -127,6 +127,7 @@ class _AddServerModalState extends State { if (status == AuthStatus.manyAttepts) return AppLocalizations.of(context)!.tooManyAttempts; if (status == AuthStatus.socketException || status == AuthStatus.timeoutException) return AppLocalizations.of(context)!.cantReachServer; if (status == AuthStatus.serverError) return AppLocalizations.of(context)!.serverError; + if (status == AuthStatus.handshakeException) return AppLocalizations.of(context)!.sslError; return AppLocalizations.of(context)!.unknownError; } @@ -429,6 +430,24 @@ class _AddServerModalState extends State { horizontal: 24, ), ), + Card( + margin: const EdgeInsets.only( + top: 16, left: 24, right: 24 + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.warning_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 16), + Flexible(child: Text(AppLocalizations.of(context)!.redirectHttpsWarning)) + ], + ), + ), + ), if (connectionType == ConnectionType.https) Card( margin: const EdgeInsets.only( top: 16, left: 24, right: 24 @@ -437,7 +456,10 @@ class _AddServerModalState extends State { padding: const EdgeInsets.all(16), child: Row( children: [ - const Icon(Icons.info_rounded), + Icon( + Icons.info_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), const SizedBox(width: 16), Flexible(child: Text(AppLocalizations.of(context)!.sslWarning)) ], From 0980641746bc77bfea7c4a5696080bf2362fa130 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 16 Jan 2024 18:25:20 +0100 Subject: [PATCH 478/676] Updated libraries --- macos/Podfile.lock | 14 +++--- pubspec.lock | 120 ++++++++++++++++++++++++--------------------- pubspec.yaml | 2 +- 3 files changed, 72 insertions(+), 64 deletions(-) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 32c37ec..9d30918 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -9,13 +9,13 @@ PODS: - FMDB/standard (2.7.5) - package_info_plus (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.15.2): - - SentryPrivate (= 8.15.2) + - Sentry/HybridSDK (8.17.2): + - SentryPrivate (= 8.17.2) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.15.2) - - SentryPrivate (8.15.2) + - Sentry/HybridSDK (= 8.17.2) + - SentryPrivate (8.17.2) - sqflite (0.0.2): - FlutterMacOS - FMDB (>= 2.7.5) @@ -83,9 +83,9 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - Sentry: 6f5742b4c47c17c9adcf265f6f328cf4a0ed1923 - sentry_flutter: 2c309a1d4b45e59d02cfa15795705687f1e2081b - SentryPrivate: b2f7996f37781080f04a946eb4e377ff63c64195 + Sentry: 64a9f9c3637af913adcf53deced05bbe452d1410 + sentry_flutter: 57912cf425e09398bdf47f38842a1fcb9836f1be + SentryPrivate: 024c6fed507ac39ae98e6d087034160f942920d5 sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea sqlite3: 6e2d4a4879854d0ec86b476bf3c3e30870bac273 sqlite3_flutter_libs: a25f3a0f522fdcd8fef6a4a50a3d681dd43d8dea diff --git a/pubspec.lock b/pubspec.lock index 963ce6f..cf61106 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: "direct main" description: name: animations - sha256: "708e4b68c23228c264b038fe7003a2f5d01ce85fc64d8cae090e86b27fcea6c5" + sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb url: "https://pub.dev" source: hosted - version: "2.0.10" + version: "2.0.11" ansicolor: dependency: transitive description: @@ -29,10 +29,10 @@ packages: dependency: transitive description: name: archive - sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b" + sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" url: "https://pub.dev" source: hosted - version: "3.4.9" + version: "3.4.10" args: dependency: transitive description: @@ -77,10 +77,10 @@ packages: dependency: transitive description: name: cli_util - sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 url: "https://pub.dev" source: hosted - version: "0.4.0" + version: "0.4.1" clock: dependency: transitive description: @@ -157,10 +157,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: "8b8bd1d798bd393e11eddeaa8ae95b12ff028bf7d5998fc5d003488cd5f4ce2f" + sha256: a866f1f8947bfdaf674d7928e769eac7230388a2e7a2542824fad4bb5b87be3b url: "https://pub.dev" source: hosted - version: "1.6.8" + version: "1.6.9" equatable: dependency: transitive description: @@ -201,14 +201,22 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" fl_chart: dependency: "direct main" description: name: fl_chart - sha256: "5a74434cc83bf64346efb562f1a06eefaf1bcb530dc3d96a104f631a1eff8d79" + sha256: fe6fec7d85975a99c73b9515a69a6e291364accfa0e4a5b3ce6de814d74b9a1c url: "https://pub.dev" source: hosted - version: "0.65.0" + version: "0.66.0" flutter: dependency: "direct main" description: flutter @@ -263,18 +271,18 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "35108526a233cc0755664d445f8a6b4b61e6f8fe993b3658b80b4a26827fc196" + sha256: "30088ce826b5b9cfbf9e8bece34c716c8a59fa54461dcae1e4ac01a94639e762" url: "https://pub.dev" source: hosted - version: "0.6.18+2" + version: "0.6.18+3" flutter_native_splash: dependency: "direct dev" description: name: flutter_native_splash - sha256: "141b20f15a2c4fe6e33c49257ca1bc114fc5c500b04fcbc8d75016bb86af672f" + sha256: "9cdb5d9665dab5d098dc50feab74301c2c228cd02ca25c9b546ab572cebcd6af" url: "https://pub.dev" source: hosted - version: "2.3.8" + version: "2.3.9" flutter_reorderable_list: dependency: "direct main" description: @@ -346,10 +354,10 @@ packages: dependency: transitive description: name: image - sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271" + sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d" url: "https://pub.dev" source: hosted - version: "4.1.3" + version: "4.1.4" intl: dependency: "direct main" description: @@ -490,18 +498,18 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.1.8" pointycastle: dependency: transitive description: name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" url: "https://pub.dev" source: hosted - version: "3.7.3" + version: "3.7.4" provider: dependency: "direct main" description: @@ -522,18 +530,18 @@ packages: dependency: transitive description: name: sentry - sha256: e7ded42974bac5f69e4ca4ddc57d30499dd79381838f24b7e8fd9aa4139e7b79 + sha256: "89e426587b0879e53c46a0aae0eb312696d9d2d803ba14b252a65cc24b1416a2" url: "https://pub.dev" source: hosted - version: "7.13.2" + version: "7.14.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: d6f55ec7a1f681784165021f749007712a72ff57eadf91e963331b6ae326f089 + sha256: fd089ee4e75a927be037c56815a0a54af5a519f52b803a5ffecb589bb36e2401 url: "https://pub.dev" source: hosted - version: "7.13.2" + version: "7.14.0" sky_engine: dependency: transitive description: flutter @@ -567,26 +575,26 @@ packages: dependency: transitive description: name: sqflite_common - sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 + sha256: "76db4d324c8cbb16ca5b60ad2f3d25cec953107c93ae65aafa480d3e6fb69f14" url: "https://pub.dev" source: hosted - version: "2.5.0+2" + version: "2.5.2-1" sqflite_common_ffi: dependency: "direct main" description: name: sqflite_common_ffi - sha256: "873677ee78738a723d1ded4ccb23980581998d873d30ee9c331f6a81748663ff" + sha256: d0e3f0d04fdf668e57db8db1df758f56c4193cb429092c708e7bfcc6ab04b27e url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" sqlite3: dependency: transitive description: name: sqlite3 - sha256: "8922805564b78eb7aa9386c10056d377a541ac7270dc6a1589176277ebb4d15d" + sha256: c4a4c5a4b2a32e2d0f6837b33d7c91a67903891a5b7dbe706cf4b1f6b0c798c5 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" sqlite3_flutter_libs: dependency: "direct main" description: @@ -631,10 +639,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.0+1" term_glyph: dependency: transitive description: @@ -671,34 +679,34 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86 + sha256: d25bb0ca00432a5e1ee40e69c36c85863addf7cc45e433769d61bed3fe81fd96 url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.2.3" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.2.2" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.2.4" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "9f2d390e096fdbe1e6e6256f97851e51afc2d9c423d3432f1d6a02a8a9a8b9fd" + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" url_launcher_macos: dependency: transitive description: @@ -711,58 +719,58 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "7286aec002c8feecc338cc33269e96b73955ab227456e9fb2a91f7fab8a358e9" + sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "7754a1ad30ee896b265f8d14078b0513a4dba28d358eabb9d5f339886f4a1adc" + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" uuid: dependency: "direct main" description: name: uuid - sha256: df5a4d8f22ee4ccd77f8839ac7cb274ebc11ef9adcce8b92be14b797fe889921 + sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 url: "https://pub.dev" source: hosted - version: "4.2.1" + version: "4.3.3" vector_graphics: dependency: transitive description: name: vector_graphics - sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43" + sha256: "18f6690295af52d081f6808f2f7c69f0eed6d7e23a71539d75f4aeb8f0062172" url: "https://pub.dev" source: hosted - version: "1.1.9+1" + version: "1.1.9+2" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7" + sha256: "531d20465c10dfac7f5cd90b60bbe4dd9921f1ec4ca54c83ebb176dbacb7bb2d" url: "https://pub.dev" source: hosted - version: "1.1.9+1" + version: "1.1.9+2" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26 + sha256: "03012b0a33775c5530576b70240308080e1d5050f0faf000118c20e6463bc0ad" url: "https://pub.dev" source: hosted - version: "1.1.9+1" + version: "1.1.9+2" vector_math: dependency: transitive description: @@ -783,10 +791,10 @@ packages: dependency: transitive description: name: win32 - sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 + sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "5.2.0" win32_registry: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5edc2c7..18406dd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,7 +48,7 @@ dependencies: device_info_plus: ^9.1.1 uuid: ^4.2.1 expandable: ^5.0.1 - fl_chart: ^0.65.0 + fl_chart: ^0.66.0 flutter_web_browser: ^0.17.1 flutter_svg: ^2.0.9 percent_indicator: ^4.2.3 From 26086269e5807382ba7dd943c18c8f5c73ab5ff9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 16 Jan 2024 18:25:38 +0100 Subject: [PATCH 479/676] Fix save fallback dns when no dns is added --- lib/providers/dns_provider.dart | 2 +- lib/screens/settings/dns/fallback_dns.dart | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index c5809af..84b86cd 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -119,7 +119,7 @@ class DnsProvider with ChangeNotifier { if (result.successful == true) { DnsInfo data = dnsInfo!; - data.bootstrapDns = List.from(value['fallback_dns']); + data.fallbackDns = List.from(value['fallback_dns']); setDnsInfoData(data); return result; } diff --git a/lib/screens/settings/dns/fallback_dns.dart b/lib/screens/settings/dns/fallback_dns.dart index 4df30c9..dcae0a2 100644 --- a/lib/screens/settings/dns/fallback_dns.dart +++ b/lib/screens/settings/dns/fallback_dns.dart @@ -34,11 +34,7 @@ class _FallbackDnsScreenState extends State { } void checkValidValues() { - if ( - fallbackControllers.isNotEmpty && - fallbackControllers.every((element) => element['controller'].text != '') && - fallbackControllers.every((element) => element['error'] == null) - ) { + if (fallbackControllers.every((element) => element['error'] == null)) { setState(() => validValues = true); } else { From 61d521f9f9f805b8fdc221973a069701cbd7c339 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 16 Jan 2024 18:25:47 +0100 Subject: [PATCH 480/676] Change logs breaking width --- lib/screens/logs/logs.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 757c949..560db9c 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -21,7 +21,7 @@ class _LogsState extends State { Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { - if (constraints.maxWidth > 1000) { + if (constraints.maxWidth > 800) { return Material( color: Colors.transparent, child: Row( From 236124d246e0850929258e739b2dbfd8eef27688 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 16 Jan 2024 18:45:37 +0100 Subject: [PATCH 481/676] Updated readme, added key properties sample and updated app version --- README.md | 42 +++++++++++++++++++++-------------- android/key.properties.sample | 4 ++++ pubspec.yaml | 2 +- 3 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 android/key.properties.sample diff --git a/README.md b/README.md index 0a4af9d..a81e1dd 100644 --- a/README.md +++ b/README.md @@ -44,18 +44,28 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a ## Generate production build
    +
  • + Prerequisites +
      +
    1. Open pubspec.yaml and change the version name and the version number.
    2. +
    3. Run flutter clean.
    4. +
    5. Run flutter pub get.
    6. +
    +
  • +
  • + Android +
      +
    1. Make sure you have your key.properties file at android/, with all the required values of your signing key correctly set up.
    2. +
    3. Make sure you have your keystore file at android/app.
    4. +
    5. Run flutter build apk --release to compile the APK.
    6. +
    7. The .apk package is located at build/app/outputs/flutter-apk/app-release.apk.
    8. +
    +
  • macOS
      -
    1. flutter clean
    2. -
    3. flutter pub get
    4. -
    5. flutter build macos --release
    6. -
    7. Open macos/Runner.xcworkspace on Xcode
    8. -
    9. Make sure all the pods have the minimum deployment version at 10.14
    10. -
    11. Select Runner > Targets Runner
    12. -
    13. Make sure the Version and Build numbers are correct
    14. -
    15. Click on Product menu and on Archive
    16. -
    17. Select the first on the list and click on Distribute app, select Copy App and click on Next
    18. +
    19. Run flutter build macos --release to compile the production build.
    20. +
    21. The .app package is located at build/macos/Build/Products/Release/AdGuard Home Manager.app.
  • @@ -67,24 +77,22 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a Build
      -
    1. Open debian.yaml file inside debian/ and update the version number
    2. +
    3. Open debian.yaml file inside debian/ and update the version number
    4. run rps build linux
    5. -
    6. The .tar.gz is at build/linux/x64/release/bundle
    7. -
    8. The .deb package is at debian/packages
    9. +
    10. The .tar.gz is at build/linux/x64/release/bundle
    11. +
    12. The .deb package is at debian/packages
  • Windows
      -
    1. flutter clean
    2. -
    3. flutter pub get
    4. -
    5. flutter build windows
    6. +
    7. Run flutter build windows --release.
    8. Open Inno Setup Compiler application and load the script
    9. -
    10. The script is located at windows/innosetup_installer_builder.iss
    11. +
    12. The script is located at windows/innosetup_installer_builder.iss
    13. Update the version number and save the changes
    14. Click on the Compile button
    15. -
    16. The installer will be generated at build/windows/aghm_installer.exe
    17. +
    18. The installer will be generated at build/windows/aghm_installer.exe.
  • diff --git a/android/key.properties.sample b/android/key.properties.sample new file mode 100644 index 0000000..b51dc2c --- /dev/null +++ b/android/key.properties.sample @@ -0,0 +1,4 @@ +storePassword= # keystore password # +keyPassword= # keystore key password # +keyAlias= # key alias # +storeFile= # ./keystore-file-name.jks # \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 18406dd..e4dbaa8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.14.0+119 +version: 2.14.1+120 environment: sdk: '>=2.18.1 <3.0.0' From d93eb504b069ec1999c4371e51370a1ea69d2483 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 16 Jan 2024 19:06:47 +0100 Subject: [PATCH 482/676] Updated workflow --- .github/workflows/release-stable.yaml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 2d8f0e8..220c56d 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -172,7 +172,7 @@ jobs: - name: Generate .deb package run: flutter_to_debian - name: Move .deb package to project root - run: mv debian/packages/AdGuardHomeManager_${{ env.VERSION_NAME }}_amd64.deb AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux_amd64.deb + run: mv build/linux/x64/release/debian/AdGuardHomeManager_${{ env.VERSION_NAME }}_amd64.deb AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux_amd64.deb - name: Generate .tar.gz package uses: a7ul/tar-action@v1.1.3 id: compress diff --git a/README.md b/README.md index a81e1dd..930d090 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a
  • Open debian.yaml file inside debian/ and update the version number
  • run rps build linux
  • The .tar.gz is at build/linux/x64/release/bundle
  • -
  • The .deb package is at debian/packages
  • +
  • The .deb package is at build/linux/x64/release/debian/
  • From 2693f96cf25ec043ec0ae2abf95b551aa9fdd7cd Mon Sep 17 00:00:00 2001 From: Dmitry Nagibin Date: Thu, 18 Jan 2024 23:18:47 +0500 Subject: [PATCH 483/676] Russian_translation: updated for app version 2.14.1 --- lib/l10n/app_ru.arb | 128 +++++++++++++++++++++++++++++++++----------- 1 file changed, 97 insertions(+), 31 deletions(-) diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 78b3e37..4d57935 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -4,6 +4,7 @@ "connect": "ПодключитьÑÑ", "servers": "Серверы", "createConnection": "Создать подключение", + "editConnection": "Edit connection", "name": "ИмÑ", "ipDomain": "IP-Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ домен", "path": "Путь", @@ -22,7 +23,7 @@ "nameNotEmpty": "Ð˜Ð¼Ñ Ð½Ðµ может быть пуÑтым", "invalidUsernamePassword": "Ðеверный логин или пароль", "tooManyAttempts": "Слишком много попыток. Попробуйте позднее.", - "cantReachServer": "Ðе удаётÑÑ ÑƒÑтановить Ñоединение Ñ Ñервером. Проверьте наÑтройки подключениÑ", + "cantReachServer": "Ðе удаётÑÑ ÑƒÑтановить Ñоединение Ñ Ñервером. Проверьте наÑтройки подключениÑ.", "sslError": "Ошибка SSL. Перейдите в «ÐаÑтройки» > «Дополнительные наÑтройки» и активируйте «Ðе проверÑть SSL-Ñертификат».", "unknownError": "ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°", "connectionNotCreated": "Ðе удалоÑÑŒ Ñоздать подключение", @@ -30,7 +31,7 @@ "connected": "Подключено", "selectedDisconnected": "Выбран, но отключён", "connectionDefaultSuccessfully": "Подключение уÑпешно уÑтановлено как «подключение по умолчанию».", - "connectionDefaultFailed": "Подключение не удалоÑÑŒ уÑтановить «подключением по умолчанию»", + "connectionDefaultFailed": "Ðе удалоÑÑŒ уÑтановить «подключением по умолчанию».", "noSavedConnections": "Ðет Ñохранённых подключений", "cannotConnect": "Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ Ðº Ñерверу", "connectionRemoved": "Подключение удалено уÑпешно", @@ -50,13 +51,13 @@ "parentalFilteringWidget": "РодительÑкий контроль", "safeSearchWidget": "БезопаÑный поиÑк", "ruleFiltering": "Правила фильтрации", - "safeBrowsing": "БезопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ", - "parentalFiltering": "РодительÑкий контроль", + "safeBrowsing": "БезопаÑнаÑ\nнавигациÑ", + "parentalFiltering": "РодительÑкий\nконтроль", "safeSearch": "БезопаÑный поиÑк", "serverStatusNotRefreshed": "Ðе удалоÑÑŒ обновить ÑÑ‚Ð°Ñ‚ÑƒÑ Ñервера", "loadingStatus": "Загрузка...", "errorLoadServerStatus": "Ðе удалоÑÑŒ получить ÑÑ‚Ð°Ñ‚ÑƒÑ Ñервера", - "topQueriedDomains": "ЧаÑто запрашиваемые домены", + "topQueriedDomains": "ЧаÑто запрашиваемые\nдомены", "viewMore": "Показать больше", "topClients": "ЧаÑтые клиенты", "topBlockedDomains": "ЧаÑто блокируемые домены", @@ -79,8 +80,8 @@ "appVersion": "ВерÑÐ¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ", "createdBy": "Ðвтор", "clients": "Клиенты", - "allowed": "Разрешён", - "blocked": "Заблокирован", + "allowed": "Обработан", + "blocked": "Заблокировано", "noClientsList": "СпиÑок клиентов пуÑÑ‚", "activeClients": "Ðктивные", "removeClient": "Удалить запиÑÑŒ", @@ -104,30 +105,30 @@ "dontCheckCertificate": "Ðе проверÑть SSL-Ñертификат", "dontCheckCertificateDescription": "ПереопределÑет проверку SSL-Ñертификата Ñервера", "advancedSetupDescription": "РаÑширенные параметры", - "settingsUpdatedSuccessfully": "ÐаÑтройки уÑпешно обновлены", - "cannotUpdateSettings": "Ðе удалоÑÑŒ обновить наÑтройки", + "settingsUpdatedSuccessfully": "ÐаÑтройки уÑпешно обновлены.", + "cannotUpdateSettings": "Ðе удалоÑÑŒ обновить наÑтройки.", "restartAppTakeEffect": "ПерезапуÑтите приложение", "loadingLogs": "Загрузка журнала...", "logsNotLoaded": "Ðе удалоÑÑŒ загрузить журнал", "processed": "Обработан\nБез ÑпиÑка", "processedRow": "Обработан", "blockedBlacklist": "Заблокирован\nЧёрный ÑпиÑок", - "blockedBlacklistRow": "Заблокирован (чёрный ÑпиÑок)", + "blockedBlacklistRow": "Заблокирован Чёрным ÑпиÑком", "blockedSafeBrowsing": "Заблокирован\nБезопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ", - "blockedSafeBrowsingRow": "Блок. (безопаÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ)", + "blockedSafeBrowsingRow": "Заблокировано БезопаÑной навигацией", "blockedParental": "Заблокирован\nРодительÑкий контроль", - "blockedParentalRow": "Блок. (родительÑкий контроль)", + "blockedParentalRow": "Заблокировано РодительÑким контролем", "blockedInvalid": "Заблокировано\nÐеверный", "blockedInvalidRow": "Заблокирован (Ðеверный)", "blockedSafeSearch": "Заблокирован\nБезопаÑный поиÑк", - "blockedSafeSearchRow": "Блок. (безопаÑный поиÑк)", + "blockedSafeSearchRow": "Заблокировано БезопаÑным поиÑком", "blockedService": "Заблокирован\nЗаблокированный ÑервиÑ", "blockedServiceRow": "Заблокирован (заблокированный ÑервиÑ)", - "processedWhitelist": "Обработан\nБелый ÑпиÑок", - "processedWhitelistRow": "Разрешён (белый ÑпиÑок)", + "processedWhitelist": "Разрешён\nБелый ÑпиÑок", + "processedWhitelistRow": "Разрешён Белым ÑпиÑком", "processedError": "Обработан\nОшибка", "processedErrorRow": "Обработан (ошибка)", - "rewrite": "ПерепиÑать", + "rewrite": "ПерепиÑан", "status": "СтатуÑ", "result": "Результат", "time": "ВремÑ", @@ -169,14 +170,14 @@ "search": "ПоиÑк", "dnsQueries": "DNS-запроÑÑ‹", "average": "Среднее", - "blockedFilters": "Заблокировано фильтрами", - "malwarePhisingBlocked": "Заблокированные вредоноÑные и фишинговые Ñайты", - "blockedAdultWebsites": "Заблокированные «взроÑлые» Ñайты", + "blockedFilters": "Заблокировано\nфильтрами", + "malwarePhishingBlocked": "Заблокированные\nвредоноÑные и\nфишинговые Ñайты", + "blockedAdultWebsites": "Заблокированные\n«взроÑлые» Ñайты", "generalSettings": "ОÑновные наÑтройки", "generalSettingsDescription": "Различные наÑтройки", "hideZeroValues": "Скрывать нулевые значениÑ", "hideZeroValuesDescription": "Скрывать блоки Ñ Ð½ÑƒÐ»ÐµÐ²Ñ‹Ð¼Ð¸ значениÑми на домашнем Ñкране", - "webAdminPanel": "Веб-панель админ.", + "webAdminPanel": "Веб-панель админиÑтрированиÑ", "visitGooglePlay": "ПоÑетить Ñтраницу в Google Play", "gitHub": "ИÑходный код Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупен на GitHub", "blockClient": "Заблокировать клиента", @@ -209,14 +210,14 @@ "clientNotDeleted": "Ðе удалоÑÑŒ удалить клиента", "options": "Параметры", "loadingFilters": "Загрузка фильтров...", - "filtersNotLoaded": "Ðе удалоÑÑŒ загрузить фильтры", + "filtersNotLoaded": "Ðе удалоÑÑŒ загрузить фильтры.", "whitelists": "Белые ÑпиÑки DNS", "blacklists": "Чёрные ÑпиÑки DNS", "rules": "КоличеÑтво правил", "customRules": "ПользовательÑкие правила фильтрации", - "enabledRules": "Включенные правила", - "enabled": "Включено", - "disabled": "Отключено", + "enabledRules": "Ðктивных правил", + "enabled": "Включён", + "disabled": "Отключён", "rule": "Правило", "addCustomRule": "Добавить пользовательÑкое правило фильтрации", "removeCustomRule": "Удалить пользовательÑкое правило фильтрации", @@ -268,7 +269,7 @@ "httpPort": "HTTP-порт", "protectionEnabled": "Защита активна", "dhcpAvailable": "DHCP доÑтупен", - "serverRunning": "Сервер запущен ", + "serverRunning": "Сервер запущен", "serverVersion": "ВерÑÐ¸Ñ Ñервера", "serverLanguage": "Язык Ñервера", "yes": "Да", @@ -303,7 +304,7 @@ "errorCheckingHost": "Ðе удалоÑÑŒ проверить хоÑÑ‚", "block": "Запретить", "unblock": "Разрешить", - "custom": "Custom", + "custom": "Своё правило", "addImportant": "Добавить $important", "howCreateRules": "Как Ñоздать пользовательÑкие правила", "examples": "Примеры", @@ -317,6 +318,7 @@ "enablingList": "Включение ÑпиÑка...", "disablingList": "Отключение ÑпиÑка...", "disableFiltering": "Отключить фильтрацию", + "savingList": "Сохранение ÑпиÑка...", "enablingFiltering": "Включение фильтрации...", "disablingFiltering": "Отключение фильтрации...", "filteringStatusUpdated": "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ð¸ уÑпешно обновлен", @@ -460,7 +462,7 @@ "defaultMode": "Стандартный", "defaultDescription": "Отвечает Ñ Ð½ÑƒÐ»ÐµÐ²Ñ‹Ð¼ IP-адреÑом, (0.0.0.0 Ð´Ð»Ñ A; :: Ð´Ð»Ñ AAAA) когда заблокировано правилом в Ñтиле Adblock; отвечает Ñ IP-адреÑом, указанным в правиле, когда заблокировано правилом в Ñтиле файлов hosts", "refusedDescription": "Отвечает Ñ ÐºÐ¾Ð´Ð¾Ð¼ REFUSED", - "nxdomainDescription": "Отвечает Ñ ÐºÐ¾Ð´Ð¾Ð¼ NXDOMAIN ", + "nxdomainDescription": "Отвечает Ñ ÐºÐ¾Ð´Ð¾Ð¼ NXDOMAIN", "nullIp": "Ðулевой IP", "nullIpDescription": "Отвечает Ñ Ð½ÑƒÐ»ÐµÐ²Ñ‹Ð¼ IP-адреÑом (0.0.0.0 Ð´Ð»Ñ A; :: Ð´Ð»Ñ AAAA)", "customIp": "ПользовательÑкий IP", @@ -626,11 +628,11 @@ "ipLogs": "IP-адреÑа в запиÑÑÑ… журнала", "ipLogsDescription": "Ð’Ñегда показывать IP-Ð°Ð´Ñ€ÐµÑ Ð² запиÑÑÑ… журнала вмеÑто имени клиента", "application": "Приложение", - "combinedChart": "Объединить графики", + "combinedChart": "ОбъединÑть графики", "combinedChartDescription": "Комбинирует вÑе графики в один", "statistics": "СтатиÑтика", "errorLoadFilters": "Ошибка при загрузке фильтров.", - "clientRemovedSuccessfully": "ЗапиÑÑŒ уÑпешно удалена", + "clientRemovedSuccessfully": "ЗапиÑÑŒ уÑпешно удалена.", "editRewriteRule": "Редактировать правило", "dnsRewriteRuleUpdated": "Правило перезапиÑи DNS уÑпешно обновлено", "dnsRewriteRuleNotUpdated": "Ðе удалоÑÑŒ обновить правило перезапиÑи DNS", @@ -660,5 +662,69 @@ "topItemsOrderDescription": "УпорÑдочьте раÑположение блоков на главном Ñкране", "topItemsReorderInfo": "Чтобы менÑть порÑдок Ñлементов, ÑƒÐ´ÐµÑ€Ð¶Ð¸Ð²Ð°Ñ Ñлемент, перетащите его на новое меÑто.", "discardChanges": "Отменить изменениÑ", - "discardChangesDescription": "Ð’Ñ‹ уверены, что хотите отменить изменениÑ?" -} \ No newline at end of file + "discardChangesDescription": "Ð’Ñ‹ уверены, что хотите отменить изменениÑ?", + "others": "Прочее", + "showChart": "Показать график", + "hideChart": "Скрыть график", + "showTopItemsChart": "Показывать ТОП-графики на главной Ñтранице", + "showTopItemsChartDescription": "По умолчанию на главной Ñтранице отображаютÑÑ ÐºÑ€ÑƒÐ³Ð¾Ð²Ñ‹Ðµ диаграммы Ð´Ð»Ñ Ñ‡Ð°Ñто запрашиваемых доменов, чаÑтых клиентов и прочего. ВлиÑет только на проÑмотр Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑŒÐ½Ð¾Ð³Ð¾ уÑтройÑтва", + "openMenu": "Открыть меню", + "closeMenu": "Закрыть меню", + "openListUrl": "Открыть URL ÑпиÑка", + "selectionMode": "Режим выбора", + "enableDisableSelected": "Включить или выключить выбранные Ñлементы", + "deleteSelected": "Удалить выбранные Ñлементы", + "deleteSelectedLists": "Удалить выбранные ÑпиÑки", + "allSelectedListsDeletedSuccessfully": "Ð’Ñе выбранные ÑпиÑки уÑпешно удалены.", + "deletionResult": "Результат удалениÑ", + "deletingLists": "Удаление ÑпиÑков...", + "failedElements": "Ðеудачные Ñлементы", + "processingLists": "Обработка ÑпиÑков...", + "enableDisableResult": "Включить или выключить результат", + "selectedListsEnabledDisabledSuccessfully": "Ð’Ñе выбранные ÑпиÑки были включены или выключены уÑпешно", + "sslWarning": "ЕÑли иÑпользуетÑÑ HTTPS-Ñоединение Ñ ÑамоподпиÑным Ñертификатом, то должна быть активирована Ð¾Ð¿Ñ†Ð¸Ñ Â«Ðе проверÑть SSL-Ñертификат» в разделе «ÐаÑтройки» > «Дополнительные наÑтройки».", + "unsupportedServerVersion": "ÐÐµÐ¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñервера", + "unsupportedServerVersionMessage": "Ð”Ð°Ð½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ AdGuard Home уÑтарела и не поддерживаетÑÑ AdGuard Home Manager. Чтобы иÑпользовать данное приложение, необходимо выполнить обновление AdGuard Home до актуальной верÑии.", + "yourVersion": "Ваша верÑиÑ: {version}", + "minimumRequiredVersion": "ÐœÐ¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑиÑ: {version}", + "topUpstreams": "ЧаÑто запрашиваемые\nupstream-Ñерверы", + "averageUpstreamResponseTime": "Среднее Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ÐºÐ»Ð¸ÐºÐ°\nupstream-Ñервера", + "dhcpNotAvailable": "DHCP Ñервер не доÑтупен.", + "osServerInstalledIncompatible": " ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ ÑиÑтема, в которой уÑтановлен Ñервер, неÑовмеÑтима Ñ Ñтой функцией.", + "resetSettings": "СброÑить наÑтройки", + "resetEncryptionSettingsDescription": "Ð’Ñ‹ уверены, что хотите ÑброÑить наÑтройки ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ðº значениÑм по умолчанию?", + "resettingConfig": "Ð¡Ð±Ñ€Ð¾Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¸...", + "configurationResetSuccessfully": "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÑƒÑпешно Ñброшена", + "configurationResetError": "Ðе удалоÑÑŒ ÑброÑить конфигурацию", + "testUpstreamDnsServers": "ТеÑÑ‚ upstream DNS-Ñерверов", + "errorTestUpstreamDns": "Ошибка при теÑтировании upstream DNS-Ñерверов.", + "useCustomIpEdns": "Use custom IP for EDNS", + "useCustomIpEdnsDescription": "ИÑпользовать ÑобÑтвенный IP-Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ EDNS", + "sortingOptions": "Параметры Ñортировки", + "fromHighestToLowest": "От большего к меньшему", + "fromLowestToHighest": "От меньшего к большему", + "queryLogsAndStatistics": "Журналы запроÑов и ÑтатиÑтика", + "ignoreClientQueryLog": "Игнорировать Ñтого клиента в журнале запроÑов", + "ignoreClientStatistics": "Игнорировать Ñтого клиента в ÑтатиÑтике", + "savingChanges": "Сохранение изменений...", + "fallbackDnsServers": "Резервные DNS-Ñерверы", + "fallbackDnsServersDescription": "ÐаÑтроить резервные DNS-Ñерверы", + "fallbackDnsServersInfo": "СпиÑок резервных DNS-Ñерверов, иÑпользуемых в тех ÑлучаÑÑ…, когда вышеÑтоÑщие DNS-Ñерверы недоÑтупны. СинтакÑÐ¸Ñ Ñ‚Ð°ÐºÐ¾Ð¹ же, как и в поле Upstream DNS-Ñерверы выше.", + "noFallbackDnsAdded": "Резервные DNS-Ñерверы не добавлены.", + "blockedResponseTtl": "TTL заблокированного ответа", + "blockedResponseTtlDescription": "Указывает, в течение Ñкольких Ñекунд клиенты должны кешировать отфильтрованный ответ", + "invalidValue": "ÐедопуÑтимое значение", + "noDataChart": "Ðет данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð³Ñ€Ð°Ñ„Ð¸ÐºÐ°.", + "noData": "Ðет данных", + "unblockClient": "Разблокировать клиента", + "blockingClient": "Блокировка клиента...", + "unblockingClient": "СнÑтие блокироваки Ñ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ð°...", + "upstreamDnsCacheConfiguration": "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÐºÐµÑˆÐ° upstream DNS-Ñерверов", + "enableDnsCachingClient": "Включить кеширование Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑкой конфигурации upstream-Ñерверов Ñтого клиента", + "dnsCacheSize": "Размер DNS-кеша", + "nameInvalid": "ТребуетÑÑ Ð¸Ð¼Ñ", + "oneIdentifierRequired": "ТребуетÑÑ Ð¿Ð¾ крайней мере один идентификатор", + "dnsCacheNumber": "Размер кÑша DNS должен быть чиÑлом", + "errors": "Ошибки", + "redirectHttpsWarning": "ЕÑли в AdGuard Home активирована Ð¾Ð¿Ñ†Ð¸Ñ Â«ÐвтоматичеÑки перенаправлÑть на HTTPS», то необходимо иÑпользовать HTTPS-Ñоединение и HTTPS-порт." +} From cf7bfa44f82219b80502cf5003052060eb366954 Mon Sep 17 00:00:00 2001 From: Dmitry Nagibin Date: Thu, 18 Jan 2024 23:28:36 +0500 Subject: [PATCH 484/676] Russian_translation: fix for app version 2.14.1 --- lib/l10n/app_ru.arb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 4d57935..c0a6063 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -68,7 +68,7 @@ "systemDefined": "СиÑÑ‚ÐµÐ¼Ð½Ð°Ñ Ñ‚ÐµÐ¼Ð°", "close": "Закрыть", "connectedTo": "Подключено к:", - "selectedServer": "Selected server:", + "selectedServer": "Выбранный Ñервер:", "noServerSelected": "Ðет выбранных Ñерверов", "manageServer": "Управление Ñервером", "allProtections": "Защита", @@ -621,7 +621,7 @@ "copyListUrl": "Скопировать URL", "listUrlCopied": "URL ÑпиÑка Ñохранён в буфер обмена", "unsupportedVersion": "ÐÐµÐ¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑиÑ", - "unsupprtedVersionMessage": "Поддержка Ñервера верÑии {version} не гарантируетÑÑ. Приложение может работать неÑтабильно Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ верÑией Ñервера.\n\nПриложение AdGuard Home Manager предназначено Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñо Ñтабильными верÑиÑми Ñервера AdGuard Home. Приложение может работать Ñ Ð°Ð»ÑŒÑ„Ð° и бета верÑиÑми Ñервера, но ÑовмеÑтимоÑть и ÑтабильноÑть не гарантируютÑÑ.", + "unsupprtedVersionMessage": "Поддержка AdGuard Home верÑии {version} не гарантируетÑÑ. Приложение может работать неÑтабильно Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ верÑией Ñервера.\n\nПриложение AdGuard Home Manager предназначено Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñо Ñтабильными верÑиÑми AdGuard Home. Приложение может работать Ñ Ð°Ð»ÑŒÑ„Ð° и бета верÑиÑми Ñервера, но ÑовмеÑтимоÑть и ÑтабильноÑть не гарантируютÑÑ.", "iUnderstand": "Продолжить", "appUpdates": "ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹", "usingLatestVersion": "Ð’Ñ‹ иÑпользуете поÑледнюю верÑию", @@ -682,7 +682,7 @@ "processingLists": "Обработка ÑпиÑков...", "enableDisableResult": "Включить или выключить результат", "selectedListsEnabledDisabledSuccessfully": "Ð’Ñе выбранные ÑпиÑки были включены или выключены уÑпешно", - "sslWarning": "ЕÑли иÑпользуетÑÑ HTTPS-Ñоединение Ñ ÑамоподпиÑным Ñертификатом, то должна быть активирована Ð¾Ð¿Ñ†Ð¸Ñ Â«Ðе проверÑть SSL-Ñертификат» в разделе «ÐаÑтройки» > «Дополнительные наÑтройки».", + "sslWarning": "ЕÑли иÑпользуетÑÑ HTTPS-Ñоединение Ñ ÑамоподпиÑанным Ñертификатом, то должна быть активирована Ð¾Ð¿Ñ†Ð¸Ñ Â«Ðе проверÑть SSL-Ñертификат» в разделе «ÐаÑтройки» > «Дополнительные наÑтройки».", "unsupportedServerVersion": "ÐÐµÐ¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñервера", "unsupportedServerVersionMessage": "Ð”Ð°Ð½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ AdGuard Home уÑтарела и не поддерживаетÑÑ AdGuard Home Manager. Чтобы иÑпользовать данное приложение, необходимо выполнить обновление AdGuard Home до актуальной верÑии.", "yourVersion": "Ваша верÑиÑ: {version}", From 65ee702b8962f00a401783cc5ea6864d0105ff37 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 Jan 2024 13:07:25 +0100 Subject: [PATCH 485/676] Improved theme color selection for desktop --- .../settings/customization/color_item.dart | 14 +- .../settings/customization/customization.dart | 153 +++++++++--------- 2 files changed, 90 insertions(+), 77 deletions(-) diff --git a/lib/screens/settings/customization/color_item.dart b/lib/screens/settings/customization/color_item.dart index 0d6ea03..d753bf5 100644 --- a/lib/screens/settings/customization/color_item.dart +++ b/lib/screens/settings/customization/color_item.dart @@ -1,23 +1,31 @@ import 'package:flutter/material.dart'; class ColorItem extends StatelessWidget { + final int index; + final int total; final Color color; final int numericValue; final int? selectedValue; final void Function(int) onChanged; const ColorItem({ - Key? key, + super.key, + required this.index, + required this.total, required this.color, required this.numericValue, required this.selectedValue, required this.onChanged - }) : super(key: key); + }); @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.all(10), + padding: index == 0 + ? const EdgeInsets.only(top: 10, right: 10, bottom: 10) + : index == total-1 + ? const EdgeInsets.only(top: 10, bottom: 10, left: 10) + : const EdgeInsets.all(10), child: Material( borderRadius: BorderRadius.circular(50), child: InkWell( diff --git a/lib/screens/settings/customization/customization.dart b/lib/screens/settings/customization/customization.dart index fb4526b..7bec949 100644 --- a/lib/screens/settings/customization/customization.dart +++ b/lib/screens/settings/customization/customization.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -30,9 +32,9 @@ class CustomizationWidget extends StatefulWidget { final AppConfigProvider appConfigProvider; const CustomizationWidget({ - Key? key, + super.key, required this.appConfigProvider, - }) : super(key: key); + }); @override State createState() => _CustomizationWidgetState(); @@ -44,6 +46,8 @@ class _CustomizationWidgetState extends State { int selectedColor = 0; bool useThemeColorInsteadGreenRed = false; + final _colorsScrollController = ScrollController(); + @override void initState() { selectedTheme = widget.appConfigProvider.selectedThemeNumber; @@ -125,83 +129,84 @@ class _CustomizationWidgetState extends State { title: AppLocalizations.of(context)!.useDynamicTheme, ), if (!(appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31)) const SizedBox(height: 20), - if (dynamicColor == false) ...[ - SizedBox( - width: MediaQuery.of(context).size.width, - height: 70, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: colors.length, - itemBuilder: (context, index) { - if (index == 0) { - return Row( - children: [ - const SizedBox(width: 15), - ColorItem( - color: colors[index], - numericValue: index, - selectedValue: selectedColor, - onChanged: (value) { - setState(() => selectedColor = value); - appConfigProvider.setStaticColor(value); + if (dynamicColor == false) Padding( + padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16), + child: Scrollbar( + controller: _colorsScrollController, + thumbVisibility: Platform.isMacOS || Platform.isLinux || Platform.isWindows, + interactive: Platform.isMacOS || Platform.isLinux || Platform.isWindows, + thickness: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 8 : 0, + child: Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: MediaQuery.of(context).size.width, + height: 70, + child: ListView.builder( + controller: _colorsScrollController, + scrollDirection: Axis.horizontal, + itemCount: colors.length, + padding: const EdgeInsets.all(0), + itemBuilder: (context, index) { + if (index == 0) { + return Row( + children: [ + ColorItem( + index: index, + total: colors.length, + color: colors[index], + numericValue: index, + selectedValue: selectedColor, + onChanged: (value) { + setState(() => selectedColor = value); + appConfigProvider.setStaticColor(value); + } + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 10), + width: 1, + height: 60, + decoration: BoxDecoration( + color: Colors.grey, + borderRadius: BorderRadius.circular(1) + ), + ) + ], + ); } - ), - Container( - margin: const EdgeInsets.symmetric(horizontal: 10), - width: 1, - height: 60, - decoration: BoxDecoration( - color: Colors.grey, - borderRadius: BorderRadius.circular(1) - ), - ) - ], - ); - } - else if (index == colors.length-1) { - return Row( - children: [ - ColorItem( - color: colors[index], - numericValue: index, - selectedValue: selectedColor, - onChanged: (value) { - setState(() => selectedColor = value); - appConfigProvider.setStaticColor(value); + else { + return ColorItem( + index: index, + total: colors.length, + color: colors[index], + numericValue: index, + selectedValue: selectedColor, + onChanged: (value) { + setState(() => selectedColor = value); + appConfigProvider.setStaticColor(value); + } + ); } + }, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Text( + colorTranslation(context, selectedColor), + style: TextStyle( + color: Theme.of(context).listTileTheme.iconColor, + fontSize: 16 ), - const SizedBox(width: 15) - ], - ); - } - else { - return ColorItem( - color: colors[index], - numericValue: index, - selectedValue: selectedColor, - onChanged: (value) { - setState(() => selectedColor = value); - appConfigProvider.setStaticColor(value); - } - ); - } - }, - ), - ), - Padding( - padding: const EdgeInsets.only( - left: 25, - top: 10 - ), - child: Text( - colorTranslation(context, selectedColor), - style: TextStyle( - color: Theme.of(context).listTileTheme.iconColor, - fontSize: 16 + ), + ) + ], ), ), - ) - ], + ), + ), CustomSwitchListTile( value: useThemeColorInsteadGreenRed, onChanged: (value) { From 211eab9f448f56cdf3856dc13f17810ec84834a9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 Jan 2024 13:55:15 +0100 Subject: [PATCH 486/676] Moved logs settings to settings screen --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- .../logs/configuration/config_widgets.dart | 276 ------------------ .../logs/configuration/logs_config_modal.dart | 187 ------------ lib/screens/logs/logs_list_appbar.dart | 92 ------ .../logs_settings/config_widgets.dart | 177 +++++++++++ .../settings/logs_settings/logs_settings.dart | 167 +++++++++++ lib/screens/settings/settings.dart | 31 +- lib/services/api_client.dart | 2 +- 9 files changed, 369 insertions(+), 569 deletions(-) delete mode 100644 lib/screens/logs/configuration/config_widgets.dart delete mode 100644 lib/screens/logs/configuration/logs_config_modal.dart create mode 100644 lib/screens/settings/logs_settings/config_widgets.dart create mode 100644 lib/screens/settings/logs_settings/logs_settings.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 3778a60..79081e5 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -726,5 +726,6 @@ "oneIdentifierRequired": "At least one identifier is required", "dnsCacheNumber": "DNS cache size must be a number", "errors": "Errors", - "redirectHttpsWarning": "If you have enabled \"Redirect to HTTPS automatically\" on your AdGuard Home server, you must select an HTTPS connection and use the HTTPS port of your server." + "redirectHttpsWarning": "If you have enabled \"Redirect to HTTPS automatically\" on your AdGuard Home server, you must select an HTTPS connection and use the HTTPS port of your server.", + "logsSettingsDescription": "Configure query logs" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 03e3440..3846777 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -726,5 +726,6 @@ "oneIdentifierRequired": "Se require al menos un identificador", "dnsCacheNumber": "El tamaño de caché de DNS debe ser un número", "errors": "Errores", - "redirectHttpsWarning": "Si tienes activado \"Redireccionar a HTTPS automáticamente\" en tu servidor AdGuard Home, debes seleccionar una conexión HTTPS y utilizar el puerto de HTTPS de tu servidor." + "redirectHttpsWarning": "Si tienes activado \"Redireccionar a HTTPS automáticamente\" en tu servidor AdGuard Home, debes seleccionar una conexión HTTPS y utilizar el puerto de HTTPS de tu servidor.", + "logsSettingsDescription": "Configura los registros de peticiones" } \ No newline at end of file diff --git a/lib/screens/logs/configuration/config_widgets.dart b/lib/screens/logs/configuration/config_widgets.dart deleted file mode 100644 index 1fa59f9..0000000 --- a/lib/screens/logs/configuration/config_widgets.dart +++ /dev/null @@ -1,276 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/screens/logs/configuration/logs_config_modal.dart'; - -class LogsConfigOptions extends StatelessWidget { - final bool generalSwitch; - final void Function(bool) updateGeneralSwitch; - final bool anonymizeClientIp; - final void Function(bool) updateAnonymizeClientIp; - final List retentionItems; - final double? retentionTime; - final void Function(double?) updateRetentionTime; - final void Function() onClear; - final void Function() onConfirm; - - const LogsConfigOptions({ - super.key, - required this.generalSwitch, - required this.updateGeneralSwitch, - required this.anonymizeClientIp, - required this.updateAnonymizeClientIp, - required this.retentionItems, - required this.retentionTime, - required this.updateRetentionTime, - required this.onClear, - required this.onConfirm - }); - - @override - Widget build(BuildContext context) { - final width = MediaQuery.of(context).size.width; - - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 24), - child: Icon( - Icons.settings, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.logsSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - ], - ), - ], - ), - 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: () => updateGeneralSwitch(!generalSwitch), - borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.enableLog, - style: const TextStyle( - fontSize: 18, - ), - ), - Switch( - value: generalSwitch, - onChanged: updateGeneralSwitch, - ) - ], - ), - ), - ), - ), - ), - Container(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 14), - child: Column( - children: [ - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => updateAnonymizeClientIp(!anonymizeClientIp), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 30), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Text( - AppLocalizations.of(context)!.anonymizeClientIp, - style: const TextStyle( - fontSize: 16 - ), - ), - ), - Switch( - value: anonymizeClientIp, - onChanged: updateAnonymizeClientIp, - ) - ], - ), - ), - ), - ), - Container(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: DropdownButtonFormField( - items: retentionItems.map((item) => DropdownMenuItem( - value: item.value, - child: Text(item.label), - )).toList(), - value: retentionTime, - onChanged: (value) => updateRetentionTime(value as double), - decoration: InputDecoration( - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - label: Text(AppLocalizations.of(context)!.retentionTime) - ), - borderRadius: BorderRadius.circular(20), - ), - ), - ], - ), - ) - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (width > 500) TextButton( - onPressed: () { - Navigator.pop(context); - onClear(); - }, - child: Text(AppLocalizations.of(context)!.clearLogs) - ), - if (width <= 500) IconButton( - onPressed: () { - Navigator.pop(context); - onClear(); - }, - icon: const Icon(Icons.delete_rounded), - tooltip: AppLocalizations.of(context)!.clearLogs, - ), - Row( - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.cancel) - ), - const SizedBox(width: 20), - TextButton( - onPressed: retentionTime != null - ? () { - Navigator.pop(context); - onConfirm(); - } - : null, - child: Text( - AppLocalizations.of(context)!.confirm, - style: TextStyle( - color: retentionTime != null - ? Theme.of(context).colorScheme.primary - : Colors.grey - ), - ) - ), - ], - ) - ], - ), - ), - if (Platform.isIOS) const SizedBox(height: 16) - ], - ); - } -} - -class ConfigLogsLoading extends StatelessWidget { - const ConfigLogsLoading({super.key}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.loadingLogsSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ) - ], - ), - ); - } -} - -class ConfigLogsError extends StatelessWidget { - const ConfigLogsError({super.key}); - - @override - Widget build(BuildContext context) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.logSettingsNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ) - ], - ); - } -} \ No newline at end of file diff --git a/lib/screens/logs/configuration/logs_config_modal.dart b/lib/screens/logs/configuration/logs_config_modal.dart deleted file mode 100644 index 5c2ba44..0000000 --- a/lib/screens/logs/configuration/logs_config_modal.dart +++ /dev/null @@ -1,187 +0,0 @@ -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/logs/configuration/config_widgets.dart'; - -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; - -class RetentionItem { - final String label; - final double value; - - const RetentionItem({ - required this.label, - required this.value, - }); -} - -class LogsConfigModal extends StatefulWidget { - final BuildContext context; - final void Function(Map) onConfirm; - final void Function() onClear; - final bool dialog; - final String serverVersion; - - const LogsConfigModal({ - super.key, - required this.context, - required this.onConfirm, - required this.onClear, - required this.dialog, - required this.serverVersion - }); - - @override - State createState() => _LogsConfigModalState(); -} - -class _LogsConfigModalState extends State { - bool generalSwitch = false; - bool anonymizeClientIp = false; - double? retentionTime; - - List retentionItems = []; - - LoadStatus loadStatus = LoadStatus.loading; - - void loadData() async { - final serversProvider = Provider.of(context, listen: false); - - final result = await serversProvider.apiClient2!.getQueryLogInfo(); - - if (mounted) { - if (result.successful == true) { - setState(() { - generalSwitch = result.content['enabled']; - anonymizeClientIp = result.content['anonymize_client_ip']; - retentionTime = result.content['interval'] != null - ? double.parse(result.content['interval'].toString()) - : null; - loadStatus = LoadStatus.loaded; - }); - } - else { - setState(() => loadStatus = LoadStatus.error); - } - } - } - - @override - void initState() { - retentionItems = [ - RetentionItem( - label: AppLocalizations.of(widget.context)!.hours6, - value: 21600000 - ), - RetentionItem( - label: AppLocalizations.of(widget.context)!.hours24, - value: 86400000 - ), - RetentionItem( - label: AppLocalizations.of(widget.context)!.days7, - value: 604800000 - ), - RetentionItem( - label: AppLocalizations.of(widget.context)!.days30, - value: 2592000000 - ), - RetentionItem( - label: AppLocalizations.of(widget.context)!.days90, - value: 7776000000 - ), - ]; - - loadData(); - super.initState(); - } - - @override - Widget build(BuildContext context) { - if (widget.dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: Builder( - builder: (context) { - switch (loadStatus) { - case LoadStatus.loading: - return const ConfigLogsLoading(); - - case LoadStatus.loaded: - return LogsConfigOptions( - generalSwitch: generalSwitch, - updateGeneralSwitch: (v) => setState(() => generalSwitch = v), - anonymizeClientIp: anonymizeClientIp, - updateAnonymizeClientIp: (v) => setState(() => anonymizeClientIp = v), - retentionItems: retentionItems, - retentionTime: retentionTime, - updateRetentionTime: (v) => setState(() => retentionTime = v), - onClear: () => widget.onClear(), - onConfirm: () => widget.onConfirm({ - "enabled": generalSwitch, - "interval": retentionTime, - "anonymize_client_ip": anonymizeClientIp - }) - ); - - case LoadStatus.error: - return const ConfigLogsError(); - - default: - return const SizedBox(); - } - }, - ) - ), - ); - } - else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor - ), - child: SafeArea( - child: Builder( - builder: (context) { - switch (loadStatus) { - case LoadStatus.loading: - return const ConfigLogsLoading(); - - case LoadStatus.loaded: - return LogsConfigOptions( - generalSwitch: generalSwitch, - updateGeneralSwitch: (v) => setState(() => generalSwitch = v), - anonymizeClientIp: anonymizeClientIp, - updateAnonymizeClientIp: (v) => setState(() => anonymizeClientIp = v), - retentionItems: retentionItems, - retentionTime: retentionTime, - updateRetentionTime: (v) => setState(() => retentionTime = v), - onClear: () => widget.onClear(), - onConfirm: () => widget.onConfirm({ - "enabled": generalSwitch, - "interval": retentionTime, - "anonymize_client_ip": anonymizeClientIp - }) - ); - - case LoadStatus.error: - return const ConfigLogsError(); - - default: - return const SizedBox(); - } - }, - ), - ) - ); - } - } -} \ No newline at end of file diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 8aeb752..144a55e 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -7,16 +7,10 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/filters/logs_filters_modal.dart'; -import 'package:adguard_home_manager/screens/logs/configuration/logs_config_modal.dart'; -import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; class LogsListAppBar extends StatelessWidget { @@ -32,61 +26,9 @@ class LogsListAppBar extends StatelessWidget { @override Widget build(BuildContext context) { final logsProvider = Provider.of(context); - final statusProvider = Provider.of(context); - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; - void updateConfig(Map data) async { - ProcessModal processModal = ProcessModal(); - processModal.open(AppLocalizations.of(context)!.updatingSettings); - - final result = await serversProvider.apiClient2!.updateQueryLogParameters(data: data); - - processModal.close(); - - if (result.successful == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsConfigUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsConfigNotUpdated, - color: Colors.red - ); - } - } - - void clearQueries() async { - ProcessModal processModal = ProcessModal(); - processModal.open(AppLocalizations.of(context)!.updatingSettings); - - final result = await serversProvider.apiClient2!.clearLogs(); - - processModal.close(); - - if (result.successful == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsCleared, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsNotCleared, - color: Colors.red - ); - } - } - - void openFilersModal() { if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { showDialog( @@ -143,40 +85,6 @@ class LogsListAppBar extends StatelessWidget { tooltip: AppLocalizations.of(context)!.filters, ) : const SizedBox(), - if (statusProvider.serverStatus != null) IconButton( - tooltip: AppLocalizations.of(context)!.settings, - onPressed: () => { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (context) => LogsConfigModal( - context: context, - onConfirm: updateConfig, - onClear: clearQueries, - dialog: true, - serverVersion: statusProvider.serverStatus!.serverVersion, - ), - barrierDismissible: false - ) - } - else { - showModalBottomSheet( - context: context, - useRootNavigator: true, - builder: (context) => LogsConfigModal( - context: context, - onConfirm: updateConfig, - onClear: clearQueries, - dialog: false, - serverVersion: statusProvider.serverStatus!.serverVersion, - ), - backgroundColor: Colors.transparent, - isScrollControlled: true - ) - } - }, - icon: const Icon(Icons.settings) - ), const SizedBox(width: 5), ], bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null diff --git a/lib/screens/settings/logs_settings/config_widgets.dart b/lib/screens/settings/logs_settings/config_widgets.dart new file mode 100644 index 0000000..3374854 --- /dev/null +++ b/lib/screens/settings/logs_settings/config_widgets.dart @@ -0,0 +1,177 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; + +class LogsConfigOptions extends StatelessWidget { + final bool generalSwitch; + final void Function(bool) updateGeneralSwitch; + final bool anonymizeClientIp; + final void Function(bool) updateAnonymizeClientIp; + final List retentionItems; + final double? retentionTime; + final void Function(double?) updateRetentionTime; + final void Function() onClear; + final void Function() onConfirm; + + const LogsConfigOptions({ + super.key, + required this.generalSwitch, + required this.updateGeneralSwitch, + required this.anonymizeClientIp, + required this.updateAnonymizeClientIp, + required this.retentionItems, + required this.retentionTime, + required this.updateRetentionTime, + required this.onClear, + required this.onConfirm + }); + + @override + Widget build(BuildContext context) { + final List dropdownItemTranslation = [ + AppLocalizations.of(context)!.hours6, + AppLocalizations.of(context)!.hours24, + AppLocalizations.of(context)!.days7, + AppLocalizations.of(context)!.days30, + AppLocalizations.of(context)!.days90, + ]; + + return Column( + children: [ + const SizedBox(height: 16), + 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: () => updateGeneralSwitch(!generalSwitch), + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context)!.enableLog, + style: const TextStyle( + fontSize: 18, + ), + ), + Switch( + value: generalSwitch, + onChanged: updateGeneralSwitch, + ) + ], + ), + ), + ), + ), + ), + const SizedBox(height: 16), + CustomCheckboxListTile( + value: anonymizeClientIp, + onChanged: (_) => updateAnonymizeClientIp(!anonymizeClientIp), + title: AppLocalizations.of(context)!.anonymizeClientIp, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), + ), + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 22), + child: DropdownButtonFormField( + items: retentionItems.asMap().entries.map((item) => DropdownMenuItem( + value: item.value, + child: Text(dropdownItemTranslation[item.key]), + )).toList(), + value: retentionTime, + onChanged: (value) => updateRetentionTime(value as double), + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + label: Text(AppLocalizations.of(context)!.retentionTime) + ), + borderRadius: BorderRadius.circular(20), + ), + ), + const SizedBox(height: 24), + ElevatedButton.icon( + onPressed: onClear, + icon: const Icon(Icons.delete_rounded), + label: Text(AppLocalizations.of(context)!.clearLogs), + ) + ], + ); + } +} + +class ConfigLogsLoading extends StatelessWidget { + const ConfigLogsLoading({super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(24), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.loadingLogsSettings, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), + ), + ); + } +} + +class ConfigLogsError extends StatelessWidget { + const ConfigLogsError({super.key}); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.logSettingsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/logs_settings/logs_settings.dart b/lib/screens/settings/logs_settings/logs_settings.dart new file mode 100644 index 0000000..2fc6892 --- /dev/null +++ b/lib/screens/settings/logs_settings/logs_settings.dart @@ -0,0 +1,167 @@ +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/settings/logs_settings/config_widgets.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class LogsSettings extends StatefulWidget { + const LogsSettings({super.key}); + + @override + State createState() => _LogsSettingsState(); +} + +class _LogsSettingsState extends State { + bool generalSwitch = false; + bool anonymizeClientIp = false; + double? retentionTime; + + List retentionItems = [ + 21600000, + 86400000, + 604800000, + 2592000000, + 7776000000 + ]; + + LoadStatus loadStatus = LoadStatus.loading; + + void loadData() async { + final serversProvider = Provider.of(context, listen: false); + + final result = await serversProvider.apiClient2!.getQueryLogInfo(); + + if (mounted) { + if (result.successful == true) { + setState(() { + generalSwitch = result.content['enabled']; + anonymizeClientIp = result.content['anonymize_client_ip']; + retentionTime = result.content['interval'] != null + ? double.parse(result.content['interval'].toString()) + : null; + loadStatus = LoadStatus.loaded; + }); + } + else { + setState(() => loadStatus = LoadStatus.error); + } + } + } + + @override + void initState() { + loadData(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void clearQueries() async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.updatingSettings); + + final result = await serversProvider.apiClient2!.clearLogs(); + + processModal.close(); + + if (!mounted) return; + + if (result.successful == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsCleared, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsNotCleared, + color: Colors.red + ); + } + } + + void updateConfig() async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.updatingSettings); + + final result = await serversProvider.apiClient2!.updateQueryLogParameters( + data: { + "enabled": generalSwitch, + "interval": retentionTime, + "anonymize_client_ip": anonymizeClientIp + } + ); + + processModal.close(); + + if (!mounted) return; + + if (result.successful == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsConfigUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsConfigNotUpdated, + color: Colors.red + ); + } + } + + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.logsSettings), + actions: [ + if (loadStatus == LoadStatus.loaded) IconButton( + onPressed: updateConfig, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 8) + ], + ), + body: Builder( + builder: (context) { + switch (loadStatus) { + case LoadStatus.loading: + return const ConfigLogsLoading(); + + case LoadStatus.loaded: + return LogsConfigOptions( + generalSwitch: generalSwitch, + updateGeneralSwitch: (v) => setState(() => generalSwitch = v), + anonymizeClientIp: anonymizeClientIp, + updateAnonymizeClientIp: (v) => setState(() => anonymizeClientIp = v), + retentionItems: retentionItems, + retentionTime: retentionTime, + updateRetentionTime: (v) => setState(() => retentionTime = v), + onClear: clearQueries, + onConfirm: updateConfig + ); + + case LoadStatus.error: + return const ConfigLogsError(); + + default: + return const SizedBox(); + } + }, + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 6efdd9b..0e5256d 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -8,6 +8,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/server_info/server_info.dart'; import 'package:adguard_home_manager/screens/settings/encryption/encryption.dart'; +import 'package:adguard_home_manager/screens/settings/logs_settings/logs_settings.dart'; import 'package:adguard_home_manager/screens/settings/access_settings/access_settings.dart'; import 'package:adguard_home_manager/screens/settings/customization/customization.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp.dart'; @@ -139,11 +140,19 @@ class _SettingsWidgetState extends State<_SettingsWidget> { screenToNavigate: const SafeSearchSettingsScreen(), twoColumns: widget.twoColumns, ), + _SettingsTile( + icon: Icons.list_alt_rounded, + title: AppLocalizations.of(context)!.logsSettings, + subtitle: AppLocalizations.of(context)!.logsSettingsDescription, + thisItem: 1, + screenToNavigate: const LogsSettings(), + twoColumns: widget.twoColumns, + ), _SettingsTile( icon: Icons.lock_rounded, title: AppLocalizations.of(context)!.accessSettings, subtitle: AppLocalizations.of(context)!.accessSettingsDescription, - thisItem: 1, + thisItem: 2, screenToNavigate: const AccessSettings(), twoColumns: widget.twoColumns, ), @@ -151,7 +160,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.install_desktop_rounded, title: AppLocalizations.of(context)!.dhcpSettings, subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, - thisItem: 2, + thisItem: 3, screenToNavigate: const DhcpScreen(), twoColumns: widget.twoColumns, ), @@ -159,7 +168,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.dns_rounded, title: AppLocalizations.of(context)!.dnsSettings, subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, - thisItem: 3, + thisItem: 4, screenToNavigate: DnsSettings( splitView: widget.twoColumns, ), @@ -169,7 +178,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.security_rounded, title: AppLocalizations.of(context)!.encryptionSettings, subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, - thisItem: 4, + thisItem: 5, screenToNavigate: const EncryptionSettings(), twoColumns: widget.twoColumns, ), @@ -177,7 +186,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.route_rounded, title: AppLocalizations.of(context)!.dnsRewrites, subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, - thisItem: 5, + thisItem: 6, screenToNavigate: const DnsRewritesScreen(), twoColumns: widget.twoColumns, ), @@ -197,7 +206,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { ), ) : null, - thisItem: 6, + thisItem: 7, screenToNavigate: const UpdateScreen(), twoColumns: widget.twoColumns, ), @@ -205,7 +214,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.info_rounded, title: AppLocalizations.of(context)!.serverInformation, subtitle: AppLocalizations.of(context)!.serverInformationDescription, - thisItem: 7, + thisItem: 8, screenToNavigate: const ServerInformation(), twoColumns: widget.twoColumns, ), @@ -215,7 +224,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.palette_rounded, title: AppLocalizations.of(context)!.customization, subtitle: AppLocalizations.of(context)!.customizationDescription, - thisItem: 8, + thisItem: 9, screenToNavigate: const Customization(), twoColumns: widget.twoColumns, ), @@ -227,7 +236,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" : AppLocalizations.of(context)!.noServerSelected, - thisItem: 9, + thisItem: 10, screenToNavigate: const Servers(), twoColumns: widget.twoColumns, ), @@ -235,7 +244,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.settings, title: AppLocalizations.of(context)!.generalSettings, subtitle: AppLocalizations.of(context)!.generalSettingsDescription, - thisItem: 10, + thisItem: 11, screenToNavigate: GeneralSettings(splitView: widget.twoColumns), twoColumns: widget.twoColumns, ), @@ -243,7 +252,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.build_outlined, title: AppLocalizations.of(context)!.advancedSettings, subtitle: AppLocalizations.of(context)!.advancedSetupDescription, - thisItem: 11, + thisItem: 12, screenToNavigate: const AdvancedSettings(), twoColumns: widget.twoColumns, ), diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index b45622a..f48d6d7 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -649,7 +649,7 @@ class ApiClientV2 { } Future clearLogs() async { - final result = await HttpRequestClient.put( + final result = await HttpRequestClient.post( urlPath: '/querylog_clear', server: server, body: {}, From c12e8c5ad342c23982c267a9927cdb2248a0c803 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 Jan 2024 15:14:19 +0100 Subject: [PATCH 487/676] Added ignored domains list config --- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/models/querylog_config.dart | 27 ++++ .../logs_settings/config_widgets.dart | 117 ++++++++++++++++-- .../settings/logs_settings/logs_settings.dart | 79 +++++++++--- lib/services/api_client.dart | 18 ++- 6 files changed, 218 insertions(+), 31 deletions(-) create mode 100644 lib/models/querylog_config.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 79081e5..b7e9999 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -727,5 +727,7 @@ "dnsCacheNumber": "DNS cache size must be a number", "errors": "Errors", "redirectHttpsWarning": "If you have enabled \"Redirect to HTTPS automatically\" on your AdGuard Home server, you must select an HTTPS connection and use the HTTPS port of your server.", - "logsSettingsDescription": "Configure query logs" + "logsSettingsDescription": "Configure query logs", + "ignoredDomains": "Ignored domains", + "noIgnoredDomainsAdded": "No domains to ignore added" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 3846777..0ea54a0 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -727,5 +727,7 @@ "dnsCacheNumber": "El tamaño de caché de DNS debe ser un número", "errors": "Errores", "redirectHttpsWarning": "Si tienes activado \"Redireccionar a HTTPS automáticamente\" en tu servidor AdGuard Home, debes seleccionar una conexión HTTPS y utilizar el puerto de HTTPS de tu servidor.", - "logsSettingsDescription": "Configura los registros de peticiones" + "logsSettingsDescription": "Configura los registros de peticiones", + "ignoredDomains": "Dominios ignorados", + "noIgnoredDomainsAdded": "No hay añadidos dominios para ignorar" } \ No newline at end of file diff --git a/lib/models/querylog_config.dart b/lib/models/querylog_config.dart new file mode 100644 index 0000000..dfb80b4 --- /dev/null +++ b/lib/models/querylog_config.dart @@ -0,0 +1,27 @@ +class QueryLogConfig { + final List? ignored; + final int? interval; + final bool? enabled; + final bool? anonymizeClientIp; + + QueryLogConfig({ + this.ignored, + this.interval, + this.enabled, + this.anonymizeClientIp, + }); + + factory QueryLogConfig.fromJson(Map json) => QueryLogConfig( + ignored: json["ignored"] == null ? [] : List.from(json["ignored"]!.map((x) => x)), + interval: json["interval"], + enabled: json["enabled"], + anonymizeClientIp: json["anonymize_client_ip"], + ); + + Map toJson() => { + "ignored": ignored == null ? [] : List.from(ignored!.map((x) => x)), + "interval": interval, + "enabled": enabled, + "anonymize_client_ip": anonymizeClientIp, + }; +} diff --git a/lib/screens/settings/logs_settings/config_widgets.dart b/lib/screens/settings/logs_settings/config_widgets.dart index 3374854..4dbaee7 100644 --- a/lib/screens/settings/logs_settings/config_widgets.dart +++ b/lib/screens/settings/logs_settings/config_widgets.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/settings/logs_settings/logs_settings.dart'; +import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; class LogsConfigOptions extends StatelessWidget { @@ -13,6 +16,8 @@ class LogsConfigOptions extends StatelessWidget { final void Function(double?) updateRetentionTime; final void Function() onClear; final void Function() onConfirm; + final List ignoredDomainsControllers; + final void Function(List) updateIgnoredDomainsControllers; const LogsConfigOptions({ super.key, @@ -24,11 +29,15 @@ class LogsConfigOptions extends StatelessWidget { required this.retentionTime, required this.updateRetentionTime, required this.onClear, - required this.onConfirm + required this.onConfirm, + required this.ignoredDomainsControllers, + required this.updateIgnoredDomainsControllers }); @override Widget build(BuildContext context) { + const Uuid uuid = Uuid(); + final List dropdownItemTranslation = [ AppLocalizations.of(context)!.hours6, AppLocalizations.of(context)!.hours24, @@ -37,7 +46,28 @@ class LogsConfigOptions extends StatelessWidget { AppLocalizations.of(context)!.days90, ]; - return Column( + void validateDomain(String value, String id) { + final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); + bool error = false; + if (domainRegex.hasMatch(value)) { + error = false; + } + else { + error = true; + } + updateIgnoredDomainsControllers( + ignoredDomainsControllers.map((entry) { + if (entry.id != id) return entry; + return DomainListItemController( + id: id, + controller: entry.controller, + error: error + ); + }).toList() + ); + } + + return ListView( children: [ const SizedBox(height: 16), Padding( @@ -100,12 +130,83 @@ class LogsConfigOptions extends StatelessWidget { borderRadius: BorderRadius.circular(20), ), ), - const SizedBox(height: 24), - ElevatedButton.icon( - onPressed: onClear, - icon: const Icon(Icons.delete_rounded), - label: Text(AppLocalizations.of(context)!.clearLogs), - ) + Padding( + padding: const EdgeInsets.only(top: 24, bottom: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SectionLabel( + label: AppLocalizations.of(context)!.ignoredDomains, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 0), + ), + Padding( + padding: const EdgeInsets.only(right: 10), + child: IconButton( + onPressed: () => updateIgnoredDomainsControllers([ + ...ignoredDomainsControllers, + DomainListItemController( + id: uuid.v4(), + controller: TextEditingController(), + error: false + ), + ]), + icon: const Icon(Icons.add) + ), + ) + ], + ), + ), + if (ignoredDomainsControllers.isNotEmpty) ...ignoredDomainsControllers.map((controller) => Padding( + padding: const EdgeInsets.only( + top: 12, bottom: 12, left: 24, right: 10 + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: TextFormField( + controller: controller.controller, + onChanged: (v) => validateDomain(v, controller.id), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.domain, + errorText: controller.error + ? AppLocalizations.of(context)!.invalidDomain + : null + ), + ), + ), + const SizedBox(width: 12), + Padding( + padding: controller.error + ? const EdgeInsets.only(bottom: 24) + : const EdgeInsets.all(0), + child: IconButton( + onPressed: () => updateIgnoredDomainsControllers( + ignoredDomainsControllers.where((e) => e.id != controller.id).toList() + ), + icon: const Icon(Icons.remove_circle_outline_outlined) + ), + ) + ], + ), + )), + if (ignoredDomainsControllers.isEmpty) Container( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Text( + AppLocalizations.of(context)!.noIgnoredDomainsAdded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), ], ); } diff --git a/lib/screens/settings/logs_settings/logs_settings.dart b/lib/screens/settings/logs_settings/logs_settings.dart index 2fc6892..8c651e0 100644 --- a/lib/screens/settings/logs_settings/logs_settings.dart +++ b/lib/screens/settings/logs_settings/logs_settings.dart @@ -1,15 +1,29 @@ import 'package:flutter/material.dart'; 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/settings/logs_settings/config_widgets.dart'; +import 'package:adguard_home_manager/models/querylog_config.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; +class DomainListItemController { + final String id; + final TextEditingController controller; + bool error; + + DomainListItemController({ + required this.id, + required this.controller, + required this.error + }); +} + class LogsSettings extends StatefulWidget { const LogsSettings({super.key}); @@ -18,9 +32,12 @@ class LogsSettings extends StatefulWidget { } class _LogsSettingsState extends State { + final Uuid uuid = const Uuid(); + bool generalSwitch = false; bool anonymizeClientIp = false; double? retentionTime; + List _ignoredDomainsControllers = []; List retentionItems = [ 21600000, @@ -37,20 +54,27 @@ class _LogsSettingsState extends State { final result = await serversProvider.apiClient2!.getQueryLogInfo(); - if (mounted) { - if (result.successful == true) { - setState(() { - generalSwitch = result.content['enabled']; - anonymizeClientIp = result.content['anonymize_client_ip']; - retentionTime = result.content['interval'] != null - ? double.parse(result.content['interval'].toString()) - : null; - loadStatus = LoadStatus.loaded; - }); - } - else { - setState(() => loadStatus = LoadStatus.error); - } + if (!mounted) return; + if (result.successful == true) { + final data = result.content as QueryLogConfig; + setState(() { + generalSwitch = data.enabled ?? false; + anonymizeClientIp = data.anonymizeClientIp ?? false; + retentionTime = data.interval != null + ? double.parse(data.interval.toString()) + : null; + if (data.ignored != null) { + _ignoredDomainsControllers = data.ignored!.map((e) => DomainListItemController( + id: uuid.v4(), + controller: TextEditingController(text: e), + error: false + )).toList(); + } + loadStatus = LoadStatus.loaded; + }); + } + else { + setState(() => loadStatus = LoadStatus.error); } } @@ -65,6 +89,10 @@ class _LogsSettingsState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final validValues = _ignoredDomainsControllers.where( + (d) => d.controller.text == "" || d.error == true + ).isEmpty; + void clearQueries() async { ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.updatingSettings); @@ -99,7 +127,8 @@ class _LogsSettingsState extends State { data: { "enabled": generalSwitch, "interval": retentionTime, - "anonymize_client_ip": anonymizeClientIp + "anonymize_client_ip": anonymizeClientIp, + "ignored": _ignoredDomainsControllers.map((e) => e.controller.text).toList() } ); @@ -128,10 +157,24 @@ class _LogsSettingsState extends State { title: Text(AppLocalizations.of(context)!.logsSettings), actions: [ if (loadStatus == LoadStatus.loaded) IconButton( - onPressed: updateConfig, + onPressed: validValues ? () => updateConfig() : null, icon: const Icon(Icons.save_rounded), tooltip: AppLocalizations.of(context)!.save, ), + if (loadStatus == LoadStatus.loaded) PopupMenuButton( + itemBuilder: (context) => [ + PopupMenuItem( + onTap: clearQueries, + child: Row( + children: [ + const Icon(Icons.delete_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.clearLogs), + ], + ) + ) + ], + ), const SizedBox(width: 8) ], ), @@ -151,7 +194,9 @@ class _LogsSettingsState extends State { retentionTime: retentionTime, updateRetentionTime: (v) => setState(() => retentionTime = v), onClear: clearQueries, - onConfirm: updateConfig + onConfirm: updateConfig, + ignoredDomainsControllers: _ignoredDomainsControllers, + updateIgnoredDomainsControllers: (v) => setState(() => _ignoredDomainsControllers = v), ); case LoadStatus.error: diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index f48d6d7..b122a8c 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:adguard_home_manager/models/blocked_services.dart'; +import 'package:adguard_home_manager/models/querylog_config.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/encryption.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; @@ -627,10 +628,19 @@ class ApiClientV2 { Future getQueryLogInfo() async { final result = await HttpRequestClient.get(urlPath: '/querylog/config', server: server); if (result.successful) { - return ApiResponse( - successful: true, - content: jsonDecode(result.body!) - ); + try { + return ApiResponse( + successful: true, + content: QueryLogConfig.fromJson(jsonDecode(result.body!)) + ); + } catch (e, stackTrace) { + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); + return const ApiResponse(successful: false); + } } else { return const ApiResponse(successful: false); From 9529cd6f567d32d5c6d7ea32a3917b89b0b12b59 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 Jan 2024 00:39:36 +0100 Subject: [PATCH 488/676] Replaced ring chart with bar chart --- .../home/top_items/top_items_section.dart | 195 +++++++----------- 1 file changed, 75 insertions(+), 120 deletions(-) diff --git a/lib/screens/home/top_items/top_items_section.dart b/lib/screens/home/top_items/top_items_section.dart index bc021cf..2c6f0c1 100644 --- a/lib/screens/home/top_items/top_items_section.dart +++ b/lib/screens/home/top_items/top_items_section.dart @@ -10,6 +10,7 @@ import 'package:adguard_home_manager/screens/home/top_items/row_item.dart'; import 'package:adguard_home_manager/screens/home/top_items/top_items_screen.dart'; import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; +import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -64,7 +65,7 @@ class _TopItemsState extends State { final withChart = widget.type != HomeTopItems.avgUpstreamResponseTime; - Map chartData() { + Map ringData() { Map values = {}; widget.data.sublist(0, widget.data.length > 5 ? 5 : widget.data.length).forEach((element) { values = { @@ -84,6 +85,29 @@ class _TopItemsState extends State { return values; } + List> lineData() { + List> values = []; + widget.data.sublist(0, widget.data.length > 5 ? 5 : widget.data.length).forEach((element) { + values.add({ + "label": element.keys.first, + "value": element.values.first.toDouble() + }); + }); + if (widget.data.length > 5) { + final int rest = List.from( + widget.data.sublist(5, widget.data.length).map((e) => e.values.first.toInt()) + ).reduce((a, b) => a + b); + values.add({ + "label": AppLocalizations.of(context)!.others, + "value": rest.toDouble() + }); + } + return values; + } + + final data = lineData(); + final total = data.map((e) => e["value"]).reduce((a, b) => a + b); + final Widget noItems = Padding( padding: const EdgeInsets.only( bottom: 20, @@ -116,7 +140,7 @@ class _TopItemsState extends State { child: Padding( padding: const EdgeInsets.all(16), child: CustomPieChart( - data: chartData(), + data: ringData(), colors: colors ) ), @@ -159,126 +183,57 @@ class _TopItemsState extends State { ], ), ), - if (widget.data.isNotEmpty && width <= 700) Builder( - builder: (context) { - if (widget.withChart == true) { - return Column( - children: [ - ExpansionPanelList( - expandedHeaderPadding: const EdgeInsets.all(0), - elevation: 0, - expansionCallback: (_, isExpanded) => setState(() => _showChart = isExpanded), - animationDuration: const Duration(milliseconds: 250), - children: [ - ExpansionPanel( - headerBuilder: (context, isExpanded) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( - mainAxisAlignment: width <= 700 - ? MainAxisAlignment.spaceBetween - : MainAxisAlignment.center, - children: [ - Flexible( - child: Text( - widget.label, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - ], - ), + if (widget.data.isNotEmpty && width <= 700) ...[ + Text( + widget.label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 8), + if (withChart == true) Padding( + padding: const EdgeInsets.all(16), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: SizedBox( + height: 20, + child: LayoutBuilder( + builder: (context, constraints) => Row( + children: data.asMap().entries.map((e) => Tooltip( + message:'${e.value["label"]} (${doubleFormat((e.value["value"]/total)*100, Platform.localeName)}%)', + child: Container( + width: constraints.maxWidth*(e.value["value"]/total), + decoration: BoxDecoration( + color: colors[e.key] ), - body: Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Column( - children: [ - SizedBox( - height: 150, - child: CustomPieChart( - data: chartData(), - colors: colors - ) - ), - const SizedBox(height: 16), - ], - ), - ), - isExpanded: _showChart ), - ], - ), - Padding( - padding: const EdgeInsets.only(top: 8), - child: _ItemsList( - colors: colors, - data: widget.data, - clients: widget.type == HomeTopItems.recurrentClients, - type: widget.type, - showChart: _showChart, - buildValue: widget.buildValue, - menuOptions: widget.menuOptions, - onTapEntry: widget.onTapEntry, - ), - ), - if (widget.withChart == true) OthersRowItem( - items: widget.data, - showColor: _showChart, - ), - const SizedBox(height: 16), - ], - ); - } - else { - return Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 18), - child: Row( - mainAxisAlignment: width <= 700 - ? MainAxisAlignment.spaceBetween - : MainAxisAlignment.center, - children: [ - Flexible( - child: Text( - widget.label, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top: 16), - child: _ItemsList( - colors: colors, - data: widget.data, - clients: widget.type == HomeTopItems.recurrentClients, - type: widget.type, - showChart: false, - buildValue: widget.buildValue, - menuOptions: widget.menuOptions, - onTapEntry: widget.onTapEntry, - ), - ), - if (widget.withChart == true) OthersRowItem( - items: widget.data, - showColor: false, - ), - const SizedBox(height: 16), - ], - ); - } - }, - ), + )).toList() + ) + ) + ), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 8), + child: _ItemsList( + colors: colors, + data: widget.data, + clients: widget.type == HomeTopItems.recurrentClients, + type: widget.type, + showChart: withChart == false ? false : _showChart, + buildValue: widget.buildValue, + menuOptions: widget.menuOptions, + onTapEntry: widget.onTapEntry, + ), + ), + OthersRowItem( + items: widget.data, + showColor: withChart == false ? false : _showChart, + ), + ], if (widget.data.length > 5) ...[ Padding( From 2fd829021c28e438b9b38c6a780585784cfe61b4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 Jan 2024 00:47:20 +0100 Subject: [PATCH 489/676] Removed config variable --- lib/providers/app_config_provider.dart | 24 ---- .../home/top_items/top_items_section.dart | 117 ++++++++---------- .../general_settings/general_settings.dart | 22 ---- lib/services/db/database.dart | 33 +++-- 4 files changed, 77 insertions(+), 119 deletions(-) diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index d44b5af..99e2f0f 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -52,8 +52,6 @@ class AppConfigProvider with ChangeNotifier { int _combinedChartHome = 0; - int _showTopItemsChart = 0; - String? _doNotRememberVersion; GitHubRelease? _appUpdatesAvailable; @@ -170,10 +168,6 @@ class AppConfigProvider with ChangeNotifier { return _hideServerAddress == 1 ? true : false; } - bool get showTopItemsChart { - return _showTopItemsChart == 1 ? true : false; - } - void setDbInstance(Database db) { _dbInstance = db; } @@ -408,23 +402,6 @@ class AppConfigProvider with ChangeNotifier { } } - Future setShowTopItemsChart(bool value) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'showTopItemsChart', - value: value == true ? 1 : 0 - ); - if (updated == true) { - _showTopItemsChart = value == true ? 1 : 0; - notifyListeners(); - return true; - } - else { - return false; - } - } - - Future setDoNotRememberVersion(String value) async { final updated = await updateConfigQuery( db: _dbInstance!, @@ -446,7 +423,6 @@ class AppConfigProvider with ChangeNotifier { _showIpLogs = dbData['showIpLogs'] ?? 0; _combinedChartHome = dbData['combinedChart'] ?? 0; _hideServerAddress = dbData['hideServerAddress']; - _showTopItemsChart = dbData['showTopItemsChart']; if (dbData['homeTopItemsOrder'] != null) { try { final itemsOrder = List.from( diff --git a/lib/screens/home/top_items/top_items_section.dart b/lib/screens/home/top_items/top_items_section.dart index 2c6f0c1..475ffb9 100644 --- a/lib/screens/home/top_items/top_items_section.dart +++ b/lib/screens/home/top_items/top_items_section.dart @@ -3,7 +3,6 @@ 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/home/top_items/row_item.dart'; @@ -13,9 +12,8 @@ import 'package:adguard_home_manager/widgets/custom_pie_chart.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -class TopItemsSection extends StatefulWidget { +class TopItemsSection extends StatelessWidget { final HomeTopItems type; final String label; final List> data; @@ -37,45 +35,32 @@ class TopItemsSection extends StatefulWidget { this.onTapEntry, }); - @override - State createState() => _TopItemsState(); -} - -class _TopItemsState extends State { - bool _showChart = true; - - final colors = [ - Colors.red, - Colors.green, - Colors.blue, - Colors.orange, - Colors.teal, - Colors.grey - ]; - - @override - void initState() { - _showChart = Provider.of(context, listen: false).showTopItemsChart; - super.initState(); - } - @override Widget build(BuildContext context) { + final colors = [ + Colors.red, + Colors.green, + Colors.blue, + Colors.orange, + Colors.teal, + Colors.grey + ]; + final width = MediaQuery.of(context).size.width; - final withChart = widget.type != HomeTopItems.avgUpstreamResponseTime; + final withChart = type != HomeTopItems.avgUpstreamResponseTime; Map ringData() { Map values = {}; - widget.data.sublist(0, widget.data.length > 5 ? 5 : widget.data.length).forEach((element) { + data.sublist(0, data.length > 5 ? 5 : data.length).forEach((element) { values = { ...values, element.keys.first: element.values.first.toDouble() }; }); - if (widget.data.length > 5) { + if (data.length > 5) { final int rest = List.from( - widget.data.sublist(5, widget.data.length).map((e) => e.values.first.toInt()) + data.sublist(5, data.length).map((e) => e.values.first.toInt()) ).reduce((a, b) => a + b); values = { ...values, @@ -87,15 +72,15 @@ class _TopItemsState extends State { List> lineData() { List> values = []; - widget.data.sublist(0, widget.data.length > 5 ? 5 : widget.data.length).forEach((element) { + data.sublist(0, data.length > 5 ? 5 : data.length).forEach((element) { values.add({ "label": element.keys.first, "value": element.values.first.toDouble() }); }); - if (widget.data.length > 5) { + if (data.length > 5) { final int rest = List.from( - widget.data.sublist(5, widget.data.length).map((e) => e.values.first.toInt()) + data.sublist(5, data.length).map((e) => e.values.first.toInt()) ).reduce((a, b) => a + b); values.add({ "label": AppLocalizations.of(context)!.others, @@ -105,8 +90,8 @@ class _TopItemsState extends State { return values; } - final data = lineData(); - final total = data.map((e) => e["value"]).reduce((a, b) => a + b); + final lineChartData = lineData(); + final total = lineChartData.map((e) => e["value"]).reduce((a, b) => a + b); final Widget noItems = Padding( padding: const EdgeInsets.only( @@ -125,8 +110,8 @@ class _TopItemsState extends State { return SizedBox( child: Column( children: [ - if (widget.data.isEmpty) noItems, - if (widget.data.isNotEmpty && width > 700) Padding( + if (data.isEmpty) noItems, + if (data.isNotEmpty && width > 700) Padding( padding: EdgeInsets.only(bottom: withChart == false ? 16 : 0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, @@ -156,7 +141,7 @@ class _TopItemsState extends State { bottom: 16 ), child: Text( - widget.label, + label, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w500 @@ -165,16 +150,16 @@ class _TopItemsState extends State { ), _ItemsList( colors: colors, - data: widget.data, - clients: widget.type == HomeTopItems.recurrentClients, - type: widget.type, - showChart: withChart == true ? _showChart : false, - buildValue: widget.buildValue, - menuOptions: widget.menuOptions, - onTapEntry: widget.onTapEntry, + data: data, + clients: type == HomeTopItems.recurrentClients, + type: type, + showChart: withChart, + buildValue: buildValue, + menuOptions: menuOptions, + onTapEntry: onTapEntry, ), if (withChart == true) OthersRowItem( - items: widget.data, + items: data, showColor: true, ) ] @@ -183,9 +168,9 @@ class _TopItemsState extends State { ], ), ), - if (widget.data.isNotEmpty && width <= 700) ...[ + if (data.isNotEmpty && width <= 700) ...[ Text( - widget.label, + label, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 18, @@ -202,7 +187,7 @@ class _TopItemsState extends State { height: 20, child: LayoutBuilder( builder: (context, constraints) => Row( - children: data.asMap().entries.map((e) => Tooltip( + children: lineChartData.asMap().entries.map((e) => Tooltip( message:'${e.value["label"]} (${doubleFormat((e.value["value"]/total)*100, Platform.localeName)}%)', child: Container( width: constraints.maxWidth*(e.value["value"]/total), @@ -220,22 +205,22 @@ class _TopItemsState extends State { padding: const EdgeInsets.only(top: 8), child: _ItemsList( colors: colors, - data: widget.data, - clients: widget.type == HomeTopItems.recurrentClients, - type: widget.type, - showChart: withChart == false ? false : _showChart, - buildValue: widget.buildValue, - menuOptions: widget.menuOptions, - onTapEntry: widget.onTapEntry, + data: data, + clients: type == HomeTopItems.recurrentClients, + type: type, + showChart: withChart, + buildValue: buildValue, + menuOptions: menuOptions, + onTapEntry: onTapEntry, ), ), OthersRowItem( - items: widget.data, - showColor: withChart == false ? false : _showChart, + items: data, + showColor: withChart, ), ], - if (widget.data.length > 5) ...[ + if (data.length > 5) ...[ Padding( padding: const EdgeInsets.only(right: 20), child: Row( @@ -263,14 +248,14 @@ class _TopItemsState extends State { ); }, pageBuilder: (context, animation, secondaryAnimation) => TopItemsScreen( - type: widget.type, - title: widget.label, - isClient: widget.type == HomeTopItems.recurrentClients, - data: widget.data, - withProgressBar: widget.withProgressBar, - buildValue: widget.buildValue, - options: widget.menuOptions, - onTapEntry: widget.onTapEntry, + type: type, + title: label, + isClient: type == HomeTopItems.recurrentClients, + data: data, + withProgressBar: withProgressBar, + buildValue: buildValue, + options: menuOptions, + onTapEntry: onTapEntry, isFullscreen: !(width > 700 || !(Platform.isAndroid | Platform.isIOS)), ) ) diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index 74cc752..fb0560c 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -206,28 +206,6 @@ class _GeneralSettingsState extends State { ) ) ), - CustomListTile( - icon: Icons.donut_large_rounded, - title: AppLocalizations.of(context)!.showTopItemsChart, - subtitle: AppLocalizations.of(context)!.showTopItemsChartDescription, - trailing: Switch( - value: appConfigProvider.showTopItemsChart, - onChanged: (value) => updateSettings( - newStatus: value, - function: appConfigProvider.setShowTopItemsChart - ), - ), - onTap: () => updateSettings( - newStatus: !appConfigProvider.showTopItemsChart, - function: appConfigProvider.setShowTopItemsChart - ), - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 16, - right: 10 - ) - ), SectionLabel(label: AppLocalizations.of(context)!.logs), CustomListTile( icon: Icons.timer_rounded, diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index 7d8cf13..b60b38a 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -127,9 +127,19 @@ Future> loadDb(bool acceptsDynamicTheme) async { }); } + Future upgradeDbToV11(Database db) async { + await db.execute("ALTER TABLE appConfig DROP COLUMN showTopItemsChart"); + + await db.transaction((txn) async{ + await txn.rawQuery( + 'SELECT * FROM appConfig', + ); + }); + } + Database db = await openDatabase( 'adguard_home_manager.db', - version: 10, + version: 11, onCreate: (Database db, int version) async { await db.execute( """ @@ -165,8 +175,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { combinedChart NUMERIC, doNotRememberVersion TEXT, hideServerAddress NUMERIC, - homeTopItemsOrder TEXT, - showTopItemsChart NUMERIC + homeTopItemsOrder TEXT ) """ ); @@ -185,8 +194,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { showIpLogs, combinedChart, hideServerAddress, - homeTopItemsOrder, - showTopItemsChart + homeTopItemsOrder ) VALUES ( 0, @@ -199,8 +207,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { 0, 0, 0, - '$homeTopItemsDefaultOrderString', - 1 + '$homeTopItemsDefaultOrderString' ) """ ); @@ -216,6 +223,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV8(db); await upgradeDbToV9(db); await upgradeDbToV10(db); + await upgradeDbToV11(db); } if (oldVersion == 2) { await upgradeDbToV3(db); @@ -226,6 +234,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV8(db); await upgradeDbToV9(db); await upgradeDbToV10(db); + await upgradeDbToV11(db); } if (oldVersion == 3) { await upgradeDbToV4(db); @@ -235,6 +244,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV8(db); await upgradeDbToV9(db); await upgradeDbToV10(db); + await upgradeDbToV11(db); } if (oldVersion == 4) { await upgradeDbToV5(db); @@ -243,6 +253,7 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV8(db); await upgradeDbToV9(db); await upgradeDbToV10(db); + await upgradeDbToV11(db); } if (oldVersion == 5) { await upgradeDbToV6(db); @@ -250,24 +261,32 @@ Future> loadDb(bool acceptsDynamicTheme) async { await upgradeDbToV8(db); await upgradeDbToV9(db); await upgradeDbToV10(db); + await upgradeDbToV11(db); } if (oldVersion == 6) { await upgradeDbToV7(db); await upgradeDbToV8(db); await upgradeDbToV9(db); await upgradeDbToV10(db); + await upgradeDbToV11(db); } if (oldVersion == 7) { await upgradeDbToV8(db); await upgradeDbToV9(db); await upgradeDbToV10(db); + await upgradeDbToV11(db); } if (oldVersion == 8) { await upgradeDbToV9(db); await upgradeDbToV10(db); + await upgradeDbToV11(db); } if (oldVersion == 9) { await upgradeDbToV10(db); + await upgradeDbToV11(db); + } + if (oldVersion == 10) { + await upgradeDbToV11(db); } }, onOpen: (Database db) async { From a40580f425c9f4ac13d4e288d0c95f3505a7a456 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 Jan 2024 00:50:35 +0100 Subject: [PATCH 490/676] Removed top items entries animation --- lib/screens/home/top_items/row_item.dart | 225 ++++++----------------- 1 file changed, 61 insertions(+), 164 deletions(-) diff --git a/lib/screens/home/top_items/row_item.dart b/lib/screens/home/top_items/row_item.dart index b323eb0..bc8856b 100644 --- a/lib/screens/home/top_items/row_item.dart +++ b/lib/screens/home/top_items/row_item.dart @@ -8,7 +8,7 @@ import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; -class RowItem extends StatefulWidget { +class RowItem extends StatelessWidget { final HomeTopItems type; final Color chartColor; final String domain; @@ -32,61 +32,14 @@ class RowItem extends StatefulWidget { this.unit, }); - @override - State createState() => _RowItemState(); -} - -class _RowItemState extends State with TickerProviderStateMixin { - late AnimationController expandController; - late Animation animation; - - @override - void initState() { - super.initState(); - prepareAnimations(); - _runExpandCheck(); - } - - void prepareAnimations() { - expandController = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 250) - ); - animation = CurvedAnimation( - parent: expandController, - curve: Curves.ease, - ); - } - - void _runExpandCheck() { - if (widget.showColor) { - expandController.forward(); - } - else { - expandController.reverse(); - } - } - - @override - void didUpdateWidget(oldWidget) { - super.didUpdateWidget(oldWidget); - _runExpandCheck(); - } - - @override - void dispose() { - expandController.dispose(); - super.dispose(); - } - @override Widget build(BuildContext context) { final statusProvider = Provider.of(context); String? name; - if (widget.clients == true) { + if (clients == true) { try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(widget.domain)).name; + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(domain)).name; } catch (e) { // ---- // } @@ -95,9 +48,9 @@ class _RowItemState extends State with TickerProviderStateMixin { return Material( color: Colors.transparent, child: OptionsMenu( - value: widget.domain, - options: widget.options, - onTap: widget.onTapEntry, + value: domain, + options: options, + onTap: onTapEntry, child: Padding( padding: const EdgeInsets.symmetric( horizontal: 20, @@ -109,18 +62,13 @@ class _RowItemState extends State with TickerProviderStateMixin { Flexible( child: Row( children: [ - SizeTransition( - axisAlignment: 1.0, - sizeFactor: animation, - axis: Axis.horizontal, - child: Container( - margin: const EdgeInsets.only(right: 16), - width: 12, - height: 12, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - color: widget.chartColor - ), + Container( + margin: const EdgeInsets.only(right: 16), + width: 12, + height: 12, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: chartColor ), ), Expanded( @@ -128,7 +76,7 @@ class _RowItemState extends State with TickerProviderStateMixin { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.domain, + domain, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 16, @@ -154,7 +102,7 @@ class _RowItemState extends State with TickerProviderStateMixin { ), const SizedBox(width: 16), Text( - widget.number, + number, style: TextStyle( color: Theme.of(context).colorScheme.onSurface ), @@ -167,7 +115,7 @@ class _RowItemState extends State with TickerProviderStateMixin { } } -class OthersRowItem extends StatefulWidget { +class OthersRowItem extends StatelessWidget { final List> items; final bool showColor; @@ -177,111 +125,60 @@ class OthersRowItem extends StatefulWidget { required this.showColor, }); - @override - State createState() => _OthersRowItemState(); -} - -class _OthersRowItemState extends State with SingleTickerProviderStateMixin { - late AnimationController expandController; - late Animation animation; - - @override - void initState() { - super.initState(); - prepareAnimations(); - _runExpandCheck(); - } - - void prepareAnimations() { - expandController = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 250) - ); - animation = CurvedAnimation( - parent: expandController, - curve: Curves.ease, - ); - } - - void _runExpandCheck() { - if (widget.showColor) { - expandController.forward(); - } - else { - expandController.reverse(); - } - } - - @override - void didUpdateWidget(oldWidget) { - super.didUpdateWidget(oldWidget); - _runExpandCheck(); - } - - @override - void dispose() { - expandController.dispose(); - super.dispose(); - } - @override Widget build(BuildContext context) { - if (widget.items.length <= 5) { + if (items.length <= 5) { return const SizedBox(); } - return SizeTransition( - axisAlignment: 1.0, - sizeFactor: animation, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Row( - children: [ - Container( - margin: const EdgeInsets.only(right: 16), - width: 12, - height: 12, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - color: Colors.grey - ), + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + children: [ + Container( + margin: const EdgeInsets.only(right: 16), + width: 12, + height: 12, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Colors.grey ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.others, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.others, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface ), - ], - ), + ), + ], ), - ], - ), + ), + ], ), - const SizedBox(width: 16), - Text( - List.from( - widget.items.sublist(5, widget.items.length).map((e) => e.values.first.toInt()) - ).reduce((a, b) => a + b).toString(), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), + ), + const SizedBox(width: 16), + Text( + List.from( + items.sublist(5, items.length).map((e) => e.values.first.toInt()) + ).reduce((a, b) => a + b).toString(), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], ), ); } From 2d991ce9dfadaf6538a06a003b094586fc4e10d9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 Jan 2024 00:51:46 +0100 Subject: [PATCH 491/676] Fixed showColor --- lib/screens/home/top_items/row_item.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/home/top_items/row_item.dart b/lib/screens/home/top_items/row_item.dart index bc8856b..bfa43e7 100644 --- a/lib/screens/home/top_items/row_item.dart +++ b/lib/screens/home/top_items/row_item.dart @@ -62,7 +62,7 @@ class RowItem extends StatelessWidget { Flexible( child: Row( children: [ - Container( + if (showColor == true) Container( margin: const EdgeInsets.only(right: 16), width: 12, height: 12, @@ -142,7 +142,7 @@ class OthersRowItem extends StatelessWidget { Flexible( child: Row( children: [ - Container( + if (showColor == true) Container( margin: const EdgeInsets.only(right: 16), width: 12, height: 12, From 5b2523158b46e522fa48ade1beb4e77ab7174d5a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 Jan 2024 00:55:12 +0100 Subject: [PATCH 492/676] Small change --- lib/widgets/custom_pie_chart.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/widgets/custom_pie_chart.dart b/lib/widgets/custom_pie_chart.dart index 0c8f9f6..343ec58 100644 --- a/lib/widgets/custom_pie_chart.dart +++ b/lib/widgets/custom_pie_chart.dart @@ -7,11 +7,11 @@ class CustomPieChart extends StatelessWidget { final Duration? animationDuration; const CustomPieChart({ - Key? key, + super.key, required this.data, required this.colors, - this.animationDuration = const Duration(milliseconds: 800), - }) : super(key: key); + this.animationDuration = const Duration(milliseconds: 800), + }); @override Widget build(BuildContext context) { From d73ad93180fb5191d2d4270279d06e6526a9a1cc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 25 Jan 2024 22:34:30 +0100 Subject: [PATCH 493/676] Created block time schedule settings --- README.md | 1 + lib/l10n/app_en.arb | 20 +- lib/l10n/app_es.arb | 18 +- lib/models/clients.dart | 68 ++++- .../clients/client/blocking_schedule.dart | 143 +++++++++ .../client/blocking_schedule_modal.dart | 283 ++++++++++++++++++ lib/screens/clients/client/client_form.dart | 10 + lib/screens/clients/client/client_screen.dart | 16 +- pubspec.lock | 8 + pubspec.yaml | 1 + 10 files changed, 560 insertions(+), 8 deletions(-) create mode 100644 lib/screens/clients/client/blocking_schedule.dart create mode 100644 lib/screens/clients/client/blocking_schedule_modal.dart diff --git a/README.md b/README.md index 930d090..fb9505d 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [flutter reorderable list](https://pub.dev/packages/flutter_reorderable_list) - [pie chart](https://pub.dev/packages/pie_chart) - [segmented button slide](https://pub.dev/packages/segmented_button_slide) +- [timezone](https://pub.dev/packages/timezone)
    diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index b7e9999..6e281d4 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -719,7 +719,7 @@ "unblockClient": "Unblock client", "blockingClient": "Blocking client...", "unblockingClient": "Unblocking client...", - "upstreamDnsCacheConfiguration": "Configuración de la caché DNS upstream", + "upstreamDnsCacheConfiguration": "DNS upstream cache configuration", "enableDnsCachingClient": "Enable DNS caching for this client", "dnsCacheSize": "DNS cache size", "nameInvalid": "Name is required", @@ -729,5 +729,21 @@ "redirectHttpsWarning": "If you have enabled \"Redirect to HTTPS automatically\" on your AdGuard Home server, you must select an HTTPS connection and use the HTTPS port of your server.", "logsSettingsDescription": "Configure query logs", "ignoredDomains": "Ignored domains", - "noIgnoredDomainsAdded": "No domains to ignore added" + "noIgnoredDomainsAdded": "No domains to ignore added", + "pauseServiceBlocking": "Pause service blocking", + "newSchedule": "New schedule", + "editSchedule": "Edit schedule", + "timezone": "Timezone", + "monday": "Monday", + "tuesday": "Tuesday", + "wednesday": "Wednesday", + "thursday": "Thursday", + "friday": "Friday", + "saturday": "Saturday", + "sunday": "Sunday", + "from": "From: {from}", + "to": "To: {to}", + "selectStartTime": "Select start time", + "selectEndTime": "Select end time", + "startTimeBeforeEndTime": "Start time must be before end time." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 0ea54a0..55f8237 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -729,5 +729,21 @@ "redirectHttpsWarning": "Si tienes activado \"Redireccionar a HTTPS automáticamente\" en tu servidor AdGuard Home, debes seleccionar una conexión HTTPS y utilizar el puerto de HTTPS de tu servidor.", "logsSettingsDescription": "Configura los registros de peticiones", "ignoredDomains": "Dominios ignorados", - "noIgnoredDomainsAdded": "No hay añadidos dominios para ignorar" + "noIgnoredDomainsAdded": "No hay añadidos dominios para ignorar", + "pauseServiceBlocking": "Pausa del servicio de bloqueo", + "newSchedule": "Nueva programación", + "editSchedule": "Editar programación", + "timezone": "Zona horaria", + "monday": "Lunes", + "tuesday": "Martes", + "wednesday": "Miércoles", + "thursday": "Jueves", + "friday": "Viernes", + "saturday": "Sábado", + "sunday": "Domingo", + "from": "Desde: {from}", + "to": "Hasta: {to}", + "selectStartTime": "Seleccionar hora de inicio", + "selectEndTime": "Seleccionar hora de fin", + "startTimeBeforeEndTime": "La hora de inicio debe ser anterior a la hora de fin." } \ No newline at end of file diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 67740bd..56a967e 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -91,6 +91,7 @@ class Client { final bool? ignoreStatistics; final bool? upstreamsCacheEnabled; final int? upstreamsCacheSize; + final BlockedServicesSchedule? blockedServicesSchedule; Client({ required this.name, @@ -108,6 +109,7 @@ class Client { required this.ignoreStatistics, required this.upstreamsCacheEnabled, required this.upstreamsCacheSize, + required this.blockedServicesSchedule, }); factory Client.fromJson(Map json) => Client( @@ -127,7 +129,8 @@ class Client { ignoreQuerylog: json["ignore_querylog"], ignoreStatistics: json["ignore_statistics"], upstreamsCacheEnabled: json["upstreams_cache_enabled"], - upstreamsCacheSize: json["upstreams_cache_size"] + upstreamsCacheSize: json["upstreams_cache_size"], + blockedServicesSchedule: BlockedServicesSchedule.fromJson(json["blocked_services_schedule"]) ); Map toJson() => { @@ -145,6 +148,67 @@ class Client { "ignore_querylog": ignoreQuerylog, "ignore_statistics": ignoreStatistics, "upstreams_cache_enabled": upstreamsCacheEnabled, - "upstreams_cache_size": upstreamsCacheSize + "upstreams_cache_size": upstreamsCacheSize, + "blocked_services_schedule":blockedServicesSchedule?.toJson() + }; +} + +class BlockedServicesSchedule { + final String? timeZone; + final BlockedServicesScheduleDay? mon; + final BlockedServicesScheduleDay? tue; + final BlockedServicesScheduleDay? wed; + final BlockedServicesScheduleDay? thu; + final BlockedServicesScheduleDay? fri; + final BlockedServicesScheduleDay? sat; + final BlockedServicesScheduleDay? sun; + + BlockedServicesSchedule({ + this.timeZone, + this.mon, + this.tue, + this.wed, + this.thu, + this.fri, + this.sat, + this.sun + }); + + factory BlockedServicesSchedule.fromJson(Map json) => BlockedServicesSchedule( + timeZone: json["time_zone"], + mon: json["mon"] == null ? null : BlockedServicesScheduleDay.fromJson(json["mon"]), + tue: json["tue"] == null ? null : BlockedServicesScheduleDay.fromJson(json["tue"]), + wed: json["wed"] == null ? null : BlockedServicesScheduleDay.fromJson(json["wed"]), + thu: json["thu"] == null ? null : BlockedServicesScheduleDay.fromJson(json["thu"]), + fri: json["fri"] == null ? null : BlockedServicesScheduleDay.fromJson(json["fri"]), + sat: json["sat"] == null ? null : BlockedServicesScheduleDay.fromJson(json["sat"]), + sun: json["sun"] == null ? null : BlockedServicesScheduleDay.fromJson(json["sun"]), + ); + + Map toJson() => { + "time_zone": timeZone, + "tue": tue?.toJson(), + "wed": wed?.toJson(), + "thu": thu?.toJson(), + }; +} + +class BlockedServicesScheduleDay { + final int? start; + final int? end; + + BlockedServicesScheduleDay({ + this.start, + this.end, + }); + + factory BlockedServicesScheduleDay.fromJson(Map json) => BlockedServicesScheduleDay( + start: json["start"], + end: json["end"], + ); + + Map toJson() => { + "start": start, + "end": end, }; } \ No newline at end of file diff --git a/lib/screens/clients/client/blocking_schedule.dart b/lib/screens/clients/client/blocking_schedule.dart new file mode 100644 index 0000000..0ae7abb --- /dev/null +++ b/lib/screens/clients/client/blocking_schedule.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/clients/client/blocking_schedule_modal.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/models/clients.dart'; + +class BlockingSchedule extends StatelessWidget { + final BlockedServicesSchedule blockedServicesSchedule; + final void Function(BlockedServicesSchedule) setBlockedServicesSchedule; + + const BlockingSchedule({ + super.key, + required this.blockedServicesSchedule, + required this.setBlockedServicesSchedule, + }); + + @override + Widget build(BuildContext context) { + void openAddScheduleModal() { + showDialog( + context: context, + builder: (context) => BlockingScheduleModal( + onConfirm: (v) => {}, + ), + ); + } + + String formatTime(int time) { + final formatted = Duration(milliseconds: time); + final hours = formatted.inHours; + final minutes = formatted.inMinutes - hours*60; + return "${hours.toString().padLeft(2 , '0')}:${minutes.toString().padLeft(2, '0')}"; + } + + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SectionLabel(label: AppLocalizations.of(context)!.pauseServiceBlocking), + Padding( + padding: const EdgeInsets.only(right: 12), + child: IconButton( + onPressed: openAddScheduleModal, + icon: const Icon(Icons.add) + ), + ) + ], + ), + const SizedBox(height: 2), + if (blockedServicesSchedule.mon != null) _ScheduleTile( + weekday: AppLocalizations.of(context)!.monday, + schedule: "${formatTime(blockedServicesSchedule.mon!.start!)} - ${formatTime(blockedServicesSchedule.mon!.end!)}", + onEdit: () => {}, + onDelete: () => {} + ), + if (blockedServicesSchedule.tue != null) _ScheduleTile( + weekday: AppLocalizations.of(context)!.tuesday, + schedule: "${formatTime(blockedServicesSchedule.tue!.start!)} - ${formatTime(blockedServicesSchedule.tue!.end!)}", + onEdit: () => {}, + onDelete: () => {} + ), + if (blockedServicesSchedule.wed != null) _ScheduleTile( + weekday: AppLocalizations.of(context)!.wednesday, + schedule: "${formatTime(blockedServicesSchedule.wed!.start!)} - ${formatTime(blockedServicesSchedule.wed!.end!)}", + onEdit: () => {}, + onDelete: () => {} + ), + if (blockedServicesSchedule.thu != null) _ScheduleTile( + weekday: AppLocalizations.of(context)!.thursday, + schedule: "${formatTime(blockedServicesSchedule.thu!.start!)} - ${formatTime(blockedServicesSchedule.thu!.end!)}", + onEdit: () => {}, + onDelete: () => {} + ), + if (blockedServicesSchedule.fri != null) _ScheduleTile( + weekday: AppLocalizations.of(context)!.friday, + schedule: "${formatTime(blockedServicesSchedule.fri!.start!)} - ${formatTime(blockedServicesSchedule.fri!.end!)}", + onEdit: () => {}, + onDelete: () => {} + ), + if (blockedServicesSchedule.sat != null) _ScheduleTile( + weekday: AppLocalizations.of(context)!.saturday, + schedule: "${formatTime(blockedServicesSchedule.sat!.start!)} - ${formatTime(blockedServicesSchedule.sat!.end!)}", + onEdit: () => {}, + onDelete: () => {} + ), + if (blockedServicesSchedule.sun != null) _ScheduleTile( + weekday: AppLocalizations.of(context)!.sunday, + schedule: "${formatTime(blockedServicesSchedule.sun!.start!)} - ${formatTime(blockedServicesSchedule.sun!.end!)}", + onEdit: () => {}, + onDelete: () => {} + ), + ], + ); + } +} + +class _ScheduleTile extends StatelessWidget { + final String weekday; + final String schedule; + final void Function() onEdit; + final void Function() onDelete; + + const _ScheduleTile({ + required this.weekday, + required this.schedule, + required this.onEdit, + required this.onDelete, + }); + + @override + Widget build(BuildContext context) { + return CustomListTile( + title: weekday, + subtitle: schedule, + trailing: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + onPressed: onEdit, + icon: const Icon(Icons.edit_rounded), + tooltip: AppLocalizations.of(context)!.edit, + ), + const SizedBox(width: 4), + IconButton( + onPressed: onDelete, + icon: const Icon(Icons.delete_rounded), + tooltip: AppLocalizations.of(context)!.delete, + ), + ], + ), + padding: const EdgeInsets.only( + left: 16, + top: 6, + right: 12, + bottom: 6 + ) + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/client/blocking_schedule_modal.dart b/lib/screens/clients/client/blocking_schedule_modal.dart new file mode 100644 index 0000000..f4e18ef --- /dev/null +++ b/lib/screens/clients/client/blocking_schedule_modal.dart @@ -0,0 +1,283 @@ +import 'package:flutter/material.dart'; +import 'package:timezone/timezone.dart' as tz; +import 'package:timezone/data/latest.dart' as tz; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/models/clients.dart'; + +class BlockingScheduleModal extends StatefulWidget { + final void Function(BlockedServicesSchedule) onConfirm; + + const BlockingScheduleModal({ + super.key, + required this.onConfirm, + }); + + @override + State createState() => _BlockingScheduleModalState(); +} + +class _BlockingScheduleModalState extends State { + String? _timezone; + List _weekdays = []; + TimeOfDay? _from; + TimeOfDay? _to; + + bool _compareTimes(TimeOfDay startTime, TimeOfDay endTime) { + bool result = false; + int startTimeInt = (startTime.hour * 60 + startTime.minute) * 60; + int endTimeInt = (endTime.hour * 60 + endTime.minute) * 60; + + if (endTimeInt > startTimeInt) { + result = true; + } else { + result = false; + } + return result; + } + + bool _validate() { + return _timezone != null && + _weekdays.isNotEmpty && + _from != null && + _to != null && + _compareTimes(_from!, _to!); + } + + int _timeOfDayToInt(TimeOfDay timeOfDay) { + return Duration( + days: 0, + hours: timeOfDay.hour, + minutes: timeOfDay.minute, + seconds: 0 + ).inMinutes; + } + + @override + void initState() { + tz.initializeTimeZones(); + _timezone = tz.local.name; + super.initState(); + } + + @override + Widget build(BuildContext context) { + void onSelectWeekday(bool newStatus, String day) { + if (newStatus == true && !_weekdays.contains(day)) { + setState(() => _weekdays.add(day)); + } + else if (newStatus == false) { + setState(() => _weekdays = _weekdays.where((e) => e != day).toList()); + } + } + + void onConfirm() { + widget.onConfirm( + BlockedServicesSchedule( + timeZone: _timezone, + mon: _weekdays.contains("mon") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, + tue: _weekdays.contains("tue") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, + wed: _weekdays.contains("wed") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, + thu: _weekdays.contains("thu") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, + fri: _weekdays.contains("fri") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, + sat: _weekdays.contains("sat") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, + sun: _weekdays.contains("sun") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, + ) + ); + } + + final valid = _validate(); + final validTimes = _from != null && _to != null + ? _compareTimes(_from!, _to!) + : null; + + return Dialog( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.schedule_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.newSchedule, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 24, + ), + ), + const SizedBox(height: 30), + LayoutBuilder( + builder: (context, constraints) => DropdownButtonFormField( + items: tz.timeZoneDatabase.locations.keys.map((item) => DropdownMenuItem( + value: item, + child: SizedBox( + width: constraints.maxWidth-48, + child: Text( + item, + overflow: TextOverflow.ellipsis, + ), + ), + )).toList(), + value: _timezone, + onChanged: (v) => setState(() => _timezone = v), + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + label: Text(AppLocalizations.of(context)!.timezone) + ), + borderRadius: BorderRadius.circular(20), + ), + ), + const SizedBox(height: 16), + SizedBox( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + FilterChip( + label: Text(AppLocalizations.of(context)!.monday), + selected: _weekdays.contains("mon"), + onSelected: (value) => onSelectWeekday(value, "mon") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.tuesday), + selected: _weekdays.contains("tue"), + onSelected: (value) => onSelectWeekday(value, "tue") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.wednesday), + selected: _weekdays.contains("wed"), + onSelected: (value) => onSelectWeekday(value, "wed") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.thursday), + selected: _weekdays.contains("thu"), + onSelected: (value) => onSelectWeekday(value, "thu") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.friday), + selected: _weekdays.contains("fri"), + onSelected: (value) => onSelectWeekday(value, "fri") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.saturday), + selected: _weekdays.contains("sat"), + onSelected: (value) => onSelectWeekday(value, "sat") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.sunday), + selected: _weekdays.contains("sun"), + onSelected: (value) => onSelectWeekday(value, "sun") + ), + ], + ), + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () async { + final selected = await showTimePicker( + context: context, + initialTime: _from ?? const TimeOfDay(hour: 0, minute: 0), + helpText: AppLocalizations.of(context)!.selectStartTime, + confirmText: AppLocalizations.of(context)!.confirm, + ); + setState(() => _from = selected); + }, + child: Text( + AppLocalizations.of(context)!.from( + _from != null ? "${_from!.hour.toString().padLeft(2, '0')}:${_from!.minute.toString().padLeft(2, '0')}" : "--:--" + ) + ) + ), + ElevatedButton( + onPressed: () async { + final selected = await showTimePicker( + context: context, + initialTime: _to ?? const TimeOfDay(hour: 23, minute: 59), + helpText: AppLocalizations.of(context)!.selectEndTime, + confirmText: AppLocalizations.of(context)!.confirm + ); + setState(() => _to = selected); + }, + child: Text( + AppLocalizations.of(context)!.to( + _to != null ? "${_to!.hour.toString().padLeft(2, '0')}:${_to!.minute.toString().padLeft(2, '0')}" : "--:--" + ) + ) + ), + ], + ), + if (validTimes == false) Padding( + padding: const EdgeInsets.only(top: 16), + child: Card( + color: const Color.fromARGB(255, 255, 182, 175), + elevation: 0, + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.error_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + const SizedBox(width: 16), + Expanded( + child: Text( + AppLocalizations.of(context)!.startTimeBeforeEndTime, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ), + ), + ], + ), + ), + ) + ) + ], + ), + ), + ), + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close) + ), + const SizedBox(width: 8), + TextButton( + onPressed: valid ? () => onConfirm() : null, + child: Text(AppLocalizations.of(context)!.confirm) + ), + ], + ) + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/clients/client/client_form.dart b/lib/screens/clients/client/client_form.dart index e127466..2d22dd7 100644 --- a/lib/screens/clients/client/client_form.dart +++ b/lib/screens/clients/client/client_form.dart @@ -8,6 +8,7 @@ import 'package:adguard_home_manager/screens/clients/client/identifiers_section. 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/screens/clients/client/blocking_schedule.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; @@ -52,6 +53,8 @@ class ClientForm extends StatelessWidget { final TextEditingController dnsCacheField; final String? dnsCacheError; final void Function(String?) updateDnsCacheError; + final BlockedServicesSchedule blockedServicesSchedule; + final void Function(BlockedServicesSchedule) setBlockedServicesSchedule; const ClientForm({ super.key, @@ -90,6 +93,8 @@ class ClientForm extends StatelessWidget { required this.dnsCacheField, required this.dnsCacheError, required this.updateDnsCacheError, + required this.blockedServicesSchedule, + required this.setBlockedServicesSchedule, }); @override @@ -282,6 +287,11 @@ class ClientForm extends StatelessWidget { keyboardType: TextInputType.number, ), ), + BlockingSchedule( + blockedServicesSchedule: blockedServicesSchedule, + setBlockedServicesSchedule: setBlockedServicesSchedule, + ), + const SizedBox(height: 16), ], ); } diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index f41de69..225b5eb 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -81,6 +81,8 @@ class _ClientScreenState extends State { bool _enableDnsCache = false; final _dnsCacheField = TextEditingController(); String? _dnsCacheError; + + BlockedServicesSchedule _blockedServicesSchedule = BlockedServicesSchedule(); // VALIDATIONS bool _nameValid = true; @@ -140,6 +142,9 @@ class _ClientScreenState extends State { _dnsCacheField.text = widget.client!.upstreamsCacheSize != null ? widget.client!.upstreamsCacheSize.toString() : ""; + if (widget.client!.blockedServicesSchedule != null) { + _blockedServicesSchedule = widget.client!.blockedServicesSchedule!; + } } super.initState(); } @@ -166,7 +171,8 @@ class _ClientScreenState extends State { upstreamsCacheEnabled: _enableDnsCache, upstreamsCacheSize: _dnsCacheField.text != "" ? int.parse(_dnsCacheField.text) - : null + : null, + blockedServicesSchedule: _blockedServicesSchedule ); widget.onConfirm(client); } @@ -268,7 +274,9 @@ class _ClientScreenState extends State { updateEnableDnsCache: (v) => setState(() => _enableDnsCache = v), dnsCacheField: _dnsCacheField, dnsCacheError: _dnsCacheError, - updateDnsCacheError: (v) => setState(() => _dnsCacheError = v) + updateDnsCacheError: (v) => setState(() => _dnsCacheError = v), + blockedServicesSchedule: _blockedServicesSchedule, + setBlockedServicesSchedule: (v) => setState(() => _blockedServicesSchedule = v), ), ], ), @@ -353,7 +361,9 @@ class _ClientScreenState extends State { updateEnableDnsCache: (v) => setState(() => _enableDnsCache = v), dnsCacheField: _dnsCacheField, dnsCacheError: _dnsCacheError, - updateDnsCacheError: (v) => setState(() => _dnsCacheError = v) + updateDnsCacheError: (v) => setState(() => _dnsCacheError = v), + blockedServicesSchedule: _blockedServicesSchedule, + setBlockedServicesSchedule: (v) => setState(() => _blockedServicesSchedule = v), ), ], ), diff --git a/pubspec.lock b/pubspec.lock index cf61106..1cb21ba 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -659,6 +659,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.1" + timezone: + dependency: "direct main" + description: + name: timezone + sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" + url: "https://pub.dev" + source: hosted + version: "0.9.2" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e4dbaa8..a488bef 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -76,6 +76,7 @@ dependencies: pie_chart: ^5.4.0 segmented_button_slide: ^1.0.4 http: ^1.1.2 + timezone: ^0.9.2 dev_dependencies: flutter_test: From 283d4e5c41918b74f73beb9aa0465b65da778499 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 Jan 2024 21:18:04 +0100 Subject: [PATCH 494/676] Improved edit schedule --- lib/models/clients.dart | 4 ++ .../clients/client/blocking_schedule.dart | 57 ++++++++++++++++--- .../client/blocking_schedule_modal.dart | 40 ++++++++----- 3 files changed, 80 insertions(+), 21 deletions(-) diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 56a967e..2ebcccd 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -187,9 +187,13 @@ class BlockedServicesSchedule { Map toJson() => { "time_zone": timeZone, + "mon": mon?.toJson(), "tue": tue?.toJson(), "wed": wed?.toJson(), "thu": thu?.toJson(), + "fri": fri?.toJson(), + "sat": sat?.toJson(), + "sun": sun?.toJson(), }; } diff --git a/lib/screens/clients/client/blocking_schedule.dart b/lib/screens/clients/client/blocking_schedule.dart index 0ae7abb..0bcb21c 100644 --- a/lib/screens/clients/client/blocking_schedule.dart +++ b/lib/screens/clients/client/blocking_schedule.dart @@ -7,6 +7,20 @@ import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/models/clients.dart'; +class EditBlockingSchedule { + final String timezone; + final List weekday; + final int start; + final int end; + + const EditBlockingSchedule({ + required this.timezone, + required this.weekday, + required this.start, + required this.end, + }); +} + class BlockingSchedule extends StatelessWidget { final BlockedServicesSchedule blockedServicesSchedule; final void Function(BlockedServicesSchedule) setBlockedServicesSchedule; @@ -19,11 +33,38 @@ class BlockingSchedule extends StatelessWidget { @override Widget build(BuildContext context) { + void updateSchedule(EditBlockingSchedule v) { + final scheduleJson = blockedServicesSchedule.toJson(); + for (var weekday in v.weekday) { + scheduleJson[weekday] = { + "start": v.start, + "end": v.end + }; + } + scheduleJson["time_zone"] = v.timezone; + setBlockedServicesSchedule(BlockedServicesSchedule.fromJson(scheduleJson)); + } + void openAddScheduleModal() { showDialog( context: context, builder: (context) => BlockingScheduleModal( - onConfirm: (v) => {}, + onConfirm: updateSchedule, + ), + ); + } + + void openEditScheduleModal(String weekday) { + showDialog( + context: context, + builder: (context) => BlockingScheduleModal( + schedule: EditBlockingSchedule( + timezone: blockedServicesSchedule.timeZone!, + weekday: [weekday], + start: blockedServicesSchedule.toJson()[weekday]['start'], + end: blockedServicesSchedule.toJson()[weekday]['end'], + ), + onConfirm: updateSchedule, ), ); } @@ -54,43 +95,43 @@ class BlockingSchedule extends StatelessWidget { if (blockedServicesSchedule.mon != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.monday, schedule: "${formatTime(blockedServicesSchedule.mon!.start!)} - ${formatTime(blockedServicesSchedule.mon!.end!)}", - onEdit: () => {}, + onEdit: () => openEditScheduleModal("mon"), onDelete: () => {} ), if (blockedServicesSchedule.tue != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.tuesday, schedule: "${formatTime(blockedServicesSchedule.tue!.start!)} - ${formatTime(blockedServicesSchedule.tue!.end!)}", - onEdit: () => {}, + onEdit: () => openEditScheduleModal("tue"), onDelete: () => {} ), if (blockedServicesSchedule.wed != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.wednesday, schedule: "${formatTime(blockedServicesSchedule.wed!.start!)} - ${formatTime(blockedServicesSchedule.wed!.end!)}", - onEdit: () => {}, + onEdit: () => openEditScheduleModal("wed"), onDelete: () => {} ), if (blockedServicesSchedule.thu != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.thursday, schedule: "${formatTime(blockedServicesSchedule.thu!.start!)} - ${formatTime(blockedServicesSchedule.thu!.end!)}", - onEdit: () => {}, + onEdit: () => openEditScheduleModal("thu"), onDelete: () => {} ), if (blockedServicesSchedule.fri != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.friday, schedule: "${formatTime(blockedServicesSchedule.fri!.start!)} - ${formatTime(blockedServicesSchedule.fri!.end!)}", - onEdit: () => {}, + onEdit: () => openEditScheduleModal("fri"), onDelete: () => {} ), if (blockedServicesSchedule.sat != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.saturday, schedule: "${formatTime(blockedServicesSchedule.sat!.start!)} - ${formatTime(blockedServicesSchedule.sat!.end!)}", - onEdit: () => {}, + onEdit: () => openEditScheduleModal("sat"), onDelete: () => {} ), if (blockedServicesSchedule.sun != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.sunday, schedule: "${formatTime(blockedServicesSchedule.sun!.start!)} - ${formatTime(blockedServicesSchedule.sun!.end!)}", - onEdit: () => {}, + onEdit: () => openEditScheduleModal("sun"), onDelete: () => {} ), ], diff --git a/lib/screens/clients/client/blocking_schedule_modal.dart b/lib/screens/clients/client/blocking_schedule_modal.dart index f4e18ef..c0b2a43 100644 --- a/lib/screens/clients/client/blocking_schedule_modal.dart +++ b/lib/screens/clients/client/blocking_schedule_modal.dart @@ -3,13 +3,15 @@ import 'package:timezone/timezone.dart' as tz; import 'package:timezone/data/latest.dart' as tz; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/screens/clients/client/blocking_schedule.dart'; class BlockingScheduleModal extends StatefulWidget { - final void Function(BlockedServicesSchedule) onConfirm; + final EditBlockingSchedule? schedule; + final void Function(EditBlockingSchedule) onConfirm; const BlockingScheduleModal({ super.key, + this.schedule, required this.onConfirm, }); @@ -50,13 +52,26 @@ class _BlockingScheduleModalState extends State { hours: timeOfDay.hour, minutes: timeOfDay.minute, seconds: 0 - ).inMinutes; + ).inMilliseconds; + } + + TimeOfDay _intToTimeOfDay(int value) { + final duration = Duration(milliseconds: value); + final minutes = duration.inMinutes - duration.inHours*60; + return TimeOfDay(hour: duration.inHours, minute: minutes); } @override void initState() { tz.initializeTimeZones(); _timezone = tz.local.name; + if (widget.schedule != null) { + _timezone = widget.schedule!.timezone; + _weekdays = widget.schedule!.weekday; + _from = _intToTimeOfDay(widget.schedule!.start); + _to = _intToTimeOfDay(widget.schedule!.end); + } + super.initState(); } @@ -73,17 +88,14 @@ class _BlockingScheduleModalState extends State { void onConfirm() { widget.onConfirm( - BlockedServicesSchedule( - timeZone: _timezone, - mon: _weekdays.contains("mon") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, - tue: _weekdays.contains("tue") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, - wed: _weekdays.contains("wed") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, - thu: _weekdays.contains("thu") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, - fri: _weekdays.contains("fri") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, - sat: _weekdays.contains("sat") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, - sun: _weekdays.contains("sun") ? BlockedServicesScheduleDay(start: _timeOfDayToInt(_from!), end: _timeOfDayToInt(_to!)) : null, + EditBlockingSchedule( + timezone: _timezone!, + weekday: _weekdays, + start: _timeOfDayToInt(_from!), + end: _timeOfDayToInt(_to!) ) ); + Navigator.pop(context); } final valid = _validate(); @@ -109,7 +121,9 @@ class _BlockingScheduleModalState extends State { ), const SizedBox(height: 16), Text( - AppLocalizations.of(context)!.newSchedule, + widget.schedule != null + ? AppLocalizations.of(context)!.editSchedule + : AppLocalizations.of(context)!.newSchedule, textAlign: TextAlign.center, style: const TextStyle( fontSize: 24, From 770366eae64e2fa65381c6b103a9f6c0b64f14ac Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 Jan 2024 21:23:37 +0100 Subject: [PATCH 495/676] Added delete schedule and no schedule message --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- .../clients/client/blocking_schedule.dart | 39 +++++++++++++++---- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 6e281d4..5c8adbf 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -745,5 +745,6 @@ "to": "To: {to}", "selectStartTime": "Select start time", "selectEndTime": "Select end time", - "startTimeBeforeEndTime": "Start time must be before end time." + "startTimeBeforeEndTime": "Start time must be before end time.", + "noBlockingScheduleThisDevice": "There's no blocking schedule for this device." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 55f8237..6185a8f 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -745,5 +745,6 @@ "to": "Hasta: {to}", "selectStartTime": "Seleccionar hora de inicio", "selectEndTime": "Seleccionar hora de fin", - "startTimeBeforeEndTime": "La hora de inicio debe ser anterior a la hora de fin." + "startTimeBeforeEndTime": "La hora de inicio debe ser anterior a la hora de fin.", + "noBlockingScheduleThisDevice": "No hay programación de bloqueo para este dispositivo." } \ No newline at end of file diff --git a/lib/screens/clients/client/blocking_schedule.dart b/lib/screens/clients/client/blocking_schedule.dart index 0bcb21c..f17bd4d 100644 --- a/lib/screens/clients/client/blocking_schedule.dart +++ b/lib/screens/clients/client/blocking_schedule.dart @@ -69,6 +69,12 @@ class BlockingSchedule extends StatelessWidget { ); } + void onDeleteSchedule(String weekday) { + final scheduleJson = blockedServicesSchedule.toJson(); + scheduleJson[weekday] = null; + setBlockedServicesSchedule(BlockedServicesSchedule.fromJson(scheduleJson)); + } + String formatTime(int time) { final formatted = Duration(milliseconds: time); final hours = formatted.inHours; @@ -92,47 +98,66 @@ class BlockingSchedule extends StatelessWidget { ], ), const SizedBox(height: 2), + if ( + blockedServicesSchedule.mon == null && + blockedServicesSchedule.tue == null && + blockedServicesSchedule.wed == null && + blockedServicesSchedule.thu == null && + blockedServicesSchedule.fri == null && + blockedServicesSchedule.sat == null && + blockedServicesSchedule.sun == null + ) Padding( + padding: const EdgeInsets.all(16), + child: Text( + AppLocalizations.of(context)!.noBlockingScheduleThisDevice, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), if (blockedServicesSchedule.mon != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.monday, schedule: "${formatTime(blockedServicesSchedule.mon!.start!)} - ${formatTime(blockedServicesSchedule.mon!.end!)}", onEdit: () => openEditScheduleModal("mon"), - onDelete: () => {} + onDelete: () => onDeleteSchedule("mon") ), if (blockedServicesSchedule.tue != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.tuesday, schedule: "${formatTime(blockedServicesSchedule.tue!.start!)} - ${formatTime(blockedServicesSchedule.tue!.end!)}", onEdit: () => openEditScheduleModal("tue"), - onDelete: () => {} + onDelete: () => onDeleteSchedule("tue") ), if (blockedServicesSchedule.wed != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.wednesday, schedule: "${formatTime(blockedServicesSchedule.wed!.start!)} - ${formatTime(blockedServicesSchedule.wed!.end!)}", onEdit: () => openEditScheduleModal("wed"), - onDelete: () => {} + onDelete: () => onDeleteSchedule("wed") ), if (blockedServicesSchedule.thu != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.thursday, schedule: "${formatTime(blockedServicesSchedule.thu!.start!)} - ${formatTime(blockedServicesSchedule.thu!.end!)}", onEdit: () => openEditScheduleModal("thu"), - onDelete: () => {} + onDelete: () => onDeleteSchedule("thu") ), if (blockedServicesSchedule.fri != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.friday, schedule: "${formatTime(blockedServicesSchedule.fri!.start!)} - ${formatTime(blockedServicesSchedule.fri!.end!)}", onEdit: () => openEditScheduleModal("fri"), - onDelete: () => {} + onDelete: () => onDeleteSchedule("fri") ), if (blockedServicesSchedule.sat != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.saturday, schedule: "${formatTime(blockedServicesSchedule.sat!.start!)} - ${formatTime(blockedServicesSchedule.sat!.end!)}", onEdit: () => openEditScheduleModal("sat"), - onDelete: () => {} + onDelete: () => onDeleteSchedule("sat") ), if (blockedServicesSchedule.sun != null) _ScheduleTile( weekday: AppLocalizations.of(context)!.sunday, schedule: "${formatTime(blockedServicesSchedule.sun!.start!)} - ${formatTime(blockedServicesSchedule.sun!.end!)}", onEdit: () => openEditScheduleModal("sun"), - onDelete: () => {} + onDelete: () => onDeleteSchedule("sun") ), ], ); From 91e3ea44f6f2c9249b5901992a63fd4eed443513 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 Jan 2024 21:33:41 +0100 Subject: [PATCH 496/676] Fix timezone selection --- lib/l10n/app_en.arb | 3 ++- lib/l10n/app_es.arb | 3 ++- lib/screens/clients/client/blocking_schedule_modal.dart | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 5c8adbf..5bba23a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -746,5 +746,6 @@ "selectStartTime": "Select start time", "selectEndTime": "Select end time", "startTimeBeforeEndTime": "Start time must be before end time.", - "noBlockingScheduleThisDevice": "There's no blocking schedule for this device." + "noBlockingScheduleThisDevice": "There's no blocking schedule for this device.", + "selectTimezone": "Select a timezone" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 6185a8f..c803224 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -746,5 +746,6 @@ "selectStartTime": "Seleccionar hora de inicio", "selectEndTime": "Seleccionar hora de fin", "startTimeBeforeEndTime": "La hora de inicio debe ser anterior a la hora de fin.", - "noBlockingScheduleThisDevice": "No hay programación de bloqueo para este dispositivo." + "noBlockingScheduleThisDevice": "No hay programación de bloqueo para este dispositivo.", + "selectTimezone": "Selecciona una zona horaria" } \ No newline at end of file diff --git a/lib/screens/clients/client/blocking_schedule_modal.dart b/lib/screens/clients/client/blocking_schedule_modal.dart index c0b2a43..239f762 100644 --- a/lib/screens/clients/client/blocking_schedule_modal.dart +++ b/lib/screens/clients/client/blocking_schedule_modal.dart @@ -64,7 +64,6 @@ class _BlockingScheduleModalState extends State { @override void initState() { tz.initializeTimeZones(); - _timezone = tz.local.name; if (widget.schedule != null) { _timezone = widget.schedule!.timezone; _weekdays = widget.schedule!.weekday; From 74a4f659248d5575bf17cca29f15f264f1181a6b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 Jan 2024 21:38:21 +0100 Subject: [PATCH 497/676] Added scrollbar --- .../client/blocking_schedule_modal.dart | 363 +++++++++--------- 1 file changed, 191 insertions(+), 172 deletions(-) diff --git a/lib/screens/clients/client/blocking_schedule_modal.dart b/lib/screens/clients/client/blocking_schedule_modal.dart index 239f762..020e933 100644 --- a/lib/screens/clients/client/blocking_schedule_modal.dart +++ b/lib/screens/clients/client/blocking_schedule_modal.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:timezone/timezone.dart' as tz; import 'package:timezone/data/latest.dart' as tz; @@ -20,6 +22,8 @@ class BlockingScheduleModal extends StatefulWidget { } class _BlockingScheduleModalState extends State { + final _weekdaysScrollController = ScrollController(); + String? _timezone; List _weekdays = []; TimeOfDay? _from; @@ -103,192 +107,207 @@ class _BlockingScheduleModalState extends State { : null; return Dialog( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.schedule_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(height: 16), - Text( - widget.schedule != null - ? AppLocalizations.of(context)!.editSchedule - : AppLocalizations.of(context)!.newSchedule, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 24, + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 500), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.schedule_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor ), - ), - const SizedBox(height: 30), - LayoutBuilder( - builder: (context, constraints) => DropdownButtonFormField( - items: tz.timeZoneDatabase.locations.keys.map((item) => DropdownMenuItem( - value: item, - child: SizedBox( - width: constraints.maxWidth-48, - child: Text( - item, - overflow: TextOverflow.ellipsis, + const SizedBox(height: 16), + Text( + widget.schedule != null + ? AppLocalizations.of(context)!.editSchedule + : AppLocalizations.of(context)!.newSchedule, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 24, + ), + ), + const SizedBox(height: 30), + LayoutBuilder( + builder: (context, constraints) => DropdownButtonFormField( + items: tz.timeZoneDatabase.locations.keys.map((item) => DropdownMenuItem( + value: item, + child: SizedBox( + width: constraints.maxWidth-48, + child: Text( + item, + overflow: TextOverflow.ellipsis, + ), + ), + )).toList(), + value: _timezone, + onChanged: (v) => setState(() => _timezone = v), + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + label: Text(AppLocalizations.of(context)!.timezone) + ), + borderRadius: BorderRadius.circular(20), + ), + ), + const SizedBox(height: 16), + SizedBox( + height: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 66 : 50, + child: Scrollbar( + controller: _weekdaysScrollController, + thumbVisibility: Platform.isMacOS || Platform.isLinux || Platform.isWindows, + interactive: Platform.isMacOS || Platform.isLinux || Platform.isWindows, + thickness: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 8 : 0, + child: Padding( + padding: EdgeInsets.only( + bottom: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 16 : 0 + ), + child: ListView( + controller: _weekdaysScrollController, + scrollDirection: Axis.horizontal, + children: [ + FilterChip( + label: Text(AppLocalizations.of(context)!.monday), + selected: _weekdays.contains("mon"), + onSelected: (value) => onSelectWeekday(value, "mon") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.tuesday), + selected: _weekdays.contains("tue"), + onSelected: (value) => onSelectWeekday(value, "tue") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.wednesday), + selected: _weekdays.contains("wed"), + onSelected: (value) => onSelectWeekday(value, "wed") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.thursday), + selected: _weekdays.contains("thu"), + onSelected: (value) => onSelectWeekday(value, "thu") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.friday), + selected: _weekdays.contains("fri"), + onSelected: (value) => onSelectWeekday(value, "fri") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.saturday), + selected: _weekdays.contains("sat"), + onSelected: (value) => onSelectWeekday(value, "sat") + ), + const SizedBox(width: 8), + FilterChip( + label: Text(AppLocalizations.of(context)!.sunday), + selected: _weekdays.contains("sun"), + onSelected: (value) => onSelectWeekday(value, "sun") + ), + ], ), ), - )).toList(), - value: _timezone, - onChanged: (v) => setState(() => _timezone = v), - decoration: InputDecoration( - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) + ), + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () async { + final selected = await showTimePicker( + context: context, + initialTime: _from ?? const TimeOfDay(hour: 0, minute: 0), + helpText: AppLocalizations.of(context)!.selectStartTime, + confirmText: AppLocalizations.of(context)!.confirm, + ); + setState(() => _from = selected); + }, + child: Text( + AppLocalizations.of(context)!.from( + _from != null ? "${_from!.hour.toString().padLeft(2, '0')}:${_from!.minute.toString().padLeft(2, '0')}" : "--:--" + ) ) ), - label: Text(AppLocalizations.of(context)!.timezone) - ), - borderRadius: BorderRadius.circular(20), - ), - ), - const SizedBox(height: 16), - SizedBox( - height: 50, - child: ListView( - scrollDirection: Axis.horizontal, - children: [ - FilterChip( - label: Text(AppLocalizations.of(context)!.monday), - selected: _weekdays.contains("mon"), - onSelected: (value) => onSelectWeekday(value, "mon") - ), - const SizedBox(width: 8), - FilterChip( - label: Text(AppLocalizations.of(context)!.tuesday), - selected: _weekdays.contains("tue"), - onSelected: (value) => onSelectWeekday(value, "tue") - ), - const SizedBox(width: 8), - FilterChip( - label: Text(AppLocalizations.of(context)!.wednesday), - selected: _weekdays.contains("wed"), - onSelected: (value) => onSelectWeekday(value, "wed") - ), - const SizedBox(width: 8), - FilterChip( - label: Text(AppLocalizations.of(context)!.thursday), - selected: _weekdays.contains("thu"), - onSelected: (value) => onSelectWeekday(value, "thu") - ), - const SizedBox(width: 8), - FilterChip( - label: Text(AppLocalizations.of(context)!.friday), - selected: _weekdays.contains("fri"), - onSelected: (value) => onSelectWeekday(value, "fri") - ), - const SizedBox(width: 8), - FilterChip( - label: Text(AppLocalizations.of(context)!.saturday), - selected: _weekdays.contains("sat"), - onSelected: (value) => onSelectWeekday(value, "sat") - ), - const SizedBox(width: 8), - FilterChip( - label: Text(AppLocalizations.of(context)!.sunday), - selected: _weekdays.contains("sun"), - onSelected: (value) => onSelectWeekday(value, "sun") + ElevatedButton( + onPressed: () async { + final selected = await showTimePicker( + context: context, + initialTime: _to ?? const TimeOfDay(hour: 23, minute: 59), + helpText: AppLocalizations.of(context)!.selectEndTime, + confirmText: AppLocalizations.of(context)!.confirm + ); + setState(() => _to = selected); + }, + child: Text( + AppLocalizations.of(context)!.to( + _to != null ? "${_to!.hour.toString().padLeft(2, '0')}:${_to!.minute.toString().padLeft(2, '0')}" : "--:--" + ) + ) ), ], ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ElevatedButton( - onPressed: () async { - final selected = await showTimePicker( - context: context, - initialTime: _from ?? const TimeOfDay(hour: 0, minute: 0), - helpText: AppLocalizations.of(context)!.selectStartTime, - confirmText: AppLocalizations.of(context)!.confirm, - ); - setState(() => _from = selected); - }, - child: Text( - AppLocalizations.of(context)!.from( - _from != null ? "${_from!.hour.toString().padLeft(2, '0')}:${_from!.minute.toString().padLeft(2, '0')}" : "--:--" - ) - ) - ), - ElevatedButton( - onPressed: () async { - final selected = await showTimePicker( - context: context, - initialTime: _to ?? const TimeOfDay(hour: 23, minute: 59), - helpText: AppLocalizations.of(context)!.selectEndTime, - confirmText: AppLocalizations.of(context)!.confirm - ); - setState(() => _to = selected); - }, - child: Text( - AppLocalizations.of(context)!.to( - _to != null ? "${_to!.hour.toString().padLeft(2, '0')}:${_to!.minute.toString().padLeft(2, '0')}" : "--:--" - ) - ) - ), - ], - ), - if (validTimes == false) Padding( - padding: const EdgeInsets.only(top: 16), - child: Card( - color: const Color.fromARGB(255, 255, 182, 175), - elevation: 0, - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Icon( - Icons.error_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - const SizedBox(width: 16), - Expanded( - child: Text( - AppLocalizations.of(context)!.startTimeBeforeEndTime, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface + if (validTimes == false) Padding( + padding: const EdgeInsets.only(top: 16), + child: Card( + color: const Color.fromARGB(255, 255, 182, 175), + elevation: 0, + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.error_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + const SizedBox(width: 16), + Expanded( + child: Text( + AppLocalizations.of(context)!.startTimeBeforeEndTime, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), ), ), - ), - ], + ], + ), ), - ), + ) ) - ) - ], + ], + ), ), ), - ), - const SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close) - ), - const SizedBox(width: 8), - TextButton( - onPressed: valid ? () => onConfirm() : null, - child: Text(AppLocalizations.of(context)!.confirm) - ), - ], - ) - ], + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close) + ), + const SizedBox(width: 8), + TextButton( + onPressed: valid ? () => onConfirm() : null, + child: Text(AppLocalizations.of(context)!.confirm) + ), + ], + ) + ], + ), ), ), ); From ad3046a84b06811cea4c0632f1d916f380870134 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 26 Jan 2024 21:39:26 +0100 Subject: [PATCH 498/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index a488bef..94b1ce4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.14.1+120 +version: 2.15.0-beta.1+121 environment: sdk: '>=2.18.1 <3.0.0' From 5d458299378fb77b9c8cf172ad2a54e72fc02bf5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 Jan 2024 22:04:54 +0100 Subject: [PATCH 499/676] Changed from to buttons design --- lib/l10n/app_en.arb | 4 +-- lib/l10n/app_es.arb | 4 +-- .../client/blocking_schedule_modal.dart | 26 +++++++++++++------ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 5bba23a..4b92566 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -741,8 +741,8 @@ "friday": "Friday", "saturday": "Saturday", "sunday": "Sunday", - "from": "From: {from}", - "to": "To: {to}", + "from": "From", + "to": "To", "selectStartTime": "Select start time", "selectEndTime": "Select end time", "startTimeBeforeEndTime": "Start time must be before end time.", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index c803224..ff5bb7d 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -741,8 +741,8 @@ "friday": "Viernes", "saturday": "Sábado", "sunday": "Domingo", - "from": "Desde: {from}", - "to": "Hasta: {to}", + "from": "Desde", + "to": "Hasta", "selectStartTime": "Seleccionar hora de inicio", "selectEndTime": "Seleccionar hora de fin", "startTimeBeforeEndTime": "La hora de inicio debe ser anterior a la hora de fin.", diff --git a/lib/screens/clients/client/blocking_schedule_modal.dart b/lib/screens/clients/client/blocking_schedule_modal.dart index 020e933..1521ead 100644 --- a/lib/screens/clients/client/blocking_schedule_modal.dart +++ b/lib/screens/clients/client/blocking_schedule_modal.dart @@ -236,10 +236,15 @@ class _BlockingScheduleModalState extends State { ); setState(() => _from = selected); }, - child: Text( - AppLocalizations.of(context)!.from( - _from != null ? "${_from!.hour.toString().padLeft(2, '0')}:${_from!.minute.toString().padLeft(2, '0')}" : "--:--" - ) + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Column( + children: [ + Text(AppLocalizations.of(context)!.from), + const SizedBox(height: 2), + Text(_from != null ? "${_from!.hour.toString().padLeft(2, '0')}:${_from!.minute.toString().padLeft(2, '0')}" : "--:--") + ], + ), ) ), ElevatedButton( @@ -252,10 +257,15 @@ class _BlockingScheduleModalState extends State { ); setState(() => _to = selected); }, - child: Text( - AppLocalizations.of(context)!.to( - _to != null ? "${_to!.hour.toString().padLeft(2, '0')}:${_to!.minute.toString().padLeft(2, '0')}" : "--:--" - ) + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Column( + children: [ + Text(AppLocalizations.of(context)!.to), + const SizedBox(height: 2), + Text(_to != null ? "${_to!.hour.toString().padLeft(2, '0')}:${_to!.minute.toString().padLeft(2, '0')}" : "--:--") + ], + ), ) ), ], From 3e206027de1306585399b2c300a88dd6fb0ac094 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 Jan 2024 22:25:46 +0100 Subject: [PATCH 500/676] Changed general modals --- .../filters/details/list_details_screen.dart | 404 ++++++++++-------- lib/screens/filters/filters.dart | 44 +- lib/screens/home/home.dart | 2 + .../home/top_items/top_items_section.dart | 60 +-- 4 files changed, 277 insertions(+), 233 deletions(-) diff --git a/lib/screens/filters/details/list_details_screen.dart b/lib/screens/filters/details/list_details_screen.dart index bbc7c41..07d3aa0 100644 --- a/lib/screens/filters/details/list_details_screen.dart +++ b/lib/screens/filters/details/list_details_screen.dart @@ -111,177 +111,6 @@ class _ListDetailsScreenState extends State { } } - List content() { - return [ - CustomListTile( - icon: Icons.shield_rounded, - title: AppLocalizations.of(context)!.currentStatus, - subtitleWidget: Text( - list!.enabled == true - ? AppLocalizations.of(context)!.enabled - : AppLocalizations.of(context)!.disabled, - style: TextStyle( - color: list.enabled == true - ? appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Colors.grey - : Colors.red, - fontWeight: FontWeight.w500 - ), - ), - padding: widget.dialog == true - ? const EdgeInsets.symmetric( - horizontal: 24, - vertical: 8 - ) - : null, - ), - CustomListTile( - icon: Icons.badge_rounded, - title: AppLocalizations.of(context)!.name, - subtitle: list.name, - padding: widget.dialog == true - ? const EdgeInsets.symmetric( - horizontal: 24, - vertical: 8 - ) - : null, - ), - CustomListTile( - icon: Icons.link_rounded, - title: "URL", - subtitle: list.url, - padding: widget.dialog == true - ? const EdgeInsets.symmetric( - horizontal: 24, - vertical: 8 - ) - : null, - trailing: IconButton( - onPressed: () => openUrl(list!.url), - icon: const Icon(Icons.open_in_browser_rounded), - tooltip: AppLocalizations.of(context)!.openListUrl, - ), - ), - CustomListTile( - icon: Icons.list_rounded, - title: AppLocalizations.of(context)!.rules, - subtitle: list.rulesCount.toString(), - padding: widget.dialog == true - ? const EdgeInsets.symmetric( - horizontal: 24, - vertical: 8 - ) - : null, - ), - CustomListTile( - icon: Icons.shield_rounded, - title: AppLocalizations.of(context)!.listType, - subtitle: widget.type == 'whitelist' - ? AppLocalizations.of(context)!.whitelist - : AppLocalizations.of(context)!.blacklist, - padding: widget.dialog == true - ? const EdgeInsets.symmetric( - horizontal: 24, - vertical: 8 - ) - : null, - ), - if (list.lastUpdated != null) CustomListTile( - icon: Icons.schedule_rounded, - title: AppLocalizations.of(context)!.latestUpdate, - subtitle: convertTimestampLocalTimezone(list.lastUpdated!, 'dd-MM-yyyy HH:mm'), - padding: widget.dialog == true - ? const EdgeInsets.symmetric( - horizontal: 24, - vertical: 8 - ) - : null, - ), - if (widget.dialog == true) Container(height: 16) - ]; - } - - List actions() { - return [ - IconButton( - onPressed: () => { - if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { - showDialog( - context: context, - builder: (ctx) => AddListModal( - list: list, - type: widget.type, - onEdit: ({required Filter list, required String type}) async => updateList( - action: FilteringListActions.edit, - filterList: list - ), - dialog: true, - ), - ) - } - else { - showModalBottomSheet( - context: context, - useRootNavigator: true, - builder: (ctx) => AddListModal( - list: list, - type: widget.type, - onEdit: ({required Filter list, required String type}) async => updateList( - action: FilteringListActions.edit, - filterList: list - ), - dialog: false, - ), - isScrollControlled: true, - backgroundColor: Colors.transparent - ) - } - }, - icon: const Icon(Icons.edit), - tooltip: AppLocalizations.of(context)!.edit, - ), - IconButton( - onPressed: () { - showDialog( - context: context, - builder: (c) => DeleteListModal( - onConfirm: () async { - ProcessModal processModal = ProcessModal(); - processModal.open(AppLocalizations.of(context)!.deletingList); - final result = await filteringProvider.deleteList( - listUrl: list!.url, - type: widget.type, - ); - processModal.close(); - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDeleted, - color: Colors.green - ); - Navigator.pop(context); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listNotDeleted, - color: Colors.red - ); - } - } - ) - ); - }, - icon: const Icon(Icons.delete), - tooltip: AppLocalizations.of(context)!.delete, - ), - const SizedBox(width: 10), - ]; - } - if (widget.dialog == true) { return Dialog( child: ConstrainedBox( @@ -330,7 +159,11 @@ class _ListDetailsScreenState extends State { ? AppLocalizations.of(context)!.disableList : AppLocalizations.of(context)!.enableList, ), - ...actions() + _Actions( + list: list, + type: widget.type, + updateList: (action, filterList) => updateList(action: action, filterList: filterList), + ) ], ) ], @@ -340,7 +173,12 @@ class _ListDetailsScreenState extends State { child: list != null ? SingleChildScrollView( child: Wrap( - children: content(), + children: [ + _Content( + isDialog: widget.dialog, + list: list, + ) + ], ), ) : Center( @@ -361,17 +199,27 @@ class _ListDetailsScreenState extends State { return Dialog.fullscreen( child: Scaffold( appBar: AppBar( - leading: CloseButton( - onPressed: () => Navigator.pop(context), - ), title: Text(AppLocalizations.of(context)!.listDetails), - actions: list != null ? actions() : null, + actions: list != null + ? [ + _Actions( + list: list, + type: widget.type, + updateList: (action, filterList) => updateList(action: action, filterList: filterList), + ) + ] + : null, ), body: SafeArea( child: Stack( children: [ if (list != null) ListView( - children: content(), + children: [ + _Content( + isDialog: widget.dialog, + list: list, + ) + ], ), if (list == null) Center( child: Text( @@ -410,4 +258,204 @@ class _ListDetailsScreenState extends State { ); } } +} + +class _Content extends StatelessWidget { + final Filter list; + final bool isDialog; + + const _Content({ + required this.list, + required this.isDialog + }); + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + + return Column( + children: [ + CustomListTile( + icon: Icons.shield_rounded, + title: AppLocalizations.of(context)!.currentStatus, + subtitleWidget: Text( + list.enabled == true + ? AppLocalizations.of(context)!.enabled + : AppLocalizations.of(context)!.disabled, + style: TextStyle( + color: list.enabled == true + ? appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Colors.grey + : Colors.red, + fontWeight: FontWeight.w500 + ), + ), + padding: isDialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + CustomListTile( + icon: Icons.badge_rounded, + title: AppLocalizations.of(context)!.name, + subtitle: list.name, + padding: isDialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + CustomListTile( + icon: Icons.link_rounded, + title: "URL", + subtitle: list.url, + padding: isDialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + trailing: IconButton( + onPressed: () => openUrl(list!.url), + icon: const Icon(Icons.open_in_browser_rounded), + tooltip: AppLocalizations.of(context)!.openListUrl, + ), + ), + CustomListTile( + icon: Icons.list_rounded, + title: AppLocalizations.of(context)!.rules, + subtitle: list.rulesCount.toString(), + padding: isDialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + CustomListTile( + icon: Icons.shield_rounded, + title: AppLocalizations.of(context)!.listType, + subtitle: isDialog == 'whitelist' + ? AppLocalizations.of(context)!.whitelist + : AppLocalizations.of(context)!.blacklist, + padding: isDialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + if (list.lastUpdated != null) CustomListTile( + icon: Icons.schedule_rounded, + title: AppLocalizations.of(context)!.latestUpdate, + subtitle: convertTimestampLocalTimezone(list.lastUpdated!, 'dd-MM-yyyy HH:mm'), + padding: isDialog == true + ? const EdgeInsets.symmetric( + horizontal: 24, + vertical: 8 + ) + : null, + ), + if (isDialog == true) Container(height: 16) + ], + ); + } +} + +class _Actions extends StatelessWidget { + final Filter? list; + final String type; + final void Function(FilteringListActions, Filter) updateList; + + const _Actions({ + required this.list, + required this.type, + required this.updateList, + }); + + @override + Widget build(BuildContext context) { + final filteringProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; + + return Row( + children: [ + IconButton( + onPressed: () => { + if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (ctx) => AddListModal( + list: list, + type: type, + onEdit: ({required Filter list, required String type}) async => updateList(FilteringListActions.edit, list), + dialog: true, + ), + ) + } + else { + showModalBottomSheet( + context: context, + useRootNavigator: true, + builder: (ctx) => AddListModal( + list: list, + type: type, + onEdit: ({required Filter list, required String type}) async => updateList(FilteringListActions.edit, list), + dialog: false, + ), + isScrollControlled: true, + backgroundColor: Colors.transparent + ) + } + }, + icon: const Icon(Icons.edit), + tooltip: AppLocalizations.of(context)!.edit, + ), + IconButton( + onPressed: () { + showDialog( + context: context, + builder: (c) => DeleteListModal( + onConfirm: () async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.deletingList); + final result = await filteringProvider.deleteList( + listUrl: list!.url, + type: type, + ); + processModal.close(); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDeleted, + color: Colors.green + ); + Navigator.pop(context); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listNotDeleted, + color: Colors.red + ); + } + } + ) + ); + }, + icon: const Icon(Icons.delete), + tooltip: AppLocalizations.of(context)!.delete, + ), + const SizedBox(width: 10), + ], + ); + } } \ No newline at end of file diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index c0a7e20..2ab49a3 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -188,31 +188,25 @@ class _FiltersState extends State { } void openListDetails(Filter filter, String type) { - showGeneralDialog( - context: context, - barrierColor: !(width > 900 || !(Platform.isAndroid | Platform.isIOS)) - ?Colors.transparent - : Colors.black54, - transitionBuilder: (context, anim1, anim2, child) { - return SlideTransition( - position: Tween( - begin: const Offset(0, 1), - end: const Offset(0, 0) - ).animate( - CurvedAnimation( - parent: anim1, - curve: Curves.easeInOutCubicEmphasized - ) - ), - child: child, - ); - }, - pageBuilder: (context, animation, secondaryAnimation) => ListDetailsScreen( - listId: filter.id, - type: type, - dialog: width > 900 || !(Platform.isAndroid | Platform.isIOS), - ), - ); + if (width > 900) { + showDialog( + context: context, + builder: (context) => ListDetailsScreen( + listId: filter.id, + type: type, + dialog: width > 900 || !(Platform.isAndroid | Platform.isIOS), + ), + ); + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => ListDetailsScreen( + listId: filter.id, + type: type, + dialog: width > 900 || !(Platform.isAndroid | Platform.isIOS), + ), + )); + } } List actions() { diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index f34a186..b74e959 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -227,6 +227,8 @@ class _HomeState extends State { ), TopItemsLists(order: appConfigProvider.homeTopItemsOrder), + + const SizedBox(height: 16), ], ), if (statusProvider.loadStatus == LoadStatus.error) SliverFillRemaining( diff --git a/lib/screens/home/top_items/top_items_section.dart b/lib/screens/home/top_items/top_items_section.dart index 475ffb9..da0ccd8 100644 --- a/lib/screens/home/top_items/top_items_section.dart +++ b/lib/screens/home/top_items/top_items_section.dart @@ -228,37 +228,37 @@ class TopItemsSection extends StatelessWidget { children: [ TextButton( onPressed: () => { - showGeneralDialog( - context: context, - barrierColor: !(width > 700 || !(Platform.isAndroid | Platform.isIOS)) - ?Colors.transparent - : Colors.black54, - transitionBuilder: (context, anim1, anim2, child) { - return SlideTransition( - position: Tween( - begin: const Offset(0, 1), - end: const Offset(0, 0) - ).animate( - CurvedAnimation( - parent: anim1, - curve: Curves.easeInOutCubicEmphasized - ) - ), - child: child, - ); - }, - pageBuilder: (context, animation, secondaryAnimation) => TopItemsScreen( - type: type, - title: label, - isClient: type == HomeTopItems.recurrentClients, - data: data, - withProgressBar: withProgressBar, - buildValue: buildValue, - options: menuOptions, - onTapEntry: onTapEntry, - isFullscreen: !(width > 700 || !(Platform.isAndroid | Platform.isIOS)), + if (width > 700) { + showDialog( + context: context, + builder: (context) => TopItemsScreen( + type: type, + title: label, + isClient: type == HomeTopItems.recurrentClients, + data: data, + withProgressBar: withProgressBar, + buildValue: buildValue, + options: menuOptions, + onTapEntry: onTapEntry, + isFullscreen: !(width > 700 || !(Platform.isAndroid | Platform.isIOS)), + ), ) - ) + } + else { + Navigator.push(context, MaterialPageRoute( + builder: (context) => TopItemsScreen( + type: type, + title: label, + isClient: type == HomeTopItems.recurrentClients, + data: data, + withProgressBar: withProgressBar, + buildValue: buildValue, + options: menuOptions, + onTapEntry: onTapEntry, + isFullscreen: !(width > 700 || !(Platform.isAndroid | Platform.isIOS)), + ), + )) + } }, child: Row( mainAxisSize: MainAxisSize.min, From 7f77b3c6ca876acbe58868899c169a6280388b49 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 Jan 2024 23:07:00 +0100 Subject: [PATCH 501/676] Updated ios pods --- ios/Flutter/AppFrameworkInfo.plist | 2 +- ios/Podfile | 2 +- ios/Podfile.lock | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) mode change 100755 => 100644 ios/Podfile.lock diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 9625e10..7c56964 100755 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/ios/Podfile b/ios/Podfile index 88359b2..279576f 100755 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +# platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/ios/Podfile.lock b/ios/Podfile.lock old mode 100755 new mode 100644 index c3ba953..7faf3b4 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -11,13 +11,13 @@ PODS: - FMDB/standard (2.7.5) - package_info_plus (0.4.5): - Flutter - - Sentry/HybridSDK (8.15.2): - - SentryPrivate (= 8.15.2) + - Sentry/HybridSDK (8.17.2): + - SentryPrivate (= 8.17.2) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.15.2) - - SentryPrivate (8.15.2) + - Sentry/HybridSDK (= 8.17.2) + - SentryPrivate (8.17.2) - sqflite (0.0.3): - Flutter - FMDB (>= 2.7.5) @@ -84,20 +84,20 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef flutter_web_browser: 7bccaafbb0c5b8862afe7bcd158f15557109f61f FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 - Sentry: 6f5742b4c47c17c9adcf265f6f328cf4a0ed1923 - sentry_flutter: 2c309a1d4b45e59d02cfa15795705687f1e2081b - SentryPrivate: b2f7996f37781080f04a946eb4e377ff63c64195 + Sentry: 64a9f9c3637af913adcf53deced05bbe452d1410 + sentry_flutter: 57912cf425e09398bdf47f38842a1fcb9836f1be + SentryPrivate: 024c6fed507ac39ae98e6d087034160f942920d5 sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a sqlite3: 6e2d4a4879854d0ec86b476bf3c3e30870bac273 sqlite3_flutter_libs: eb769059df0356dc52ddda040f09cacc9391a7cf store_checker: 359c5051d9ec30ff0a8fa39eb5ec9df021bb745d - url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b + url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 -PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 +PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011 COCOAPODS: 1.14.3 From 0b0f38cd2e18b785890474965434e0b2300f135c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 Jan 2024 23:08:04 +0100 Subject: [PATCH 502/676] Changed filter clients modal design --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/providers/logs_provider.dart | 6 +- .../filters/details/list_details_screen.dart | 4 +- lib/screens/logs/filters/clients_modal.dart | 262 ++++++++++-------- .../logs/filters/logs_filters_modal.dart | 5 +- .../settings/dhcp/select_interface_modal.dart | 79 +----- lib/widgets/list_bottom_sheet.dart | 80 ++++++ 8 files changed, 253 insertions(+), 189 deletions(-) create mode 100644 lib/widgets/list_bottom_sheet.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 4b92566..460e98d 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -747,5 +747,6 @@ "selectEndTime": "Select end time", "startTimeBeforeEndTime": "Start time must be before end time.", "noBlockingScheduleThisDevice": "There's no blocking schedule for this device.", - "selectTimezone": "Select a timezone" + "selectTimezone": "Select a timezone", + "selectClientsFiltersInfo": "Select the clients you want to display. If no clients are selected, all will be displayed." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index ff5bb7d..c730a7c 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -747,5 +747,6 @@ "selectEndTime": "Seleccionar hora de fin", "startTimeBeforeEndTime": "La hora de inicio debe ser anterior a la hora de fin.", "noBlockingScheduleThisDevice": "No hay programación de bloqueo para este dispositivo.", - "selectTimezone": "Selecciona una zona horaria" + "selectTimezone": "Selecciona una zona horaria", + "selectClientsFiltersInfo": "Selecciona los clientes que quieres mostrar. Si no hay clientes seleccionados, se mostrarán todos." } \ No newline at end of file diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index d9bc55f..63e81cd 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -20,7 +20,7 @@ class LogsProvider with ChangeNotifier { DateTime? _logsOlderThan; String _selectedResultStatus = 'all'; String? _searchText; - List? _selectedClients; + List _selectedClients = []; int _logsQuantity = 100; int _offset = 0; @@ -65,7 +65,7 @@ class LogsProvider with ChangeNotifier { return _offset; } - List? get selectedClients { + List get selectedClients { return _selectedClients; } @@ -131,7 +131,7 @@ class LogsProvider with ChangeNotifier { } void setSelectedClients(List? clients) { - _selectedClients = clients; + _selectedClients = clients ?? []; notifyListeners(); } diff --git a/lib/screens/filters/details/list_details_screen.dart b/lib/screens/filters/details/list_details_screen.dart index 07d3aa0..95da744 100644 --- a/lib/screens/filters/details/list_details_screen.dart +++ b/lib/screens/filters/details/list_details_screen.dart @@ -64,8 +64,6 @@ class _ListDetailsScreenState extends State { final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - final width = MediaQuery.of(context).size.width; - Filter? list; try { list = filteringProvider.filtering != null @@ -322,7 +320,7 @@ class _Content extends StatelessWidget { ) : null, trailing: IconButton( - onPressed: () => openUrl(list!.url), + onPressed: () => openUrl(list.url), icon: const Icon(Icons.open_in_browser_rounded), tooltip: AppLocalizations.of(context)!.openListUrl, ), diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index 84728f8..cf8a94f 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -4,10 +4,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; +import 'package:adguard_home_manager/widgets/list_bottom_sheet.dart'; + import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; -class ClientsModal extends StatefulWidget { +class ClientsModal extends StatelessWidget { final List? value; final bool dialog; @@ -17,56 +20,90 @@ class ClientsModal extends StatefulWidget { required this.dialog }); - @override - State createState() => _ClientsModalState(); -} - -class _ClientsModalState extends State { - List selectedClients = []; - - @override - void initState() { - setState(() => selectedClients = widget.value ?? []); - super.initState(); - } - @override Widget build(BuildContext context) { - final height = MediaQuery.of(context).size.height; + final clientsProvider = Provider.of(context); + final logsProvider = Provider.of(context); - if (widget.dialog == true) { + if (dialog == true) { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( maxWidth: 500 ), child: _ModalContent( - selectedClients: selectedClients, - onClientsSelected: (v) => setState(() => selectedClients = v), + selectedClients: logsProvider.selectedClients, + onClientsSelected: (v) => logsProvider.setSelectedClients(v), ) ), ); } else { - return ConstrainedBox( - constraints: BoxConstraints( - maxHeight: height-50 - ), - child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) + return ListBottomSheet( + icon: Icons.smartphone_rounded, + title: AppLocalizations.of(context)!.clients, + children: [ + Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 16), + Flexible( + child: Text(AppLocalizations.of(context)!.selectClientsFiltersInfo) + ) + ], + ), ), - color: Theme.of(context).dialogBackgroundColor ), - child: SafeArea( - child: _ModalContent( - selectedClients: selectedClients, - onClientsSelected: (v) => setState(() => selectedClients = v), + CustomCheckboxListTile( + padding: const EdgeInsets.only( + left: 24, + top: 8, + right: 12, + bottom: 8 ), + value: logsProvider.selectedClients.length == clientsProvider.clients!.autoClients.length, + onChanged: (v) { + if (v == true) { + logsProvider.setSelectedClients(clientsProvider.clients!.autoClients.map((e) => e.ip).toList()); + } + else { + logsProvider.setSelectedClients([]); + } + }, + title: AppLocalizations.of(context)!.selectAll + ), + ListView.builder( + shrinkWrap: true, + primary: false, + itemCount: clientsProvider.clients!.autoClients.length, + itemBuilder: (context, index) => _ListItem( + label: clientsProvider.clients!.autoClients[index].ip, + checkboxActive: logsProvider.selectedClients.contains(clientsProvider.clients!.autoClients[index].ip), + onChanged: (isSelected) { + if (isSelected == true) { + logsProvider.setSelectedClients([ + ...logsProvider.selectedClients, + clientsProvider.clients!.autoClients[index].ip + ]); + } + else { + logsProvider.setSelectedClients( + logsProvider.selectedClients.where( + (item) => item != clientsProvider.clients!.autoClients[index].ip + ).toList() + ); + } + } + ) ) - ), + ] ); } } @@ -86,97 +123,92 @@ class _ModalContent extends StatelessWidget { final clientsProvider = Provider.of(context); final logsProvider = Provider.of(context); - void apply() async { - logsProvider.setSelectedClients( - selectedClients.isNotEmpty ? selectedClients : null - ); - - Navigator.pop(context); - } - - void selectAll() { - onClientsSelected( - clientsProvider.clients!.autoClients.map((item) => item.ip).toList() - ); - } - - void unselectAll() { - onClientsSelected([]); - } - return Column( mainAxisSize: MainAxisSize.min, children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 24, - bottom: 16, - ), - child: Icon( - Icons.smartphone_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Text( - AppLocalizations.of(context)!.clients, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 16), - ], - ), - Flexible( - child: ListView.builder( - itemCount: clientsProvider.clients!.autoClients.length, - itemBuilder: (context, index) => _ListItem( - label: clientsProvider.clients!.autoClients[index].ip, - checkboxActive: selectedClients.contains(clientsProvider.clients!.autoClients[index].ip), - onChanged: (isSelected) { - if (isSelected == true) { - onClientsSelected([ - ...selectedClients, - clientsProvider.clients!.autoClients[index].ip - ]); - } - else { - onClientsSelected( - selectedClients.where( - (item) => item != clientsProvider.clients!.autoClients[index].ip - ).toList() - ); - } - } - ) - ) - ), Padding( - padding: const EdgeInsets.all(24), + padding: const EdgeInsets.all(16), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TextButton( - onPressed: selectedClients.length == clientsProvider.clients!.autoClients.length - ? () => unselectAll() - : () => selectAll(), - child: Text( - selectedClients.length == clientsProvider.clients!.autoClients.length - ? AppLocalizations.of(context)!.unselectAll - : AppLocalizations.of(context)!.selectAll - ) + CloseButton( + onPressed: () => Navigator.pop(context), ), - TextButton( - onPressed: apply, - child: Text(AppLocalizations.of(context)!.apply) + const SizedBox(width: 12), + Text( + AppLocalizations.of(context)!.clients, + style: const TextStyle( + fontSize: 22 + ), ) ], ), ), + Flexible( + child: ListView( + children: [ + Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 16), + Flexible( + child: Text(AppLocalizations.of(context)!.selectClientsFiltersInfo) + ) + ], + ), + ), + ), + CustomCheckboxListTile( + padding: const EdgeInsets.only( + left: 24, + top: 8, + right: 12, + bottom: 8 + ), + value: logsProvider.selectedClients.length == clientsProvider.clients!.autoClients.length, + onChanged: (v) { + if (v == true) { + logsProvider.setSelectedClients(clientsProvider.clients!.autoClients.map((e) => e.ip).toList()); + } + else { + logsProvider.setSelectedClients([]); + } + }, + title: AppLocalizations.of(context)!.selectAll + ), + ListView.builder( + primary: false, + shrinkWrap: true, + itemCount: clientsProvider.clients!.autoClients.length, + itemBuilder: (context, index) => _ListItem( + label: clientsProvider.clients!.autoClients[index].ip, + checkboxActive: selectedClients.contains(clientsProvider.clients!.autoClients[index].ip), + onChanged: (isSelected) { + if (isSelected == true) { + onClientsSelected([ + ...selectedClients, + clientsProvider.clients!.autoClients[index].ip + ]); + } + else { + onClientsSelected( + selectedClients.where( + (item) => item != clientsProvider.clients!.autoClients[index].ip + ).toList() + ); + } + } + ) + ), + ], + ) + ), if (Platform.isIOS) const SizedBox(height: 16) ], ); @@ -203,9 +235,9 @@ class _ListItem extends StatelessWidget { child: Padding( padding: const EdgeInsets.only( left: 24, - top: 8, + top: 4, right: 12, - bottom: 8 + bottom: 4 ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/lib/screens/logs/filters/logs_filters_modal.dart b/lib/screens/logs/filters/logs_filters_modal.dart index aec6b27..9f77666 100644 --- a/lib/screens/logs/filters/logs_filters_modal.dart +++ b/lib/screens/logs/filters/logs_filters_modal.dart @@ -150,6 +150,7 @@ class _FiltersList extends StatelessWidget { dialog: false, ), isScrollControlled: true, + useSafeArea: true, backgroundColor: Colors.transparent ); } @@ -225,8 +226,8 @@ class _FiltersList extends StatelessWidget { Container(height: 16), CustomListTile( title: AppLocalizations.of(context)!.client, - subtitle: logsProvider.selectedClients != null - ? "${logsProvider.selectedClients!.length} ${AppLocalizations.of(context)!.clientsSelected}" + subtitle: logsProvider.selectedClients.isNotEmpty + ? "${logsProvider.selectedClients.length} ${AppLocalizations.of(context)!.clientsSelected}" : AppLocalizations.of(context)!.all, onTap: clientsProvider.loadStatus == LoadStatus.loaded ? openSelectClients diff --git a/lib/screens/settings/dhcp/select_interface_modal.dart b/lib/screens/settings/dhcp/select_interface_modal.dart index a9c9c67..40291e9 100644 --- a/lib/screens/settings/dhcp/select_interface_modal.dart +++ b/lib/screens/settings/dhcp/select_interface_modal.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_interface_item.dart'; +import 'package:adguard_home_manager/widgets/list_bottom_sheet.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; @@ -89,70 +90,20 @@ class SelectInterfaceModal extends StatelessWidget { ); } else { - return GestureDetector( - onTap: () => Navigator.of(context).pop(), - child: DraggableScrollableSheet( - initialChildSize: 0.6, - minChildSize: 0.3, - maxChildSize: 1, - builder: (context, controller) { - return Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28), - ), - ), - child: Column( - children: [ - Container( - margin: const EdgeInsets.all(16), - width: 36, - height: 4, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.grey - ), - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Column( - children: [ - Icon( - Icons.settings_ethernet_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.selectInterface, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ), - Expanded( - child: SafeArea( - child: ListView.builder( - controller: controller, - itemCount: interfaces.length, - itemBuilder: (context, index) => DhcpInterfaceItem( - networkInterface: interfaces[index], - onSelect: onSelect - ) - ), - ) - ), - ], - ), - ); - }, - ), + return ListBottomSheet( + icon: Icons.settings_ethernet_rounded, + title: AppLocalizations.of(context)!.selectInterface, + children: [ + ListView.builder( + primary: false, + shrinkWrap: true, + itemCount: interfaces.length, + itemBuilder: (context, index) => DhcpInterfaceItem( + networkInterface: interfaces[index], + onSelect: onSelect + ) + ), + ] ); } } diff --git a/lib/widgets/list_bottom_sheet.dart b/lib/widgets/list_bottom_sheet.dart new file mode 100644 index 0000000..2f8bd03 --- /dev/null +++ b/lib/widgets/list_bottom_sheet.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; + +class ListBottomSheet extends StatelessWidget { + final IconData icon; + final String title; + final List children; + + const ListBottomSheet({ + super.key, + required this.icon, + required this.title, + required this.children + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: DraggableScrollableSheet( + initialChildSize: 0.6, + minChildSize: 0.3, + maxChildSize: 1, + builder: (context, controller) { + return Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28), + ), + ), + child: SafeArea( + child: ListView( + controller: controller, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.all(16), + width: 36, + height: 4, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.grey + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Column( + children: [ + Icon( + icon, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + title, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ], + ), + ), + ...children + ], + ), + ), + ); + }, + ), + ); + } +} \ No newline at end of file From 791c42317b9b4a6aa64523d2bbdac90c7cd129cc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 27 Jan 2024 23:08:44 +0100 Subject: [PATCH 503/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 94b1ce4..1602a5e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.15.0-beta.1+121 +version: 2.15.0-beta.2+122 environment: sdk: '>=2.18.1 <3.0.0' From 46867b951acc4851177006c2fe6a6e652fead184 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 Jan 2024 15:01:33 +0100 Subject: [PATCH 504/676] Updated app icon --- .../main/res/mipmap-anydpi-v26/ic_launcher.xml | 6 +++--- .../res/mipmap-anydpi-v26/ic_launcher_round.xml | 5 +++++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3722 -> 0 bytes .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 2412 bytes .../res/mipmap-hdpi/ic_launcher_foreground.webp | Bin 0 -> 874 bytes .../main/res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 2412 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2407 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 1562 bytes .../res/mipmap-mdpi/ic_launcher_foreground.webp | Bin 0 -> 650 bytes .../main/res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1562 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 5202 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 3268 bytes .../mipmap-xhdpi/ic_launcher_foreground.webp | Bin 0 -> 1114 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 3268 bytes .../src/main/res/mipmap-xxhdpi/ic_launcher.png | Bin 8299 -> 0 bytes .../src/main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 5358 bytes .../mipmap-xxhdpi/ic_launcher_foreground.webp | Bin 0 -> 1620 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 5358 bytes .../src/main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 12288 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 7522 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.webp | Bin 0 -> 2154 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 7522 bytes android/app/src/main/res/values/colors.xml | 4 ---- .../main/res/values/ic_launcher_background.xml | 4 ++++ 24 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp delete mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp delete mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp delete mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp delete mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp delete mode 100644 android/app/src/main/res/values/colors.xml create mode 100644 android/app/src/main/res/values/ic_launcher_background.xml diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index ce2f8b0..6c2fdb0 100644 --- a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,7 +1,7 @@ - - + + - + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 620121e3fd0e332abcc93f13b370bae5f9c344df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3722 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..4d52a7366d978b3a4e5ceaafb2066354d095119f GIT binary patch literal 874 zcmV-w1C{(zNk&Fu0{{S5MM6+kP&iCg0{{Rop+G1QzvL>CB*n_!d*EN#`+Y_jw;zdc z+(?olMefmy{den}S!$<|Bso&{X@2YseE*-SX*ZH=s|x4b``rZzSrhwDAamzE^uENT zVCSU=Pq_T#WBC;G+8?GJRs5lJ&9nIxqKks$h6bZDF^Nr-2(}W3qj6^35^J7jnUeg) zQIpV7-Av8c+_3uBiL-Ib7G0WRW*97)90du1C8Jp&$weV0z>xr}g4F1!1j8F*K{+vSdhm&{krf*mU%0C=wD9_+2SoYLK zyy>EoIUS=Qxl$Wl8yfcm$7WC;yKn;Z_lv%^}cNA@&2!`O}5v+KR)iT z|NBAOZCi#UMccM*+qP}HD{tF9Zrl37laY~`UGY8*BKki8?7#p2%m2M@zV4ki_ALNf z>?z~0f!{YA=n^pi^??YgxQv58?m`pKS!kX0q)6Zrv@Zpc!zN#WsFH6(3%gqAS!+j$ zrxWOV@4yP(V8NL=)nim-{z|bcAjN$*AC$?%*by-Xuq?5SN#yLFeFb5{a4m5Yz#Wq8&aSH#=@-J zF!Vgp<+3eQrCtvVTe%@!HuOmC-Dj#Tx(r#lgyKWh7ERM1VvgrM_i8JeIu2Ef6RaHH zUlS5J=^?KwDcv(pO!d*Cshr7Gz)vl95&e#gvBysMFm+c@p+SxPP|*6u9@26xC?y}f zTnlIdoZPBBS3_SKU?`3;=DZHdK&iPZS_W;5{nJ;*r^u7c!{#SgyOPX*|Nn100Kk~4 A_y7O^ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..ee4fa4dfb50686a12932c31f504337f0a8933251 GIT binary patch literal 2412 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 4b33d20a48e967f4400f0fda9d13094691d8b06a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2407 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..8a39f50c67d2b8e7c6b05a3874f9d28bf8bec7ae GIT binary patch literal 650 zcmV;50(JdTNk&G30ssJ4MM6+kP&iC>0ssInYrq;1uj49`WGTvifCT(2;uj;=-rF`D zHzi_l;| zjGYAKuO>{1Li55gNbB7ZV;{Xo%%5-TnaOu>cbO{xUtK+~p3^4LOzG)!OnINN{`9v? zSMxZ<>lZ!N3$JUeKL7K(+u@M5ZQI#M8QW$swmq{uYumeH+w=cFyl8s#$y)D|^iD+o zC&2pW;rzFV1EZkdMrZl!^S$Clw#iX4sA;IXBu-tJZ zY$CD_hT!A>kf`Pl@HI3f)px>Y!vw8)@I73kCS%1x662MSl&o7wa-2oT*&LFdJ|kmy z)Yk3z@@%!PAu6xDKi{Q;^ez!wgSI++QF_6enT_{8st|9Hu-Oas*rk>5-lPh>n*@|~ zKy#UWe5rwsFy*RT=q@C1p2^HhIxtnK)(Pzqz2k`-i}{@vOsdsAFvct@I<9nbMj9<< z?o%uqV@zGDNsATO5uPr!GVc#RwwO7xmFrBVMzv7V{w8~OdW@d+(nUi6bbOTS)o2=j$W=@AXQE9m6Oc^NY zA1X6#s+&459o{TJsZueM!Ul!k8stnBnyJE385k-e;M%rr>>0mp+pc0Koo(AzXY&DU z=M`-H?v>g$zdHePV{2RHrvG}FnVFfHnU+NV_kI8VC2TBag_~|JW|rQOA~nFWGlxti zI6~1gj@Y3h6<~%2Je#=z#u+#Q02Y$++O=)lE^WKDZToDS4kSr3t-1fTo^9K<-^VIw z+lJu}qy(zLJDvd8<}i-nC?BT2>kAYzhjS#(%88uEW#R7+;jA($j7S3DYF@-Aj04@J zUmK5~UKUh;aMiN_WE3|Sc!=j2o5rgFbYS(Z?{44(z>SaaA$XsvtuYvU3j)x_ZykIj1;ZC9V=@V0CZRW|j~_|V(D*L^Db0{3 zF7kcvr2`VLd3r^LBCP{r^rFi9J2nt*j0h+&l0)J(uU|n{mn950e|24q97;7aIHI#i zclxgOyM3#Jmgg!LhZF03vXFfrCm(RQC@GHyaPR3d|RSn<7-I zQk}ENhyaPqJQb2v-9M7QTsX6M;GVy8QG_nY1BaDBLIAm&d&9pbjAvfgG}T6 zQyv-6UxCsSdbfVWm>N1#|C2moMgHu32AGlm2f6LVZ%mfBgQDOemip_*nau;!m{O{-wErMyJgR;DqO@A$iv(!jV5L7! z&;mAidE_Dc4LFW7Da90Ny%-+1&AfGsFN) z7w2Bbl19Z60N`sds6PLw^7iIuHl^1asnteAD5CoOA@%2vzr_LoEyR6MrQQrs06l2g zE?YKOO4-GQD1Sb46-d04s*39yQN`887Eh6N;zc($z%VH%wh-nGXny|aV(xTSe6-sn z%`XxWj6e<@Wn_3rhCF`W-v2G4O(M#fOzcTCS=aBq!cfvp?o~^kX9JFOPRU_IL{xfm zaANTw!!w{X}`8$ zM`A=pW6|-1J&6G>&!Gbk83h9JpJjE|d!8+Ejs|fk2TX4HM*~1Fj_i^!73~m= zzj{>#Ks|svP~u=>YVk(VMZyfxHYN)I(5cf$`g?RbThC-aEjwo z>;x|_+F;5}i;=Kiy@^R5P5Gj7r`TSxQ%*I~u;Uv5eu-Xg(pjKee?V}^Dt+t|-|#fg`v-QD!a(XRcC z+b-J0v{mmUdcskNkz^=Fu6q5hI$kZpT81ZX{pGILs~+AaBNVcz-WPq literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 3128163ec05067862b57fc1d0c6e6319ceb1a148..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5202 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�+)}qpx%;93eR+%P=tq{eDcZPO_?%f^4z&|=dD_`YTd?-8+Y&6 zvEyiHXlPP+c=*|)M~~)G8eK?axJ*+{abjX(aY91EWg=eT@#DvHBO)TQ!otFmcJADH z^t=u7m8zM%tjQIbaOZ4BagSn47ZrUn$= zP`O2LioG%jRB>}1JOTn&7#p!jZx|mQ14IxQAi)2R*91W@4dFBREZRU@XcKLt5A=mT z(KmE3NaI7IBon3v7!A_|f>RXYP*Z^?K>Q?$1rLF#1;$4}3$Fn(D1pD>HM|G!#b+c@ z&=%T6+vo#*p-=R!oSqEQ_@F2Wr6iRk7CZwC4le=Y1MnJ-AYaFO@fmzp5=BWCgD_28 pq;b{cQUYX9LjAguB+ZsA{|^o}C#c|i>hu5r002ovPDHLkV1h~aw;})l diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..aefe0b69900475853d378713de05030eb9bbb387 GIT binary patch literal 5358 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..3599460f1dfcaa3345aad61419fca7c20025d2aa GIT binary patch literal 1620 zcmV-a2CMl}Nk&FY1^@t8MM6+kP&iCK1^@srL%~oGe+Da(B-K{-UIr!Czm5BQjWE5} zkDmp{Z5v4v-7|YX7n^@no6B8x97&R+WDmjtei(?yxT0Yil5M+f8~;zL5J+xg1uWlx;77^n|k`7^_{*AzGr=sPGx!540pE^) z65G}p>r{eBuCXjzY_Ug38l;qj{;IpZg)Z$(DpkEk;8 z7D1$GRcq=|t(FmyWc2TldTp6~hxag!BBqR}^@xbSr*!;x4ZE}I!Tn?%Kd1A?b#FX> zIWJzPY#rs^vu*!4>l4rW<8(S*+Tp40+yM&Pww;Z%H(lGdZQHhO?~Xclr_Ppqg-#FFJcc*V~yXswV58tWU1uh{}1OKChA=8lD6Fa}Bwn`o4P#-f_(-(QMKDqu+ym9YBnwr_L?|O#rk+*x86R=rESz3bLEPKR}M$$q_Ch!Rq}U$svdfN zW4E^tUBdqch4(wI+j3l|f*tv4^6fN8rXHNz@wYJZ>&Mx9Q%Kc%>hUfTrt3R;HxqPo#w|%P4Uz9uV_YK4j-L8cP;at6%Pb_0QwptbDohUR zS1zpBXy_4>klI&MhpI_B%pNMN`ok>fld4pqas|xqWtnHD0V^uipzJIN_O?tL0ytZy z0-rB~;vmbsqkzkw1HYD;AUVJ?uSg)XWuW)g4Voh?GnfY4uLHZ6u^_tEGM$JZ_GKXV z(gUhD2z}|8?N@&)@VpG*PJ`?19jzc=0FEV&s8eWrV8xOs!@W0F_EoqU# z>2HNfu9P>F!i#udx-i%V(!+$xnlRUxtL1}A1Fd6${Y6GPGs9&gIqO1z;G2H^NCVP- z38TxH!BcD?FAe~_gZ+3N1?WSB;bY8zb_PWI6aa|7S4XQz0CR=mM?P+tWkihD0U-Ey zE#Jcd>}h0dAh;nzGor1ofqkVyh$n6UQICc3YwV!s84=ajYhYouxEl(rRvX9o#BLUz{g^XE(#662$w& z+I%mC%vs{yRVjwLS|taOJKeXF}%ihmy{9U3GZDQ+BCr3M93@*X9_HoAzWKi zKM1KC!4v`){5lF=K~gUXZ6m-f(C1bdsM?SMegSqr_N&=KkY)s=jn(REdkS0wEN)Rt*(x6x z2a#Q>h1TN)$TI_QvBxzX>|;^KfBzv9sx<5Cjr~fK8&h8lR2uPPcWOPL2ldg^#__-7 Sf5-oh{~iB3{&)QEj1vIFClprz literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..aefe0b69900475853d378713de05030eb9bbb387 GIT binary patch literal 5358 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 7eadefba48070f9c3a8a26725fd28bf8fbc32401..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 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 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..68173f9dc5fb9a06131b4fe33e9aac89e0944767 GIT binary patch literal 7522 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..7d5730598a6c6325673b3b9671b9f1223d0df2c3 GIT binary patch literal 2154 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..68173f9dc5fb9a06131b4fe33e9aac89e0944767 GIT binary patch literal 7522 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml deleted file mode 100644 index ab98328..0000000 --- a/android/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #ffffff - \ No newline at end of file diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file From c87e3b4943d0a9222b1e4c3eee875ca1b39264fe Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 Jan 2024 15:09:41 +0100 Subject: [PATCH 505/676] Updated splash screen icon --- .../app/src/main/res/drawable-hdpi/splash.png | Bin 6268 -> 9685 bytes .../app/src/main/res/drawable-mdpi/splash.png | Bin 2758 -> 4507 bytes .../main/res/drawable-night-hdpi/splash.png | Bin 6268 -> 9685 bytes .../main/res/drawable-night-mdpi/splash.png | Bin 2758 -> 4507 bytes .../main/res/drawable-night-xhdpi/splash.png | Bin 7482 -> 13398 bytes .../main/res/drawable-night-xxhdpi/splash.png | Bin 16774 -> 21274 bytes .../res/drawable-night-xxxhdpi/splash.png | Bin 20129 -> 25528 bytes .../src/main/res/drawable-xhdpi/splash.png | Bin 7482 -> 13398 bytes .../src/main/res/drawable-xxhdpi/splash.png | Bin 16774 -> 21274 bytes .../src/main/res/drawable-xxxhdpi/splash.png | Bin 20129 -> 25528 bytes 10 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 android/app/src/main/res/drawable-night-xxxhdpi/splash.png mode change 100644 => 100755 android/app/src/main/res/drawable-xxxhdpi/splash.png diff --git a/android/app/src/main/res/drawable-hdpi/splash.png b/android/app/src/main/res/drawable-hdpi/splash.png index a042f2bcf6dc52c506d8eace296f5a95f69e70da..0952f84abef68345d0cb9a52310db31ca5fdda1b 100644 GIT binary patch literal 9685 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 P16i1zG_5%5k?_9&e|>Ax literal 6268 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 diff --git a/android/app/src/main/res/drawable-mdpi/splash.png b/android/app/src/main/res/drawable-mdpi/splash.png index 28271d4d45cb768f408859174e13e8f5dcd93eea..b8c6efb7701e589103761bbf46460c12bf82e6c8 100644 GIT binary patch literal 4507 zcmeHKXHXQ%vYrhb7L=&SAtN9`K=LYamkc5xL4qI|$w63x3hXLD5SFZnWCSHgLCGsY zf`B3tM6zTA$r5+(@?O=ediCnQy1#GTshR4T?)kcVzUlcfQ8)E8X{cGL0RS}GT55&> zK*&=FK)}ett;EcjEV%8p40Qo`zz+Z}41hzj3bzD+pEv+3HUP-I0D##$z1~0p0Oa1{?q@%z`s2MBoc|+YxpL);`cFzdPV>++z7bZu&+G^xjheeU#AM$rB68g z`xTM*t$4fASG`H7&GKJ9n`grRoJ%=oFBGVk=~f#to`v20MR|XlHu~T~<_UMX2%$x; z|Hp#IZ*1ZbOCDcM2Wn7%%GUR6#ET-q9`##4oe&RpVzMeeUmv%ipvLVb<=0AlMBkjY zTfuBSN#!UOYD9h-HE~|6iVJ;=f1bU#^d;Gh)u5zP_`FIp^JO}oiWtcEv94+Aa**MY6mwQOgG32DsL@wUjVM~o(@Q0 zKFXi0q{L|Js#7jO*lFQ^yKgs)wt zwuXV4GCc(Y#U^r+x}X5ZdWlt8dQt;MrHtp_E&9M)Qy36~l;9iC$iL|EwW!9_eJw$H zdGn}Rik%mI5 ziD)vYov6pN;VjaIMH2yXVwj_7ezKN=5#6he5IT=$Pp)f5Z_lVG_+71)9Qj*A4m!k|UZ#F@`cpyh%J`0?u(9qrsyojN^%zX3z> zWMwR$f}U^zmIzOP=|#4x>BJ@-z8X}nSF+rFzl`vs%-K>(c_8^ zU|SuMho=kX1&A?U!g+)%u`TqX(4*BkSF}Oe%HT*{aBg$3Wjv@o&zVCusJ;KhK!`Zp zHC^G##-f;cacgG-_3E&=#lPO4hq&LJ=9VEs{-VKfKu5LbrZ27>!_Km>FY_QO@C7*o zt|u@xI=l}RbhN!^ zzqxEMj|-`$`vv$b_bIimOG`i)i7~d@bmAWyD;cP;iRLFTzBFkh&&=o1^Zq0tWZ(BU zTf&A@`qhSqJiqTPMB}ygrIc>5kwEj$z6)$K>#ubyT<5t6au@rI;oeSz0tjEqC z-Iu$xZ%&<=VoAXFAO`RKW}%Q8yVT+69@Zd@Ro>pGG!xIdO7>!2Aa|TI5+5Gaq48dd zCDpudk&9bcDwOxsq{c-2B7Bztb;`m8qX^W_tiWkbi3_#*Z^Pn7BW1}*K~6hzcn7wh zT--nQ$w}HQOTIdWiCDObL&8Kp$sn*x&l<7^$&R-a00v=BaC%dh(H|e`I6b!`KAJoZlL_c!+#W1y(1oQ}F&m0vYzajaz*d zF?)jLqG^77=+>-K4SCG#(rpYc&a|=gdn?xi(b3m* zZf*JhncQ~W>`GazPdV@G>)T}Cz*(7qoQeD4R(_OHhUG=&2ufcSs0g_%8m$?jZyq>1 zSsA^zYfZ4UDgLkI6mQJvyLOYGY)bQeLWINoOj3xq?Xrbi>WaJFo-+sA%urJwJu$D= z&FI>O<`a?r1-)wfF2!-A@0{cV#J%VmJbt4mmOX#%24=6=tGD}>goovtsYmDY{$mNh z*`S@s2>3=(Y>Vnh+_ZMXHrW~`T;E| zulgJkhTNh^-_3X5Ol)d(p?ElN!o^DLbK^satR-t($%C))tK?%zg1sfz?u5Tmfs?>XTha zyt4Vz69!%PFy`+%Y(%~%t1#{WX~!qS>-p~)oe6^7?#X}Ck`(DF%=Dlu6KAe7~ zIxgo@&_PWK4X&NQaNVo(TPZ#`nYQb!(Y3XVKbQ4U)iMxo{AN^GbKCjd zGdc4mZG)>UUg)o0VT8UNez3*T8Eupz46`xsUE&J)0C1MLIOxV2OC&3)bFrjw$1a)& z$P#1L(3QCndB*`E(Iq_0GLQ`+x0YkyWDm$YGq(B+3o~)TKe2pt~3A9o9*X6U{!OMq$k+!?k)apA~StklUtbOy~JT!1IdR zbzJh4Zh@7*YDAkgH3e~44ftF79`okro(cHDls8^-Z8#FJ;Ka(Tc1qesqh|-e6>v?7 zn&(^TdTfZ{Ef{n^RKIV2WcM@s?;^x4A@-bED2NF-JN@1jwF%G8{%E*YJ1H(s*533e?>dV`E3#iJqLBpH7+nhV{e07lYn{uqJ zlwj$+P^B=cLjP@&p}7aM>OpWHqW9@h;>cx0jp>-A02q(vLqaee#FB%2+=@GIOpUHC*rtCl=PSe?9u_!<1~$vsf@qfi|OChP|9u zxx?VxyHtNB)XQh?vX-fE`Gq+Oz}^?nZzJq(8NkLM>|6cxi|YKE56ni(E%i=))@b z_5x8whPJVQ@Xnel+wxNB*7v)>86d<^? zC-d0xFTopko+WW`|B0wa)2iS}9s@oZ2pjSze{x z3TBP_fjwtoutWYYq@z&~6epVYO|fcL>QU__JqTgK zzK4qYn_K?S5FqGve6HY0Hc%#YLEnMth%6o`pLj@kj%AuPs1VbIKn%qz(i~ekV<7~C z#p;QK$2rumeS$L~==MK)i1?qVju?v95OAb_jRoq6H5Hly(+hM}65=ma|3o(42k0$K z;fP?;=7;W>^2=8tpsU_jE0>c~ooEqyKwU=(?p1T>x+<@9IB8UuPrw04Bn}2%OApdB zvm3ITzYBnB1ah2agEFqCbgbmZdBE+iopOlB9T)#%6GdXT0a$9T@JtktwC<#HleVZd z2k2hxRPjUHicfewd|U>A8%JEJi`3sI*UIN_>%u`R&w_gHPu?o&JB6tLA%f{9BU+`RU(XS2UaiTFyrbKJ$9qpWWA$pZMpEJ|Bx~-=R)zEs zt)||UFW&WOq6t&m8JxL=r9qf6{`GKvv#4CZy3y+9MaX)7G4|p=Z%HeppP?cbBP65V zlK&!?FzRL)2V0DzoV|}DSpZ3KNoi4W2~o*w#uCzU;?i;wQo`cma^m7qzjYe^7r?{I z!R7A#e-7BM+NLA}1pg-j#>Kv((PF75H&Hw)WjK)LlPYJztF|GI9Km_p7pNh`K+6Ft&6*NZZR=jY6t)@ z@$shk0RYpNFaXWfOF;DFV*nUt`%p-G;$Wja+lmACTD+TN9I7e1MQ%5ZSh!$i+C{r- zj}3C4egO|y6I+dKT-tA}cHxyR-I^?MdHAbeL^{+hjw?W?%c+5`8m9>_a7J+KWLTrB$G=)v+4q)Y2r<+CZLyx`7ksMoxU~nO zFd@)EH{7&x`(mEK1`$)pm#5g=1MI1iyh%i8D}f0B!9Kle^qA`}?rG~uw^Zyf7l zn8Q`BI+S-FmD~vtyMju~rSuFASy21#HEkU!!SBP~4?bn+jfvzd*6=G2uQ}*Zyp3Vr zyPo`mvOE>se=z+I%6t;|Q1V*rGmiB##g)7lE2Jqa@j%P(j&Gntw%GVSSyJ8kc?S?R z9c|Q}5ke|2o%Zvy_>mClO92{lUU?@ygOUm*3U0ZEW4$OK;c@=R$Fc8Zefj_-Mw<Z35xoFwMdG$S&wKEosGCIV0g7lj0NGhXEyiS_ZpA5w;lXG5{pjW8MbxcDAV=#R2BXNI zBVQ=D4LV;Vf}K^p;zd%A{vYnzO%HvyeOZ%?R=4@*+TyQz0UK?ooGbMR*|X0-w{5mt zfSja&51TvFCsT*E6`1cq0k##3inwl2Gq5H1C}NLZ->r?t>^82c5F&{mM4|FEQjaXp zjbKwjz?rFUTZbI(E&&ujooiBCU(rm@cY;wR794MJ(AvPY<|<>1K6ZF&r3m#xi94C0JZ5of*(MfQnTToPSo)v}Z5Nj6H{E?kr(iYaS0) z^Bv+**NnO~hk4bLO#B>acwZ`ahaO_b?|_uo`_oFJLQ?Pb9AnF8?mT~#vTs?^Si++x z6O*1d!pt7bIf0Ibm9%_Pzc?q$c4`cu7d3{eSA>2Ns)EXs-XP=6Peryx{V7()2>nKL zTzxA0;mmXXy=OZd7FFC#o@iX#UOd|!tL8A?4h%L8>(i!I^6=+Gen-Ix9xI&EKNXaM z^+8yZ_-amBOMFCLQ`a}k@+SA=Nt&T7+4@B+Gq!F{)o0dvMX}3RE+dEa5+dG`b_~|? z54ay=uXE+-ete2Nv<4m{Vo2J!wd zY3&E1Qhuc3=WhX1rH>BI8YiCQt2bmZn!7lx%b6Jv(W^`Pprc8Uo8^syHDuAA#qLL3 zWAt~~6{w8&Tf!Q4#qCVFUTyfrdGRJP*mQlk0-o@_zzTk4RX0_22=Q#16S}%tMlk5Y z19fGsLyu`@&Bk$3t@+-ZK|`kAR&j6d(m{jE@hGM~cm@P*$O%T06e7X|xSD}BE7;09 z2_{65#{vtF7DFZKCK52TKZB5H!mwb@Q^)UKMz0l^95ar2|IuO@)&x-)U`zWbjlc{s zp1W>tbsVW5gY2;z5rxz$nqq8Bu?`kIm6r{mq4*$XORyW<`mVIuy#$>Qby4+GB$PO7 z_UP|u*+^N7kT=RRxEFvR?iMy$@zDwQCo9uO>d#d_`N9H2T|wy~Mcg;iH#JBYULf%Tzn>x(|q7m#(BHCaxzN1d@%rzei`alm-%1J bNpv96WEs*b!sfRAKLtLXJ1Nh|A<6#*Uul)d diff --git a/android/app/src/main/res/drawable-night-hdpi/splash.png b/android/app/src/main/res/drawable-night-hdpi/splash.png index a042f2bcf6dc52c506d8eace296f5a95f69e70da..0952f84abef68345d0cb9a52310db31ca5fdda1b 100644 GIT binary patch literal 9685 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 P16i1zG_5%5k?_9&e|>Ax literal 6268 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 diff --git a/android/app/src/main/res/drawable-night-mdpi/splash.png b/android/app/src/main/res/drawable-night-mdpi/splash.png index 28271d4d45cb768f408859174e13e8f5dcd93eea..b8c6efb7701e589103761bbf46460c12bf82e6c8 100644 GIT binary patch literal 4507 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 bNpv96WEs*b!sfRAKLtLXJ1Nh|A<6#*Uul)d diff --git a/android/app/src/main/res/drawable-night-xhdpi/splash.png b/android/app/src/main/res/drawable-night-xhdpi/splash.png index 46169c660951e5b6d7ee35decb2652f203f16178..09c5fe03e0145dc8bee28facd9212af217699dde 100644 GIT binary patch literal 13398 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 Mx%J7i6U00J1L`Yc*8l(j diff --git a/android/app/src/main/res/drawable-night-xxhdpi/splash.png b/android/app/src/main/res/drawable-night-xxhdpi/splash.png index 27ee599bf019baff150d9f168737b9550f9f334d..7251f533702e4121b01cf97f565dd7ec680060d1 100644 GIT binary patch literal 21274 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 O4T6S8tvnl+T=W}DfqHHL literal 16774 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 z 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 E2j@M|lmGw# diff --git a/android/app/src/main/res/drawable-night-xxxhdpi/splash.png b/android/app/src/main/res/drawable-night-xxxhdpi/splash.png old mode 100644 new mode 100755 index 09a5539a80834f94a525b124da9f7308851199b2..539c85bcc73a23824fb21160e1437f68aae895a6 GIT binary patch literal 25528 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 literal 20129 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 diff --git a/android/app/src/main/res/drawable-xhdpi/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png index 46169c660951e5b6d7ee35decb2652f203f16178..09c5fe03e0145dc8bee28facd9212af217699dde 100644 GIT binary patch literal 13398 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 Mx%J7i6U00J1L`Yc*8l(j diff --git a/android/app/src/main/res/drawable-xxhdpi/splash.png b/android/app/src/main/res/drawable-xxhdpi/splash.png index 27ee599bf019baff150d9f168737b9550f9f334d..7251f533702e4121b01cf97f565dd7ec680060d1 100644 GIT binary patch literal 21274 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 O4T6S8tvnl+T=W}DfqHHL literal 16774 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 z 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 E2j@M|lmGw# diff --git a/android/app/src/main/res/drawable-xxxhdpi/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png old mode 100644 new mode 100755 index 09a5539a80834f94a525b124da9f7308851199b2..539c85bcc73a23824fb21160e1437f68aae895a6 GIT binary patch literal 25528 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 literal 20129 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 From 69612cc3e5534db04a85374ca555920bcf8b2e8a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 Jan 2024 15:18:18 +0100 Subject: [PATCH 506/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 1602a5e..e95f496 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.15.0-beta.2+122 +version: 2.15.0-beta.3+123 environment: sdk: '>=2.18.1 <3.0.0' From 300738ca14ba0b06139f5647fb9a9c2cc61367d7 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 Jan 2024 17:13:18 +0100 Subject: [PATCH 507/676] Changed some error texts --- lib/l10n/app_en.arb | 2 +- lib/l10n/app_es.arb | 2 +- lib/services/auth.dart | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 460e98d..6d473e5 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -24,7 +24,7 @@ "invalidUsernamePassword": "Invalid username or password", "tooManyAttempts": "Too many attempts. Try again later.", "cantReachServer": "Can't reach server. Check connection data.", - "sslError": "SSL error. Go to Settings > Advanced settings and enable Override SSL validation.", + "sslError": "Handshake exception. Cannot establish a secure connection with the server. This can be a SSL error. Go to Settings > Advanced settings and enable Override SSL validation.", "unknownError": "Unknown error", "connectionNotCreated": "Connection couldn't be created", "connecting": "Connecting...", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index c730a7c..8180d4b 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -24,7 +24,7 @@ "invalidUsernamePassword": "Usuario o contraseña no válidos.", "tooManyAttempts": "Demasiados intentos. Prueba de nuevo más tarde.", "cantReachServer": "No se puede alcanzar el servidor. Comprueba los datos de conexión.", - "sslError": "Error de SSL. Ve a Ajustes > Ajustes avanzados y activa No comprobar SSL.", + "sslError": "Handshake exception. No se ha podido establecer una conexión segura con el servidor. Es posible que sea un error de SSL. Ve a Ajustes > Ajustes avanzados y activa No comprobar SSL.", "unknownError": "Error desconocido", "connectionNotCreated": "No se pudo crear la conexión", "connecting": "Conectando...", diff --git a/lib/services/auth.dart b/lib/services/auth.dart index a450348..68e2717 100644 --- a/lib/services/auth.dart +++ b/lib/services/auth.dart @@ -2,6 +2,8 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:sentry_flutter/sentry_flutter.dart'; + import 'package:adguard_home_manager/classes/http_client.dart'; import 'package:adguard_home_manager/models/server.dart'; @@ -52,7 +54,8 @@ class ServerAuth { return AuthStatus.timeoutException; } on HandshakeException { return AuthStatus.handshakeException; - } catch (e) { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return AuthStatus.unknown; } } @@ -75,7 +78,8 @@ class ServerAuth { return AuthStatus.timeoutException; } on HandshakeException { return AuthStatus.handshakeException; - } catch (e) { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return AuthStatus.unknown; } } From dd927bbd25971194914eaca94102f5c5b8068c85 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 Jan 2024 19:03:49 +0100 Subject: [PATCH 508/676] Fixed dhcp not available --- lib/l10n/app_en.arb | 3 ++- lib/l10n/app_es.arb | 3 ++- lib/models/dhcp.dart | 6 ++---- lib/models/server_status.dart | 5 ++++- lib/screens/settings/dhcp/dhcp.dart | 11 +++++------ lib/services/api_client.dart | 3 --- lib/services/http_requests.dart | 1 - 7 files changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 6d473e5..723c08a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -748,5 +748,6 @@ "startTimeBeforeEndTime": "Start time must be before end time.", "noBlockingScheduleThisDevice": "There's no blocking schedule for this device.", "selectTimezone": "Select a timezone", - "selectClientsFiltersInfo": "Select the clients you want to display. If no clients are selected, all will be displayed." + "selectClientsFiltersInfo": "Select the clients you want to display. If no clients are selected, all will be displayed.", + "noDataThisSection": "There's no data for this section." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 8180d4b..837d9d7 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -748,5 +748,6 @@ "startTimeBeforeEndTime": "La hora de inicio debe ser anterior a la hora de fin.", "noBlockingScheduleThisDevice": "No hay programación de bloqueo para este dispositivo.", "selectTimezone": "Selecciona una zona horaria", - "selectClientsFiltersInfo": "Selecciona los clientes que quieres mostrar. Si no hay clientes seleccionados, se mostrarán todos." + "selectClientsFiltersInfo": "Selecciona los clientes que quieres mostrar. Si no hay clientes seleccionados, se mostrarán todos.", + "noDataThisSection": "No hay datos para esta sección." } \ No newline at end of file diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index 9e7f7ca..7953f47 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -1,11 +1,9 @@ import 'dart:convert'; class DhcpModel { - bool dhcpAvailable; List networkInterfaces; DhcpStatus? dhcpStatus; DhcpModel({ - required this.dhcpAvailable, required this.networkInterfaces, required this.dhcpStatus, }); @@ -83,8 +81,8 @@ class DhcpStatus { Map toJson() => { "interface_name": interfaceName, - "v4": v4 != null ? v4!.toJson() : null, - "v6": v6 != null ? v6!.toJson() : null, + "v4": v4?.toJson(), + "v6": v6?.toJson(), "leases": List.from(leases.map((x) => x)), "static_leases": List.from(staticLeases.map((x) => x)), "enabled": enabled, diff --git a/lib/models/server_status.dart b/lib/models/server_status.dart index b43dbd1..fb7c1b4 100644 --- a/lib/models/server_status.dart +++ b/lib/models/server_status.dart @@ -21,6 +21,7 @@ class ServerStatus { bool? safeSearchPixabay; bool? safeSearchYandex; bool? safeSearchYoutube; + bool dhcpAvailable; ServerStatus({ required this.stats, @@ -39,7 +40,8 @@ class ServerStatus { required this.safeSearchDuckduckgo, required this.safeSearchPixabay, required this.safeSearchYandex, - required this.safeSearchYoutube + required this.safeSearchYoutube, + required this.dhcpAvailable, }); factory ServerStatus.fromJson(Map json) => ServerStatus( @@ -64,5 +66,6 @@ class ServerStatus { safeSearchPixabay: json['safeSearch']['pixabay'], safeSearchYandex: json['safeSearch']['yandex'], safeSearchYoutube: json['safeSearch']['youtube'], + dhcpAvailable: json['status']['dhcp_available'] ); } \ No newline at end of file diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 75d1856..a17d620 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -15,6 +15,7 @@ import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_leases.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/select_interface_modal.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/dhcp_provider.dart'; @@ -182,13 +183,15 @@ class _DhcpScreenState extends State { @override void initState() { - if (mounted) loadDhcpStatus(); + final statusProvider = Provider.of(context, listen: false); + if (mounted && statusProvider.serverStatus?.dhcpAvailable == true) loadDhcpStatus(); super.initState(); } @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final dhcpProvider = Provider.of(context); final appConfigProvider = Provider.of(context); @@ -353,11 +356,7 @@ class _DhcpScreenState extends State { }); } - if ( - dhcpProvider.loadStatus == LoadStatus.loaded && - dhcpProvider.dhcp != null && - dhcpProvider.dhcp!.dhcpAvailable == false - ) { + if (statusProvider.serverStatus?.dhcpAvailable != true) { return const DhcpNotAvailable(); } diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index b122a8c..0abb737 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -490,9 +490,6 @@ class ApiClientV2 { return ApiResponse( successful: true, content: DhcpModel( - dhcpAvailable: jsonDecode(results[1].body!)['message'] != null - ? false - : true, networkInterfaces: interfaces, dhcpStatus: jsonDecode(results[1].body!)['message'] != null ? null diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 37a2cc8..2d001f2 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1352,7 +1352,6 @@ class ApiClient { return { 'result': 'success', 'data': DhcpModel( - dhcpAvailable: true, networkInterfaces: interfaces, dhcpStatus: DhcpStatus.fromJson(jsonDecode(result[1]['body'])) ) From 56943ec73d290df1fa3ddcbf8dc8dcf963770e1c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 Jan 2024 19:04:01 +0100 Subject: [PATCH 509/676] Fixed no data issue on home top items --- .../home/top_items/top_items_section.dart | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/lib/screens/home/top_items/top_items_section.dart b/lib/screens/home/top_items/top_items_section.dart index da0ccd8..5749f5d 100644 --- a/lib/screens/home/top_items/top_items_section.dart +++ b/lib/screens/home/top_items/top_items_section.dart @@ -90,27 +90,16 @@ class TopItemsSection extends StatelessWidget { return values; } - final lineChartData = lineData(); - final total = lineChartData.map((e) => e["value"]).reduce((a, b) => a + b); - - final Widget noItems = Padding( - padding: const EdgeInsets.only( - bottom: 20, - top: 10 - ), - child: Text( - AppLocalizations.of(context)!.noItems, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ); + final List> lineChartData = lineData(); + final mapData = lineChartData.map((e) => e["value"]); + final List total = mapData.isNotEmpty + ? mapData.reduce((a, b) => a + b) + : []; return SizedBox( child: Column( children: [ - if (data.isEmpty) noItems, + if (data.isEmpty) _NoData(label: label), if (data.isNotEmpty && width > 700) Padding( padding: EdgeInsets.only(bottom: withChart == false ? 16 : 0), child: Row( @@ -321,4 +310,38 @@ class _ItemsList extends StatelessWidget { )).toList() ); } +} + +class _NoData extends StatelessWidget { + final String label; + + const _NoData({ + required this.label + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Text( + label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 24), + Text( + AppLocalizations.of(context)!.noDataThisSection, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 16), + ], + ); + } } \ No newline at end of file From 44d7da9977af0956cd5a39a62080e4651dab8aab Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 Jan 2024 20:39:42 +0100 Subject: [PATCH 510/676] Added statistics settings --- lib/l10n/app_en.arb | 11 +- lib/l10n/app_es.arb | 11 +- lib/models/statistics_config.dart | 23 ++ .../app_logs/app_log_details_modal.dart | 194 ---------- lib/screens/settings/app_logs/app_logs.dart | 81 ----- .../logs_settings/config_widgets.dart | 111 +----- .../settings/logs_settings/logs_settings.dart | 5 +- lib/screens/settings/settings.dart | 31 +- .../statistics_settings.dart | 338 ++++++++++++++++++ lib/services/api_client.dart | 35 ++ lib/widgets/custom_settings_tile.dart | 4 +- lib/widgets/load_status_widgets.dart | 76 ++++ lib/widgets/master_switch.dart | 52 +++ 13 files changed, 579 insertions(+), 393 deletions(-) create mode 100644 lib/models/statistics_config.dart delete mode 100644 lib/screens/settings/app_logs/app_log_details_modal.dart delete mode 100644 lib/screens/settings/app_logs/app_logs.dart create mode 100644 lib/screens/settings/statistics_settings/statistics_settings.dart create mode 100644 lib/widgets/load_status_widgets.dart create mode 100644 lib/widgets/master_switch.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 723c08a..bdd9f99 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -749,5 +749,14 @@ "noBlockingScheduleThisDevice": "There's no blocking schedule for this device.", "selectTimezone": "Select a timezone", "selectClientsFiltersInfo": "Select the clients you want to display. If no clients are selected, all will be displayed.", - "noDataThisSection": "There's no data for this section." + "noDataThisSection": "There's no data for this section.", + "statisticsSettings": "Statistics settings", + "statisticsSettingsDescription": "Configure data collection for statistics", + "loadingStatisticsSettings": "Loading statistics settings...", + "statisticsSettingsLoadError": "An error occured when loading statistics settings.", + "customTimeInHours": "Custom time (in hours)", + "invalidTime": "Invalid time", + "removeDomain": "Remove domain", + "addDomain": "Add domain", + "notLess1Hour": "Time cannot be less than 1 hour" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 837d9d7..d9b2f9a 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -749,5 +749,14 @@ "noBlockingScheduleThisDevice": "No hay programación de bloqueo para este dispositivo.", "selectTimezone": "Selecciona una zona horaria", "selectClientsFiltersInfo": "Selecciona los clientes que quieres mostrar. Si no hay clientes seleccionados, se mostrarán todos.", - "noDataThisSection": "No hay datos para esta sección." + "noDataThisSection": "No hay datos para esta sección.", + "statisticsSettings": "Ajustes de estadísticas", + "statisticsSettingsDescription": "Configura la recolección de datos para estadísticas", + "loadingStatisticsSettings": "Cargando ajustes de estadísticas...", + "statisticsSettingsLoadError": "Ocurrió un error al cargar los ajustes de estadísticas.", + "customTimeInHours": "Tiempo personalizado (en horas)", + "invalidTime": "Tiempo no válido", + "removeDomain": "Eliminar dominio", + "addDomain": "Añadir dominio", + "notLess1Hour": "El tiempo no puede ser inferior a 1 hora" } \ No newline at end of file diff --git a/lib/models/statistics_config.dart b/lib/models/statistics_config.dart new file mode 100644 index 0000000..f504708 --- /dev/null +++ b/lib/models/statistics_config.dart @@ -0,0 +1,23 @@ +class StatisticsConfig { + final List? ignored; + final int? interval; + final bool? enabled; + + StatisticsConfig({ + this.ignored, + this.interval, + this.enabled, + }); + + factory StatisticsConfig.fromJson(Map json) => StatisticsConfig( + ignored: json["ignored"] == null ? [] : List.from(json["ignored"]!.map((x) => x)), + interval: json["interval"], + enabled: json["enabled"], + ); + + Map toJson() => { + "ignored": ignored == null ? [] : List.from(ignored!.map((x) => x)), + "interval": interval, + "enabled": enabled, + }; +} diff --git a/lib/screens/settings/app_logs/app_log_details_modal.dart b/lib/screens/settings/app_logs/app_log_details_modal.dart deleted file mode 100644 index 26d07f2..0000000 --- a/lib/screens/settings/app_logs/app_log_details_modal.dart +++ /dev/null @@ -1,194 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/models/app_log.dart'; - -class AppLogDetailsModal extends StatefulWidget { - final AppLog log; - - const AppLogDetailsModal({ - Key? key, - required this.log - }) : super(key: key); - - @override - State createState() => _AppLogDetailsModalState(); -} - -class _AppLogDetailsModalState extends State { - String valueToShow = 'message'; - - String generateBody() { - switch (valueToShow) { - case 'message': - return widget.log.message; - - case 'statusCode': - return widget.log.statusCode != null - ? widget.log.statusCode.toString() - : "[NO STAUS CODE]"; - - case 'body': - return widget.log.resBody != null - ? widget.log.resBody.toString() - : "[NO RESPONSE BODY]"; - - default: - return ''; - } - } - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: Column( - children: [ - Icon( - Icons.description_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor, - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.logDetails, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - scrollable: true, - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 20), - Row( - children: [ - Material( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(15), - bottomLeft: Radius.circular(15) - ), - color: Colors.transparent, - child: InkWell( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(15), - bottomLeft: Radius.circular(15) - ), - onTap: () => setState(() => valueToShow = 'message'), - child: AnimatedContainer( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(15), - bottomLeft: Radius.circular(15) - ), - border: Border.all( - color: Theme.of(context).colorScheme.primary - ), - color: valueToShow == 'message' - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.primary.withOpacity(0.05) - ), - child: Text( - "Message", - style: TextStyle( - color: valueToShow == 'message' - ? Colors.white - : null - ), - ), - ), - ), - ), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => setState(() => valueToShow = 'statusCode'), - child: AnimatedContainer( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, - decoration: BoxDecoration( - border: Border( - top: BorderSide( - color: Theme.of(context).colorScheme.primary - ), - bottom: BorderSide( - color: Theme.of(context).colorScheme.primary - ), - ), - color: valueToShow == 'statusCode' - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.primary.withOpacity(0.05) - ), - child: Text( - "Status code", - style: TextStyle( - color: valueToShow == 'statusCode' - ? Colors.white - : null - ), - ), - ), - ), - ), - Material( - borderRadius: const BorderRadius.only( - topRight: Radius.circular(15), - bottomRight: Radius.circular(15) - ), - color: Colors.transparent, - child: InkWell( - borderRadius: const BorderRadius.only( - topRight: Radius.circular(15), - bottomRight: Radius.circular(15) - ), - onTap: () => setState(() => valueToShow = 'body'), - child: AnimatedContainer( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topRight: Radius.circular(15), - bottomRight: Radius.circular(15) - ), - border: Border.all( - color: Theme.of(context).colorScheme.primary - ), - color: valueToShow == 'body' - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.primary.withOpacity(0.05) - ), - child: Text( - "Body", - style: TextStyle( - color: valueToShow == 'body' - ? Colors.white - : null - ), - ), - ), - ), - ), - ], - ), - const SizedBox(height: 20), - Text(generateBody()) - ], - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text("Close") - ) - ], - ); - } -} \ No newline at end of file diff --git a/lib/screens/settings/app_logs/app_logs.dart b/lib/screens/settings/app_logs/app_logs.dart deleted file mode 100644 index 19a8502..0000000 --- a/lib/screens/settings/app_logs/app_logs.dart +++ /dev/null @@ -1,81 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'dart:convert'; - -import 'package:adguard_home_manager/functions/copy_clipboard.dart'; -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/settings/app_logs/app_log_details_modal.dart'; - -import 'package:adguard_home_manager/providers/app_config_provider.dart'; - -class AppLogs extends StatelessWidget { - const AppLogs({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final appConfigProvider = Provider.of(context); - - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.logs), - actions: [ - IconButton( - onPressed: appConfigProvider.logs.isNotEmpty - ? () => copyToClipboard( - value: jsonEncode(appConfigProvider.logs.map((log) => log.toMap()).toList()), - successMessage: AppLocalizations.of(context)!.logsCopiedClipboard - ) - : null, - icon: const Icon(Icons.share), - tooltip: AppLocalizations.of(context)!.copyLogsClipboard, - ), - const SizedBox(width: 10), - ], - ), - body: appConfigProvider.logs.isNotEmpty - ? ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: appConfigProvider.logs.length, - itemBuilder: (context, index) => ListTile( - title: Text( - appConfigProvider.logs[index].message, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface - ), - ), - subtitle: Text( - appConfigProvider.logs[index].dateTime.toString(), - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context).listTileTheme.textColor - ), - ), - trailing: Text(appConfigProvider.logs[index].type), - onTap: () => { - showDialog( - context: context, - builder: (context) => AppLogDetailsModal( - log: appConfigProvider.logs[index] - ) - ) - }, - ) - ) - : Center( - child: Text( - AppLocalizations.of(context)!.noSavedLogs, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ) - ); - } -} \ No newline at end of file diff --git a/lib/screens/settings/logs_settings/config_widgets.dart b/lib/screens/settings/logs_settings/config_widgets.dart index 4dbaee7..5896a2b 100644 --- a/lib/screens/settings/logs_settings/config_widgets.dart +++ b/lib/screens/settings/logs_settings/config_widgets.dart @@ -4,6 +4,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/logs_settings/logs_settings.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; +import 'package:adguard_home_manager/widgets/master_switch.dart'; import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; class LogsConfigOptions extends StatelessWidget { @@ -70,48 +71,21 @@ class LogsConfigOptions extends StatelessWidget { return ListView( children: [ const SizedBox(height: 16), - 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: () => updateGeneralSwitch(!generalSwitch), - borderRadius: BorderRadius.circular(28), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 8 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - AppLocalizations.of(context)!.enableLog, - style: const TextStyle( - fontSize: 18, - ), - ), - Switch( - value: generalSwitch, - onChanged: updateGeneralSwitch, - ) - ], - ), - ), - ), - ), + MasterSwitch( + label: AppLocalizations.of(context)!.enableLog, + value: generalSwitch, + onChange: updateGeneralSwitch ), const SizedBox(height: 16), CustomCheckboxListTile( value: anonymizeClientIp, onChanged: (_) => updateAnonymizeClientIp(!anonymizeClientIp), title: AppLocalizations.of(context)!.anonymizeClientIp, - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), ), const SizedBox(height: 16), Padding( - padding: const EdgeInsets.symmetric(horizontal: 22), + padding: const EdgeInsets.symmetric(horizontal: 16), child: DropdownButtonFormField( items: retentionItems.asMap().entries.map((item) => DropdownMenuItem( value: item.value, @@ -137,10 +111,10 @@ class LogsConfigOptions extends StatelessWidget { children: [ SectionLabel( label: AppLocalizations.of(context)!.ignoredDomains, - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 0), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 0), ), Padding( - padding: const EdgeInsets.only(right: 10), + padding: const EdgeInsets.only(right: 6), child: IconButton( onPressed: () => updateIgnoredDomainsControllers([ ...ignoredDomainsControllers, @@ -158,7 +132,7 @@ class LogsConfigOptions extends StatelessWidget { ), if (ignoredDomainsControllers.isNotEmpty) ...ignoredDomainsControllers.map((controller) => Padding( padding: const EdgeInsets.only( - top: 12, bottom: 12, left: 24, right: 10 + top: 12, bottom: 12, left: 16, right: 6 ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -210,69 +184,4 @@ class LogsConfigOptions extends StatelessWidget { ], ); } -} - -class ConfigLogsLoading extends StatelessWidget { - const ConfigLogsLoading({super.key}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(24), - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.loadingLogsSettings, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ) - ], - ), - ), - ); - } -} - -class ConfigLogsError extends StatelessWidget { - const ConfigLogsError({super.key}); - - @override - Widget build(BuildContext context) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.logSettingsNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ) - ], - ), - ); - } } \ No newline at end of file diff --git a/lib/screens/settings/logs_settings/logs_settings.dart b/lib/screens/settings/logs_settings/logs_settings.dart index 8c651e0..cd723c7 100644 --- a/lib/screens/settings/logs_settings/logs_settings.dart +++ b/lib/screens/settings/logs_settings/logs_settings.dart @@ -4,6 +4,7 @@ import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/logs_settings/config_widgets.dart'; +import 'package:adguard_home_manager/widgets/load_status_widgets.dart'; import 'package:adguard_home_manager/models/querylog_config.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; @@ -182,7 +183,7 @@ class _LogsSettingsState extends State { builder: (context) { switch (loadStatus) { case LoadStatus.loading: - return const ConfigLogsLoading(); + return LoadingData(text: AppLocalizations.of(context)!.loadingLogsSettings); case LoadStatus.loaded: return LogsConfigOptions( @@ -200,7 +201,7 @@ class _LogsSettingsState extends State { ); case LoadStatus.error: - return const ConfigLogsError(); + return ErrorLoadData(text: AppLocalizations.of(context)!.logSettingsNotLoaded,); default: return const SizedBox(); diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 0e5256d..c9b7151 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -12,6 +12,7 @@ import 'package:adguard_home_manager/screens/settings/logs_settings/logs_setting import 'package:adguard_home_manager/screens/settings/access_settings/access_settings.dart'; import 'package:adguard_home_manager/screens/settings/customization/customization.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp.dart'; +import 'package:adguard_home_manager/screens/settings/statistics_settings/statistics_settings.dart'; import 'package:adguard_home_manager/screens/settings/safe_search_settings.dart'; import 'package:adguard_home_manager/screens/settings/update_server/update.dart'; import 'package:adguard_home_manager/screens/settings/dns/dns.dart'; @@ -148,11 +149,19 @@ class _SettingsWidgetState extends State<_SettingsWidget> { screenToNavigate: const LogsSettings(), twoColumns: widget.twoColumns, ), + _SettingsTile( + icon: Icons.analytics_rounded, + title: AppLocalizations.of(context)!.statisticsSettings, + subtitle: AppLocalizations.of(context)!.statisticsSettingsDescription, + thisItem: 2, + screenToNavigate: const StatisticsSettings(), + twoColumns: widget.twoColumns, + ), _SettingsTile( icon: Icons.lock_rounded, title: AppLocalizations.of(context)!.accessSettings, subtitle: AppLocalizations.of(context)!.accessSettingsDescription, - thisItem: 2, + thisItem: 3, screenToNavigate: const AccessSettings(), twoColumns: widget.twoColumns, ), @@ -160,7 +169,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.install_desktop_rounded, title: AppLocalizations.of(context)!.dhcpSettings, subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, - thisItem: 3, + thisItem: 4, screenToNavigate: const DhcpScreen(), twoColumns: widget.twoColumns, ), @@ -168,7 +177,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.dns_rounded, title: AppLocalizations.of(context)!.dnsSettings, subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, - thisItem: 4, + thisItem: 5, screenToNavigate: DnsSettings( splitView: widget.twoColumns, ), @@ -178,7 +187,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.security_rounded, title: AppLocalizations.of(context)!.encryptionSettings, subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, - thisItem: 5, + thisItem: 6, screenToNavigate: const EncryptionSettings(), twoColumns: widget.twoColumns, ), @@ -186,7 +195,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.route_rounded, title: AppLocalizations.of(context)!.dnsRewrites, subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, - thisItem: 6, + thisItem: 7, screenToNavigate: const DnsRewritesScreen(), twoColumns: widget.twoColumns, ), @@ -206,7 +215,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { ), ) : null, - thisItem: 7, + thisItem: 8, screenToNavigate: const UpdateScreen(), twoColumns: widget.twoColumns, ), @@ -214,7 +223,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.info_rounded, title: AppLocalizations.of(context)!.serverInformation, subtitle: AppLocalizations.of(context)!.serverInformationDescription, - thisItem: 8, + thisItem: 9, screenToNavigate: const ServerInformation(), twoColumns: widget.twoColumns, ), @@ -224,7 +233,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.palette_rounded, title: AppLocalizations.of(context)!.customization, subtitle: AppLocalizations.of(context)!.customizationDescription, - thisItem: 9, + thisItem: 10, screenToNavigate: const Customization(), twoColumns: widget.twoColumns, ), @@ -236,7 +245,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" : AppLocalizations.of(context)!.noServerSelected, - thisItem: 10, + thisItem: 11, screenToNavigate: const Servers(), twoColumns: widget.twoColumns, ), @@ -244,7 +253,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.settings, title: AppLocalizations.of(context)!.generalSettings, subtitle: AppLocalizations.of(context)!.generalSettingsDescription, - thisItem: 11, + thisItem: 12, screenToNavigate: GeneralSettings(splitView: widget.twoColumns), twoColumns: widget.twoColumns, ), @@ -252,7 +261,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { icon: Icons.build_outlined, title: AppLocalizations.of(context)!.advancedSettings, subtitle: AppLocalizations.of(context)!.advancedSetupDescription, - thisItem: 12, + thisItem: 13, screenToNavigate: const AdvancedSettings(), twoColumns: widget.twoColumns, ), diff --git a/lib/screens/settings/statistics_settings/statistics_settings.dart b/lib/screens/settings/statistics_settings/statistics_settings.dart new file mode 100644 index 0000000..f514e78 --- /dev/null +++ b/lib/screens/settings/statistics_settings/statistics_settings.dart @@ -0,0 +1,338 @@ +import 'package:flutter/material.dart'; +import 'package:uuid/uuid.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/settings/logs_settings/logs_settings.dart'; +import 'package:adguard_home_manager/widgets/load_status_widgets.dart'; +import 'package:adguard_home_manager/widgets/section_label.dart'; +import 'package:adguard_home_manager/widgets/master_switch.dart'; + +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/models/statistics_config.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; + +class StatisticsSettings extends StatefulWidget { + const StatisticsSettings({super.key}); + + @override + State createState() => _StatisticsSettingsState(); +} + +class _StatisticsSettingsState extends State { + final Uuid uuid = const Uuid(); + LoadStatus _loadStatus = LoadStatus.loading; + bool _generalSwitch = false; + final List _retentionItems = [ + "custom", + "86400000", + "604800000", + "2592000000", + "7776000000" + ]; + final _customTimeController = TextEditingController(); + String? _customTimeError; + String? _retentionTime; + List _ignoredDomainsControllers = []; + + void loadData() async { + final serversProvider = Provider.of(context, listen: false); + + final result = await serversProvider.apiClient2!.getStatisticsConfig(); + + if (!mounted) return; + if (result.successful == true) { + final data = result.content as StatisticsConfig; + setState(() { + _generalSwitch = data.enabled ?? false; + if (_retentionItems.contains(data.interval.toString())) { + _retentionTime = data.interval.toString(); + } + else if (data.interval != null) { + _retentionTime = "custom"; + _customTimeController.text = Duration(milliseconds: data.interval!).inHours.toString(); + } + if (data.ignored != null) { + _ignoredDomainsControllers = data.ignored!.map((e) => DomainListItemController( + id: uuid.v4(), + controller: TextEditingController(text: e), + error: false + )).toList(); + } + _loadStatus = LoadStatus.loaded; + }); + } + else { + setState(() => _loadStatus = LoadStatus.error); + } + } + + @override + void initState() { + loadData(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + final List dropdownItemTranslation = [ + AppLocalizations.of(context)!.custom, + AppLocalizations.of(context)!.hours24, + AppLocalizations.of(context)!.days7, + AppLocalizations.of(context)!.days30, + AppLocalizations.of(context)!.days90, + ]; + + + void validateDomain(String value, String id) { + final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); + bool error = false; + if (domainRegex.hasMatch(value)) { + error = false; + } + else { + error = true; + } + setState(() { + _ignoredDomainsControllers = _ignoredDomainsControllers.map((entry) { + if (entry.id != id) return entry; + return DomainListItemController( + id: id, + controller: entry.controller, + error: error + ); + }).toList(); + }); + } + + void validateCustomTime(String v) { + try { + final regex = RegExp(r'^\d+$'); + final parsed = int.parse(v); + if (!regex.hasMatch(v)) { + setState(() => _customTimeError = AppLocalizations.of(context)!.invalidTime); + } + else if (parsed < 1) { + setState(() => _customTimeError = AppLocalizations.of(context)!.notLess1Hour); + } + else { + setState(() => _customTimeError = null); + } + } catch (_) { + setState(() => _customTimeError = AppLocalizations.of(context)!.invalidTime); + } + } + + void updateConfig() async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.updatingSettings); + + final result = await serversProvider.apiClient2!.updateStatisticsSettings( + body: { + "enabled": _generalSwitch, + "interval": _retentionTime == "custom" + ? Duration(hours: int.parse(_customTimeController.text)).inMilliseconds + : int.parse(_retentionTime!), + "ignored": _ignoredDomainsControllers.map((e) => e.controller.text).toList() + } + ); + + processModal.close(); + + if (!mounted) return; + + if (result.successful == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsConfigUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.logsConfigNotUpdated, + color: Colors.red + ); + } + } + + final validValues = _ignoredDomainsControllers.where( + (d) => d.controller.text == "" || d.error == true + ).isEmpty && + (_retentionTime != "custom" || + (_retentionTime == "custom" && _customTimeController.text != "" && _customTimeError == null)); + + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.statisticsSettings), + actions: [ + IconButton( + onPressed: validValues ? () => updateConfig() : null, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 8) + ], + ), + body: Builder( + builder: (context) { + switch (_loadStatus) { + case LoadStatus.loading: + return LoadingData(text: AppLocalizations.of(context)!.loadingStatisticsSettings); + + case LoadStatus.loaded: + return ListView( + children: [ + const SizedBox(height: 8), + MasterSwitch( + label: AppLocalizations.of(context)!.enableLog, + value: _generalSwitch, + onChange: (v) => setState(() => _generalSwitch = v) + ), + const SizedBox(height: 24), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: DropdownButtonFormField( + items: _retentionItems.asMap().entries.map((item) => DropdownMenuItem( + value: item.value, + child: Text(dropdownItemTranslation[item.key]), + )).toList(), + value: _retentionTime, + onChanged: (value) => setState(() { + if (value != null && value != "custom") { + _customTimeError = null; + _customTimeController.text = ""; + }; + _retentionTime = value; + }), + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + label: Text(AppLocalizations.of(context)!.retentionTime) + ), + borderRadius: BorderRadius.circular(20), + ), + ), + if (_retentionTime == "custom") Padding( + padding: const EdgeInsets.only( + left: 16, + right: 16, + top: 24 + ), + child: TextFormField( + controller: _customTimeController, + onChanged: validateCustomTime, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.schedule_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.customTimeInHours, + errorText: _customTimeError + ), + keyboardType: TextInputType.number, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SectionLabel( + label: AppLocalizations.of(context)!.ignoredDomains, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 0), + ), + Padding( + padding: const EdgeInsets.only(right: 6), + child: IconButton( + onPressed: () => setState(() => _ignoredDomainsControllers = [ + ..._ignoredDomainsControllers, + DomainListItemController( + id: uuid.v4(), + controller: TextEditingController(), + error: false + ), + ]), + icon: const Icon(Icons.add), + tooltip: AppLocalizations.of(context)!.addDomain, + ), + ) + ], + ), + ), + if (_ignoredDomainsControllers.isNotEmpty) ..._ignoredDomainsControllers.map((controller) => Padding( + padding: const EdgeInsets.only( + top: 12, bottom: 12, left: 16, right: 6 + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: TextFormField( + controller: controller.controller, + onChanged: (v) => validateDomain(v, controller.id), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.domain, + errorText: controller.error + ? AppLocalizations.of(context)!.invalidDomain + : null + ), + ), + ), + const SizedBox(width: 12), + Padding( + padding: controller.error + ? const EdgeInsets.only(bottom: 24) + : const EdgeInsets.all(0), + child: IconButton( + onPressed: () => setState(() => _ignoredDomainsControllers = _ignoredDomainsControllers.where((e) => e.id != controller.id).toList()), + icon: const Icon(Icons.remove_circle_outline_outlined), + tooltip: AppLocalizations.of(context)!.removeDomain, + ), + ) + ], + ), + )), + if (_ignoredDomainsControllers.isEmpty) Container( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Text( + AppLocalizations.of(context)!.noIgnoredDomainsAdded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ], + ); + + case LoadStatus.error: + return ErrorLoadData(text: AppLocalizations.of(context)!.statisticsSettingsLoadError); + + default: + return const SizedBox(); + } + }, + ), + ); + } +} \ No newline at end of file diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index 0abb737..4f8ba90 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -4,6 +4,7 @@ import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/models/querylog_config.dart'; +import 'package:adguard_home_manager/models/statistics_config.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/encryption.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; @@ -881,4 +882,38 @@ class ApiClientV2 { content: result.body != null ? jsonDecode(result.body!) : null ); } + + Future getStatisticsConfig() async { + final result = await HttpRequestClient.get(urlPath: '/stats/config', server: server); + if (result.successful) { + try { + return ApiResponse( + successful: true, + content: StatisticsConfig.fromJson(jsonDecode(result.body!)) + ); + } catch (e, stackTrace) { + Sentry.captureException( + e, + stackTrace: stackTrace, + hint: Hint.withMap({ "statusCode": result.statusCode.toString() }) + ); + return const ApiResponse(successful: false); + } + } + else { + return const ApiResponse(successful: false); + } + } + + Future updateStatisticsSettings({ + required Map body + }) async { + final result = await HttpRequestClient.put( + urlPath: '/stats/config/update', + server: server, + body: body + ); + print(result.body); + return ApiResponse(successful: result.successful); + } } \ No newline at end of file diff --git a/lib/widgets/custom_settings_tile.dart b/lib/widgets/custom_settings_tile.dart index 554f13b..824b710 100644 --- a/lib/widgets/custom_settings_tile.dart +++ b/lib/widgets/custom_settings_tile.dart @@ -12,7 +12,7 @@ class CustomSettingsTile extends StatelessWidget { final int? selectedItem; const CustomSettingsTile({ - Key? key, + super.key, required this.title, this.subtitle, this.subtitleWidget, @@ -22,7 +22,7 @@ class CustomSettingsTile extends StatelessWidget { this.padding, required this.thisItem, required this.selectedItem, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/load_status_widgets.dart b/lib/widgets/load_status_widgets.dart new file mode 100644 index 0000000..2b1e699 --- /dev/null +++ b/lib/widgets/load_status_widgets.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; + +class LoadingData extends StatelessWidget { + final String text; + + const LoadingData({ + super.key, + required this.text, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(24), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + text, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), + ), + ); + } +} + +class ErrorLoadData extends StatelessWidget { + final String text; + + const ErrorLoadData({ + super.key, + required this.text + }); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + text, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/master_switch.dart b/lib/widgets/master_switch.dart new file mode 100644 index 0000000..323de68 --- /dev/null +++ b/lib/widgets/master_switch.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +class MasterSwitch extends StatelessWidget { + final String label; + final bool value; + final void Function(bool) onChange; + final EdgeInsets? margin; + + const MasterSwitch({ + super.key, + required this.label, + required this.value, + required this.onChange, + this.margin + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: margin ?? const EdgeInsets.symmetric(horizontal: 16), + child: Material( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: () => onChange(!value), + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 8 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + label, + style: const TextStyle( + fontSize: 18, + ), + ), + Switch( + value: value, + onChanged: onChange, + ) + ], + ), + ), + ), + ), + ); + } +} \ No newline at end of file From 246d14151a84ae8b705f05a91193ff635c759903 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 28 Jan 2024 20:42:26 +0100 Subject: [PATCH 511/676] Fix home top items type --- lib/screens/home/top_items/top_items_section.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/home/top_items/top_items_section.dart b/lib/screens/home/top_items/top_items_section.dart index 5749f5d..708a3d0 100644 --- a/lib/screens/home/top_items/top_items_section.dart +++ b/lib/screens/home/top_items/top_items_section.dart @@ -92,9 +92,9 @@ class TopItemsSection extends StatelessWidget { final List> lineChartData = lineData(); final mapData = lineChartData.map((e) => e["value"]); - final List total = mapData.isNotEmpty + final double total = mapData.isNotEmpty ? mapData.reduce((a, b) => a + b) - : []; + : 0; return SizedBox( child: Column( From 0d5aeaba42ef3e93afce9963dfaf06c14b89d49d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 Jan 2024 00:21:52 +0100 Subject: [PATCH 512/676] Fix --- lib/screens/filters/add_button.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 7dd4d8c..dc652bc 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -39,6 +39,7 @@ class AddFiltersButton extends StatelessWidget { processModal.close(); + if (!context.mounted) return; if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, From 58bba7f1df5f9e681270dfefb4ea6eaf975b74f1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 Jan 2024 00:22:00 +0100 Subject: [PATCH 513/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index e95f496..dc2f6d3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.15.0-beta.3+123 +version: 2.15.0-beta.4+124 environment: sdk: '>=2.18.1 <3.0.0' From 2f95173d22e3a77bd159234f52925519911cf210 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 Jan 2024 01:50:06 +0100 Subject: [PATCH 514/676] Updated libraries --- pubspec.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 1cb21ba..6e0a19e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -213,10 +213,10 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: fe6fec7d85975a99c73b9515a69a6e291364accfa0e4a5b3ce6de814d74b9a1c + sha256: b5e2b0f13d93f8c532b5a2786bfb44580de1f50b927bf95813fa1af617e9caf8 url: "https://pub.dev" source: hosted - version: "0.66.0" + version: "0.66.1" flutter: dependency: "direct main" description: flutter @@ -279,10 +279,10 @@ packages: dependency: "direct dev" description: name: flutter_native_splash - sha256: "9cdb5d9665dab5d098dc50feab74301c2c228cd02ca25c9b546ab572cebcd6af" + sha256: "558f10070f03ee71f850a78f7136ab239a67636a294a44a06b6b7345178edb1e" url: "https://pub.dev" source: hosted - version: "2.3.9" + version: "2.3.10" flutter_reorderable_list: dependency: "direct main" description: @@ -338,10 +338,10 @@ packages: dependency: "direct main" description: name: http - sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.0" http_parser: dependency: transitive description: @@ -402,10 +402,10 @@ packages: dependency: "direct main" description: name: markdown - sha256: acf35edccc0463a9d7384e437c015a3535772e09714cf60e07eeef3a15870dcd + sha256: "1b134d9f8ff2da15cb298efe6cd8b7d2a78958c1b00384ebcbdf13fe340a6c90" url: "https://pub.dev" source: hosted - version: "7.1.1" + version: "7.2.1" matcher: dependency: transitive description: @@ -530,18 +530,18 @@ packages: dependency: transitive description: name: sentry - sha256: "89e426587b0879e53c46a0aae0eb312696d9d2d803ba14b252a65cc24b1416a2" + sha256: "5686ed515bb620dc52b4ae99a6586fe720d443591183cf1f620ec5d1f0eec100" url: "https://pub.dev" source: hosted - version: "7.14.0" + version: "7.15.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: fd089ee4e75a927be037c56815a0a54af5a519f52b803a5ffecb589bb36e2401 + sha256: "505dec3b6810562785d2c34ae871c73ff2cba6cf436c32c188f0464df226ba8f" url: "https://pub.dev" source: hosted - version: "7.14.0" + version: "7.15.0" sky_engine: dependency: transitive description: flutter @@ -567,18 +567,18 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.2" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "76db4d324c8cbb16ca5b60ad2f3d25cec953107c93ae65aafa480d3e6fb69f14" + sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" url: "https://pub.dev" source: hosted - version: "2.5.2-1" + version: "2.5.3" sqflite_common_ffi: dependency: "direct main" description: @@ -599,10 +599,10 @@ packages: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: "3e3583b77cf888a68eae2e49ee4f025f66b86623ef0d83c297c8d903daa14871" + sha256: "90963b515721d6a71e96f438175cf43c979493ed14822860a300b69694c74eb6" url: "https://pub.dev" source: hosted - version: "0.5.18" + version: "0.5.19+1" stack_trace: dependency: transitive description: @@ -687,10 +687,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: d25bb0ca00432a5e1ee40e69c36c85863addf7cc45e433769d61bed3fe81fd96 + sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c url: "https://pub.dev" source: hosted - version: "6.2.3" + version: "6.2.4" url_launcher_android: dependency: transitive description: From 406f7c832f09266b5d6a55f3ada2e48a98a95762 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 Jan 2024 02:36:46 +0100 Subject: [PATCH 515/676] Change android gradle --- android/app/build.gradle | 17 +++++++---------- android/build.gradle | 13 ------------- android/settings.gradle | 31 +++++++++++++++++++++++-------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 099c059..8ab520c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,3 +1,9 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) { } } -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' @@ -21,10 +22,6 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { @@ -80,5 +77,5 @@ flutter { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.20" } diff --git a/android/build.gradle b/android/build.gradle index 09b245a..bc157bd 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,16 +1,3 @@ -buildscript { - ext.kotlin_version = '1.8.20' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.2.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - allprojects { repositories { google() diff --git a/android/settings.gradle b/android/settings.gradle index 44e62bc..eeb0d0e 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,11 +1,26 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.2.2" apply false + id "org.jetbrains.kotlin.android" version "1.8.20" apply false +} + +include ":app" From a4e8694cc16fb3a7beccb3e622feed1d3ffe9703 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 Jan 2024 02:37:45 +0100 Subject: [PATCH 516/676] Changed url launcher library --- README.md | 1 - ios/Podfile.lock | 63 +++++------- lib/functions/open_url.dart | 33 +++---- linux/flutter/generated_plugin_registrant.cc | 4 - linux/flutter/generated_plugins.cmake | 1 - macos/Flutter/GeneratedPluginRegistrant.swift | 2 - pubspec.lock | 96 ++++++++----------- pubspec.yaml | 3 +- .../flutter/generated_plugin_registrant.cc | 3 - windows/flutter/generated_plugins.cmake | 1 - windows/innosetup_installer_builder.iss | 1 - 11 files changed, 79 insertions(+), 129 deletions(-) diff --git a/README.md b/README.md index fb9505d..a03478d 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,6 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [dynamic color](https://pub.dev/packages/dynamic_color) - [device info](https://pub.dev/packages/device_info) - [fl chart](https://pub.dev/packages/fl_chart) -- [flutter web browser](https://pub.dev/packages/flutter_web_browser) - [flutter svg](https://pub.dev/packages/flutter_svg) - [percent indicator](https://pub.dev/packages/percent_indicator) - [store checker](https://pub.dev/packages/store_checker) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 7faf3b4..2c2d827 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2,60 +2,53 @@ PODS: - device_info_plus (0.0.1): - Flutter - Flutter (1.0.0) + - flutter_custom_tabs_ios (2.0.0): + - Flutter - flutter_native_splash (0.0.1): - Flutter - - flutter_web_browser (0.17.1): - - Flutter - - FMDB (2.7.5): - - FMDB/standard (= 2.7.5) - - FMDB/standard (2.7.5) - package_info_plus (0.4.5): - Flutter - - Sentry/HybridSDK (8.17.2): - - SentryPrivate (= 8.17.2) + - Sentry/HybridSDK (8.18.0): + - SentryPrivate (= 8.18.0) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.17.2) - - SentryPrivate (8.17.2) + - Sentry/HybridSDK (= 8.18.0) + - SentryPrivate (8.18.0) - sqflite (0.0.3): - Flutter - - FMDB (>= 2.7.5) - - sqlite3 (3.44.0): - - sqlite3/common (= 3.44.0) - - sqlite3/common (3.44.0) - - sqlite3/fts5 (3.44.0): + - FlutterMacOS + - sqlite3 (3.45.0): + - sqlite3/common (= 3.45.0) + - sqlite3/common (3.45.0) + - sqlite3/fts5 (3.45.0): - sqlite3/common - - sqlite3/perf-threadsafe (3.44.0): + - sqlite3/perf-threadsafe (3.45.0): - sqlite3/common - - sqlite3/rtree (3.44.0): + - sqlite3/rtree (3.45.0): - sqlite3/common - sqlite3_flutter_libs (0.0.1): - Flutter - - sqlite3 (~> 3.44.0) + - sqlite3 (~> 3.45.0) - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree - store_checker (0.0.1): - Flutter - - url_launcher_ios (0.0.1): - - Flutter DEPENDENCIES: - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - Flutter (from `Flutter`) + - flutter_custom_tabs_ios (from `.symlinks/plugins/flutter_custom_tabs_ios/ios`) - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - - flutter_web_browser (from `.symlinks/plugins/flutter_web_browser/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`) - - sqflite (from `.symlinks/plugins/sqflite/ios`) + - sqflite (from `.symlinks/plugins/sqflite/darwin`) - sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`) - store_checker (from `.symlinks/plugins/store_checker/ios`) - - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) SPEC REPOS: trunk: - - FMDB - Sentry - SentryPrivate - sqlite3 @@ -65,38 +58,34 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/device_info_plus/ios" Flutter: :path: Flutter + flutter_custom_tabs_ios: + :path: ".symlinks/plugins/flutter_custom_tabs_ios/ios" flutter_native_splash: :path: ".symlinks/plugins/flutter_native_splash/ios" - flutter_web_browser: - :path: ".symlinks/plugins/flutter_web_browser/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" sentry_flutter: :path: ".symlinks/plugins/sentry_flutter/ios" sqflite: - :path: ".symlinks/plugins/sqflite/ios" + :path: ".symlinks/plugins/sqflite/darwin" sqlite3_flutter_libs: :path: ".symlinks/plugins/sqlite3_flutter_libs/ios" store_checker: :path: ".symlinks/plugins/store_checker/ios" - url_launcher_ios: - :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_custom_tabs_ios: 62439c843b2691aae516fd50119a01eb9755fff7 flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef - flutter_web_browser: 7bccaafbb0c5b8862afe7bcd158f15557109f61f - FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 - Sentry: 64a9f9c3637af913adcf53deced05bbe452d1410 - sentry_flutter: 57912cf425e09398bdf47f38842a1fcb9836f1be - SentryPrivate: 024c6fed507ac39ae98e6d087034160f942920d5 - sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a - sqlite3: 6e2d4a4879854d0ec86b476bf3c3e30870bac273 - sqlite3_flutter_libs: eb769059df0356dc52ddda040f09cacc9391a7cf + Sentry: 8984a4ffb2b9bd2894d74fb36e6f5833865bc18e + sentry_flutter: c87a0556eeb6cbf7f9f924d30e878bdedf22d364 + SentryPrivate: 2f0c9ba4c3fc993f70eab6ca95673509561e0085 + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec + sqlite3: f307b6291c4db7b5086c38d6237446b98a738581 + sqlite3_flutter_libs: aeb4d37509853dfa79d9b59386a2dac5dd079428 store_checker: 359c5051d9ec30ff0a8fa39eb5ec9df021bb745d - url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011 diff --git a/lib/functions/open_url.dart b/lib/functions/open_url.dart index b435e47..48b168f 100644 --- a/lib/functions/open_url.dart +++ b/lib/functions/open_url.dart @@ -1,30 +1,21 @@ -import 'dart:io'; - -import 'package:flutter_web_browser/flutter_web_browser.dart'; -import 'package:url_launcher/url_launcher.dart'; +import 'package:flutter_custom_tabs/flutter_custom_tabs.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; void openUrl(String url) async { - if (Platform.isAndroid || Platform.isIOS) { - FlutterWebBrowser.openWebPage( - url: url, + try { + await launchUrl( + Uri.parse(url), customTabsOptions: const CustomTabsOptions( - instantAppsEnabled: true, + shareState: CustomTabsShareState.browserDefault, + urlBarHidingEnabled: true, showTitle: true, - urlBarHidingEnabled: false, - ), + ), safariVCOptions: const SafariViewControllerOptions( barCollapsingEnabled: true, - dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, - modalPresentationCapturesStatusBarAppearance: true, - ) + dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, + ), ); - } - else { - final uri = Uri.parse(url); - if (await canLaunchUrl(uri)) { - await launchUrl(uri); - } else { - throw 'Could not launch $url'; - } + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); } } \ No newline at end of file diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 1786709..cfc2a43 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -9,7 +9,6 @@ #include #include #include -#include #include void fl_register_plugins(FlPluginRegistry* registry) { @@ -22,9 +21,6 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); - g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); - url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); g_autoptr(FlPluginRegistrar) window_size_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin"); window_size_plugin_register_with_registrar(window_size_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 59ac090..b5d8a41 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -6,7 +6,6 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color sentry_flutter sqlite3_flutter_libs - url_launcher_linux window_size ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 31a4f66..b20cdf0 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -11,7 +11,6 @@ import package_info_plus import sentry_flutter import sqflite import sqlite3_flutter_libs -import url_launcher_macos import window_size func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { @@ -21,6 +20,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) - UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 6e0a19e..907bae7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -222,6 +222,46 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_custom_tabs: + dependency: "direct main" + description: + name: flutter_custom_tabs + sha256: "961fe962ae55e9e41097c34e68c6d7d2de10e9a71034f83834919e31a891e728" + url: "https://pub.dev" + source: hosted + version: "2.0.0+1" + flutter_custom_tabs_android: + dependency: transitive + description: + name: flutter_custom_tabs_android + sha256: "5701a3e38117dfc59e5fa9e84a29eea9203e0062de7be56d1f775845c34456d9" + url: "https://pub.dev" + source: hosted + version: "2.0.0+1" + flutter_custom_tabs_ios: + dependency: transitive + description: + name: flutter_custom_tabs_ios + sha256: b29f687f7f366159d37347f888369fcd1259adac8ca6c7f07d356a80b091e08a + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_custom_tabs_platform_interface: + dependency: transitive + description: + name: flutter_custom_tabs_platform_interface + sha256: "13531a743486695d87b462b151801e11476b1b5a15274caec092420cc1943064" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_custom_tabs_web: + dependency: transitive + description: + name: flutter_custom_tabs_web + sha256: "3114b511d3942ed42c502cc57ad47eaef9622ac06dd036e2b21b19d8876f6498" + url: "https://pub.dev" + source: hosted + version: "2.0.0" flutter_displaymode: dependency: "direct main" description: @@ -313,14 +353,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_web_browser: - dependency: "direct main" - description: - name: flutter_web_browser - sha256: a5564b736253f745e147b8c4eff86de436324d081974cc1f16bff881134a400f - url: "https://pub.dev" - source: hosted - version: "0.17.1" flutter_web_plugins: dependency: transitive description: flutter @@ -683,46 +715,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" - url_launcher: - dependency: "direct main" - description: - name: url_launcher - sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c - url: "https://pub.dev" - source: hosted - version: "6.2.4" - url_launcher_android: - dependency: transitive - description: - name: url_launcher_android - sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" - url: "https://pub.dev" - source: hosted - version: "6.2.2" - url_launcher_ios: - dependency: transitive - description: - name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" - url: "https://pub.dev" - source: hosted - version: "6.2.4" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 - url: "https://pub.dev" - source: hosted - version: "3.1.1" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 - url: "https://pub.dev" - source: hosted - version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: @@ -739,14 +731,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.3" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 - url: "https://pub.dev" - source: hosted - version: "3.1.1" uuid: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index dc2f6d3..9b4f395 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,7 +49,6 @@ dependencies: uuid: ^4.2.1 expandable: ^5.0.1 fl_chart: ^0.66.0 - flutter_web_browser: ^0.17.1 flutter_svg: ^2.0.9 percent_indicator: ^4.2.3 store_checker: ^1.4.0 @@ -67,7 +66,6 @@ dependencies: git: url: https://github.com/JGeek00/flutter_split_view ref: master-alt - url_launcher: ^6.2.2 contextmenu: ^3.0.0 async: ^2.11.0 sentry_flutter: ^7.13.2 @@ -77,6 +75,7 @@ dependencies: segmented_button_slide: ^1.0.4 http: ^1.1.2 timezone: ^0.9.2 + flutter_custom_tabs: ^2.0.0+1 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 50bb1c8..932f245 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -9,7 +9,6 @@ #include #include #include -#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -19,8 +18,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("SentryFlutterPlugin")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); - UrlLauncherWindowsRegisterWithRegistrar( - registry->GetRegistrarForPlugin("UrlLauncherWindows")); WindowSizePluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("WindowSizePlugin")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 71f5fcf..e7261c3 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -6,7 +6,6 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color sentry_flutter sqlite3_flutter_libs - url_launcher_windows window_size ) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 92a4b72..b25de17 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -43,7 +43,6 @@ Source: "..\build\windows\x64\runner\Release\flutter_windows.dll"; DestDir: "{ap Source: "..\build\windows\x64\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\x64\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\window_size_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files From 02b9bd034faec025bb7723abdb7007b34b785acc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 Jan 2024 15:04:52 +0100 Subject: [PATCH 517/676] Fixed duplicated snackbar desktop --- lib/functions/snackbar.dart | 8 +- lib/screens/settings/settings.dart | 390 +++++++++++++++-------------- macos/Podfile.lock | 53 ++-- 3 files changed, 223 insertions(+), 228 deletions(-) diff --git a/lib/functions/snackbar.dart b/lib/functions/snackbar.dart index 123ef3f..b332fcd 100644 --- a/lib/functions/snackbar.dart +++ b/lib/functions/snackbar.dart @@ -9,10 +9,12 @@ void showSnacbkar({ required AppConfigProvider appConfigProvider, required String label, required Color color, - Color? labelColor + Color? labelColor, + GlobalKey? key, }) async { + final GlobalKey scaffoldKey = key ?? scaffoldMessengerKey; if (appConfigProvider.showingSnackbar == true) { - scaffoldMessengerKey.currentState?.clearSnackBars(); + scaffoldKey.currentState?.clearSnackBars(); await Future.delayed(const Duration(milliseconds: 500)); } appConfigProvider.setShowingSnackbar(true); @@ -26,7 +28,7 @@ void showSnacbkar({ ), backgroundColor: color, ); - scaffoldMessengerKey.currentState?.showSnackBar(snackBar).closed.then( + scaffoldKey.currentState?.showSnackBar(snackBar).closed.then( (value) => appConfigProvider.setShowingSnackbar(false) ); } \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index c9b7151..92ea100 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:adguard_home_manager/config/globals.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -101,214 +102,217 @@ class _SettingsWidgetState extends State<_SettingsWidget> { appConfigProvider.setSelectedSettingsScreen(screen: null); } - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - surfaceTintColor: isDesktop(width) ? Colors.transparent : null, - title: Text(AppLocalizations.of(context)!.settings), + return ScaffoldMessenger( + key: widget.twoColumns ? GlobalKey() : null, + child: Scaffold( + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, + title: Text(AppLocalizations.of(context)!.settings), + ) ) - ) - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverList.list( - children: [ - if ( - serversProvider.selectedServer != null && - statusProvider.serverStatus != null && - serversProvider.apiClient2 != null - ) ...[ - SectionLabel(label: AppLocalizations.of(context)!.serverSettings), - _SettingsTile( - icon: Icons.search_rounded, - title: AppLocalizations.of(context)!.safeSearch, - subtitle: AppLocalizations.of(context)!.safeSearchSettings, - thisItem: 0, - screenToNavigate: const SafeSearchSettingsScreen(), - twoColumns: widget.twoColumns, - ), - _SettingsTile( - icon: Icons.list_alt_rounded, - title: AppLocalizations.of(context)!.logsSettings, - subtitle: AppLocalizations.of(context)!.logsSettingsDescription, - thisItem: 1, - screenToNavigate: const LogsSettings(), - twoColumns: widget.twoColumns, - ), - _SettingsTile( - icon: Icons.analytics_rounded, - title: AppLocalizations.of(context)!.statisticsSettings, - subtitle: AppLocalizations.of(context)!.statisticsSettingsDescription, - thisItem: 2, - screenToNavigate: const StatisticsSettings(), - twoColumns: widget.twoColumns, - ), - _SettingsTile( - icon: Icons.lock_rounded, - title: AppLocalizations.of(context)!.accessSettings, - subtitle: AppLocalizations.of(context)!.accessSettingsDescription, - thisItem: 3, - screenToNavigate: const AccessSettings(), - twoColumns: widget.twoColumns, - ), - _SettingsTile( - icon: Icons.install_desktop_rounded, - title: AppLocalizations.of(context)!.dhcpSettings, - subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, - thisItem: 4, - screenToNavigate: const DhcpScreen(), - twoColumns: widget.twoColumns, - ), - _SettingsTile( - icon: Icons.dns_rounded, - title: AppLocalizations.of(context)!.dnsSettings, - subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, - thisItem: 5, - screenToNavigate: DnsSettings( - splitView: widget.twoColumns, + ], + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + if ( + serversProvider.selectedServer != null && + statusProvider.serverStatus != null && + serversProvider.apiClient2 != null + ) ...[ + SectionLabel(label: AppLocalizations.of(context)!.serverSettings), + _SettingsTile( + icon: Icons.search_rounded, + title: AppLocalizations.of(context)!.safeSearch, + subtitle: AppLocalizations.of(context)!.safeSearchSettings, + thisItem: 0, + screenToNavigate: const SafeSearchSettingsScreen(), + twoColumns: widget.twoColumns, ), + _SettingsTile( + icon: Icons.list_alt_rounded, + title: AppLocalizations.of(context)!.logsSettings, + subtitle: AppLocalizations.of(context)!.logsSettingsDescription, + thisItem: 1, + screenToNavigate: const LogsSettings(), + twoColumns: widget.twoColumns, + ), + _SettingsTile( + icon: Icons.analytics_rounded, + title: AppLocalizations.of(context)!.statisticsSettings, + subtitle: AppLocalizations.of(context)!.statisticsSettingsDescription, + thisItem: 2, + screenToNavigate: const StatisticsSettings(), + twoColumns: widget.twoColumns, + ), + _SettingsTile( + icon: Icons.lock_rounded, + title: AppLocalizations.of(context)!.accessSettings, + subtitle: AppLocalizations.of(context)!.accessSettingsDescription, + thisItem: 3, + screenToNavigate: const AccessSettings(), + twoColumns: widget.twoColumns, + ), + _SettingsTile( + icon: Icons.install_desktop_rounded, + title: AppLocalizations.of(context)!.dhcpSettings, + subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, + thisItem: 4, + screenToNavigate: const DhcpScreen(), + twoColumns: widget.twoColumns, + ), + _SettingsTile( + icon: Icons.dns_rounded, + title: AppLocalizations.of(context)!.dnsSettings, + subtitle: AppLocalizations.of(context)!.dnsSettingsDescription, + thisItem: 5, + screenToNavigate: DnsSettings( + splitView: widget.twoColumns, + ), + twoColumns: widget.twoColumns, + ), + _SettingsTile( + icon: Icons.security_rounded, + title: AppLocalizations.of(context)!.encryptionSettings, + subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, + thisItem: 6, + screenToNavigate: const EncryptionSettings(), + twoColumns: widget.twoColumns, + ), + _SettingsTile( + icon: Icons.route_rounded, + title: AppLocalizations.of(context)!.dnsRewrites, + subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, + thisItem: 7, + screenToNavigate: const DnsRewritesScreen(), + twoColumns: widget.twoColumns, + ), + if (serversProvider.updateAvailable.data != null) _SettingsTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.updates, + subtitle: AppLocalizations.of(context)!.updatesDescription, + trailing: serversProvider.updateAvailable.data != null && + serversProvider.updateAvailable.data!.canAutoupdate == true + ? Container( + width: 10, + height: 10, + margin: const EdgeInsets.only(right: 12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.red + ), + ) + : null, + thisItem: 8, + screenToNavigate: const UpdateScreen(), + twoColumns: widget.twoColumns, + ), + _SettingsTile( + icon: Icons.info_rounded, + title: AppLocalizations.of(context)!.serverInformation, + subtitle: AppLocalizations.of(context)!.serverInformationDescription, + thisItem: 9, + screenToNavigate: const ServerInformation(), + twoColumns: widget.twoColumns, + ), + ], + SectionLabel(label: AppLocalizations.of(context)!.appSettings), + _SettingsTile( + icon: Icons.palette_rounded, + title: AppLocalizations.of(context)!.customization, + subtitle: AppLocalizations.of(context)!.customizationDescription, + thisItem: 10, + screenToNavigate: const Customization(), twoColumns: widget.twoColumns, ), _SettingsTile( - icon: Icons.security_rounded, - title: AppLocalizations.of(context)!.encryptionSettings, - subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, - thisItem: 6, - screenToNavigate: const EncryptionSettings(), + icon: Icons.storage_rounded, + title: AppLocalizations.of(context)!.servers, + subtitle: serversProvider.selectedServer != null + ? statusProvider.serverStatus != null + ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" + : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" + : AppLocalizations.of(context)!.noServerSelected, + thisItem: 11, + screenToNavigate: const Servers(), twoColumns: widget.twoColumns, ), _SettingsTile( - icon: Icons.route_rounded, - title: AppLocalizations.of(context)!.dnsRewrites, - subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, - thisItem: 7, - screenToNavigate: const DnsRewritesScreen(), - twoColumns: widget.twoColumns, - ), - if (serversProvider.updateAvailable.data != null) _SettingsTile( - icon: Icons.system_update_rounded, - title: AppLocalizations.of(context)!.updates, - subtitle: AppLocalizations.of(context)!.updatesDescription, - trailing: serversProvider.updateAvailable.data != null && - serversProvider.updateAvailable.data!.canAutoupdate == true - ? Container( - width: 10, - height: 10, - margin: const EdgeInsets.only(right: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.red - ), - ) - : null, - thisItem: 8, - screenToNavigate: const UpdateScreen(), + icon: Icons.settings, + title: AppLocalizations.of(context)!.generalSettings, + subtitle: AppLocalizations.of(context)!.generalSettingsDescription, + thisItem: 12, + screenToNavigate: GeneralSettings(splitView: widget.twoColumns), twoColumns: widget.twoColumns, ), _SettingsTile( - icon: Icons.info_rounded, - title: AppLocalizations.of(context)!.serverInformation, - subtitle: AppLocalizations.of(context)!.serverInformationDescription, - thisItem: 9, - screenToNavigate: const ServerInformation(), + icon: Icons.build_outlined, + title: AppLocalizations.of(context)!.advancedSettings, + subtitle: AppLocalizations.of(context)!.advancedSetupDescription, + thisItem: 13, + screenToNavigate: const AdvancedSettings(), twoColumns: widget.twoColumns, ), + SectionLabel(label: AppLocalizations.of(context)!.aboutApp), + CustomListTile( + title: AppLocalizations.of(context)!.appVersion, + subtitle: appConfigProvider.getAppInfo!.version, + ), + CustomListTile( + title: AppLocalizations.of(context)!.createdBy, + subtitle: Strings.createdBy, + ), + Padding( + padding: const EdgeInsets.all(15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if (Platform.isAndroid) IconButton( + onPressed: () => openUrl(Urls.playStore), + icon: SvgPicture.asset( + 'assets/resources/google-play.svg', + color: Theme.of(context).colorScheme.onSurfaceVariant, + width: 30, + height: 30, + ), + tooltip: AppLocalizations.of(context)!.visitGooglePlay, + ), + IconButton( + onPressed: () => openUrl(Urls.gitHub), + icon: SvgPicture.asset( + 'assets/resources/github.svg', + color: Theme.of(context).colorScheme.onSurfaceVariant, + width: 30, + height: 30, + ), + tooltip: AppLocalizations.of(context)!.gitHub, + ), + ], + ), + ) ], - SectionLabel(label: AppLocalizations.of(context)!.appSettings), - _SettingsTile( - icon: Icons.palette_rounded, - title: AppLocalizations.of(context)!.customization, - subtitle: AppLocalizations.of(context)!.customizationDescription, - thisItem: 10, - screenToNavigate: const Customization(), - twoColumns: widget.twoColumns, - ), - _SettingsTile( - icon: Icons.storage_rounded, - title: AppLocalizations.of(context)!.servers, - subtitle: serversProvider.selectedServer != null - ? statusProvider.serverStatus != null - ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" - : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" - : AppLocalizations.of(context)!.noServerSelected, - thisItem: 11, - screenToNavigate: const Servers(), - twoColumns: widget.twoColumns, - ), - _SettingsTile( - icon: Icons.settings, - title: AppLocalizations.of(context)!.generalSettings, - subtitle: AppLocalizations.of(context)!.generalSettingsDescription, - thisItem: 12, - screenToNavigate: GeneralSettings(splitView: widget.twoColumns), - twoColumns: widget.twoColumns, - ), - _SettingsTile( - icon: Icons.build_outlined, - title: AppLocalizations.of(context)!.advancedSettings, - subtitle: AppLocalizations.of(context)!.advancedSetupDescription, - thisItem: 13, - screenToNavigate: const AdvancedSettings(), - twoColumns: widget.twoColumns, - ), - SectionLabel(label: AppLocalizations.of(context)!.aboutApp), - CustomListTile( - title: AppLocalizations.of(context)!.appVersion, - subtitle: appConfigProvider.getAppInfo!.version, - ), - CustomListTile( - title: AppLocalizations.of(context)!.createdBy, - subtitle: Strings.createdBy, - ), - Padding( - padding: const EdgeInsets.all(15), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - if (Platform.isAndroid) IconButton( - onPressed: () => openUrl(Urls.playStore), - icon: SvgPicture.asset( - 'assets/resources/google-play.svg', - color: Theme.of(context).colorScheme.onSurfaceVariant, - width: 30, - height: 30, - ), - tooltip: AppLocalizations.of(context)!.visitGooglePlay, - ), - IconButton( - onPressed: () => openUrl(Urls.gitHub), - icon: SvgPicture.asset( - 'assets/resources/github.svg', - color: Theme.of(context).colorScheme.onSurfaceVariant, - width: 30, - height: 30, - ), - tooltip: AppLocalizations.of(context)!.gitHub, - ), - ], - ), - ) - ], - ) - ], - ) + ) + ], + ) + ), ), - ), - ) + ) + ), ); } } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 9d30918..9df518c 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -4,38 +4,33 @@ PODS: - dynamic_color (0.0.2): - FlutterMacOS - FlutterMacOS (1.0.0) - - FMDB (2.7.5): - - FMDB/standard (= 2.7.5) - - FMDB/standard (2.7.5) - package_info_plus (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.17.2): - - SentryPrivate (= 8.17.2) + - Sentry/HybridSDK (8.18.0): + - SentryPrivate (= 8.18.0) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.17.2) - - SentryPrivate (8.17.2) - - sqflite (0.0.2): + - Sentry/HybridSDK (= 8.18.0) + - SentryPrivate (8.18.0) + - sqflite (0.0.3): + - Flutter - FlutterMacOS - - FMDB (>= 2.7.5) - - sqlite3 (3.44.0): - - sqlite3/common (= 3.44.0) - - sqlite3/common (3.44.0) - - sqlite3/fts5 (3.44.0): + - sqlite3 (3.45.0): + - sqlite3/common (= 3.45.0) + - sqlite3/common (3.45.0) + - sqlite3/fts5 (3.45.0): - sqlite3/common - - sqlite3/perf-threadsafe (3.44.0): + - sqlite3/perf-threadsafe (3.45.0): - sqlite3/common - - sqlite3/rtree (3.44.0): + - sqlite3/rtree (3.45.0): - sqlite3/common - sqlite3_flutter_libs (0.0.1): - FlutterMacOS - - sqlite3 (~> 3.44.0) + - sqlite3 (~> 3.45.0) - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree - - url_launcher_macos (0.0.1): - - FlutterMacOS - window_size (0.0.2): - FlutterMacOS @@ -45,14 +40,12 @@ DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`) - - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) + - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) - - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`) SPEC REPOS: trunk: - - FMDB - Sentry - SentryPrivate - sqlite3 @@ -69,11 +62,9 @@ EXTERNAL SOURCES: sentry_flutter: :path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos sqflite: - :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos + :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin sqlite3_flutter_libs: :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos - url_launcher_macos: - :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos window_size: :path: Flutter/ephemeral/.symlinks/plugins/window_size/macos @@ -81,15 +72,13 @@ SPEC CHECKSUMS: device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - Sentry: 64a9f9c3637af913adcf53deced05bbe452d1410 - sentry_flutter: 57912cf425e09398bdf47f38842a1fcb9836f1be - SentryPrivate: 024c6fed507ac39ae98e6d087034160f942920d5 - sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea - sqlite3: 6e2d4a4879854d0ec86b476bf3c3e30870bac273 - sqlite3_flutter_libs: a25f3a0f522fdcd8fef6a4a50a3d681dd43d8dea - url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 + Sentry: 8984a4ffb2b9bd2894d74fb36e6f5833865bc18e + sentry_flutter: c87a0556eeb6cbf7f9f924d30e878bdedf22d364 + SentryPrivate: 2f0c9ba4c3fc993f70eab6ca95673509561e0085 + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec + sqlite3: f307b6291c4db7b5086c38d6237446b98a738581 + sqlite3_flutter_libs: 6b9913d8fbb718e5ebf23658aa6934a0fb509c0f window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 From 340ef4f00efad8d6199ab055b2b9ec4a04d3a308 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 Jan 2024 15:05:12 +0100 Subject: [PATCH 518/676] Removed unused imports --- lib/screens/settings/settings.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 92ea100..e16a84e 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:adguard_home_manager/config/globals.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_svg/flutter_svg.dart'; From d92d755381a6d7c58db48827b050b36c1189139b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 Jan 2024 16:09:07 +0100 Subject: [PATCH 519/676] Changed url launcher --- README.md | 2 + lib/functions/open_url.dart | 44 ++++++++++------- lib/screens/home/appbar.dart | 3 +- linux/flutter/generated_plugin_registrant.cc | 4 ++ linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile.lock | 6 +++ pubspec.lock | 48 +++++++++++++++++++ pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 ++ windows/flutter/generated_plugins.cmake | 1 + windows/innosetup_installer_builder.iss | 1 + 12 files changed, 99 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index a03478d..93788ac 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,8 @@ On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a - [pie chart](https://pub.dev/packages/pie_chart) - [segmented button slide](https://pub.dev/packages/segmented_button_slide) - [timezone](https://pub.dev/packages/timezone) +- [url launcher](https://pub.dev/packages/url_launcher) +- [flutter custom tabs](https://pub.dev/packages/flutter_custom_tabs)
    diff --git a/lib/functions/open_url.dart b/lib/functions/open_url.dart index 48b168f..00cfc17 100644 --- a/lib/functions/open_url.dart +++ b/lib/functions/open_url.dart @@ -1,21 +1,33 @@ -import 'package:flutter_custom_tabs/flutter_custom_tabs.dart'; +import 'dart:io'; + +import 'package:flutter_custom_tabs/flutter_custom_tabs.dart' as flutter_custom_tabs; +import 'package:url_launcher/url_launcher.dart' as url_launcher; import 'package:sentry_flutter/sentry_flutter.dart'; void openUrl(String url) async { - try { - await launchUrl( - Uri.parse(url), - customTabsOptions: const CustomTabsOptions( - shareState: CustomTabsShareState.browserDefault, - urlBarHidingEnabled: true, - showTitle: true, - ), - safariVCOptions: const SafariViewControllerOptions( - barCollapsingEnabled: true, - dismissButtonStyle: SafariViewControllerDismissButtonStyle.close, - ), - ); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); + if (Platform.isAndroid || Platform.isIOS) { + try { + await flutter_custom_tabs.launchUrl( + Uri.parse(url), + customTabsOptions: const flutter_custom_tabs.CustomTabsOptions( + shareState: flutter_custom_tabs.CustomTabsShareState.browserDefault, + urlBarHidingEnabled: true, + showTitle: true, + ), + safariVCOptions: const flutter_custom_tabs.SafariViewControllerOptions( + barCollapsingEnabled: true, + dismissButtonStyle: flutter_custom_tabs.SafariViewControllerDismissButtonStyle.close, + ), + ); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + } + } + else { + try { + url_launcher.launchUrl(Uri.parse(url)); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + } } } \ No newline at end of file diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 52ff350..5cd481f 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -151,7 +151,8 @@ class HomeAppBar extends StatelessWidget { ), ) ] - ) + ), + const SizedBox(width: 8), ], ); } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index cfc2a43..1786709 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { @@ -21,6 +22,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); g_autoptr(FlPluginRegistrar) window_size_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin"); window_size_plugin_register_with_registrar(window_size_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index b5d8a41..59ac090 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color sentry_flutter sqlite3_flutter_libs + url_launcher_linux window_size ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b20cdf0..31a4f66 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -11,6 +11,7 @@ import package_info_plus import sentry_flutter import sqflite import sqlite3_flutter_libs +import url_launcher_macos import window_size func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { @@ -20,5 +21,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin")) } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 9df518c..1bad97f 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -31,6 +31,8 @@ PODS: - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree + - url_launcher_macos (0.0.1): + - FlutterMacOS - window_size (0.0.2): - FlutterMacOS @@ -42,6 +44,7 @@ DEPENDENCIES: - sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) + - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`) SPEC REPOS: @@ -65,6 +68,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin sqlite3_flutter_libs: :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos + url_launcher_macos: + :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos window_size: :path: Flutter/ephemeral/.symlinks/plugins/window_size/macos @@ -79,6 +84,7 @@ SPEC CHECKSUMS: sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: f307b6291c4db7b5086c38d6237446b98a738581 sqlite3_flutter_libs: 6b9913d8fbb718e5ebf23658aa6934a0fb509c0f + url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 diff --git a/pubspec.lock b/pubspec.lock index 907bae7..d584bfa 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -715,6 +715,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c + url: "https://pub.dev" + source: hosted + version: "6.2.4" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" + url: "https://pub.dev" + source: hosted + version: "6.2.2" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + url: "https://pub.dev" + source: hosted + version: "6.2.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + url: "https://pub.dev" + source: hosted + version: "3.1.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 + url: "https://pub.dev" + source: hosted + version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: @@ -731,6 +771,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + url: "https://pub.dev" + source: hosted + version: "3.1.1" uuid: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 9b4f395..f4bf52e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -76,6 +76,7 @@ dependencies: http: ^1.1.2 timezone: ^0.9.2 flutter_custom_tabs: ^2.0.0+1 + url_launcher: ^6.2.4 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 932f245..50bb1c8 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -18,6 +19,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("SentryFlutterPlugin")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); WindowSizePluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("WindowSizePlugin")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index e7261c3..71f5fcf 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color sentry_flutter sqlite3_flutter_libs + url_launcher_windows window_size ) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index b25de17..92a4b72 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -43,6 +43,7 @@ Source: "..\build\windows\x64\runner\Release\flutter_windows.dll"; DestDir: "{ap Source: "..\build\windows\x64\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\window_size_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files From aed2500fa4ed84a68a0c5bca2330206b8ddcef49 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 29 Jan 2024 16:14:34 +0100 Subject: [PATCH 520/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index f4bf52e..2d64194 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.15.0-beta.4+124 +version: 2.15.0+125 environment: sdk: '>=2.18.1 <3.0.0' From 16f1d4664cb708a2922aab3b4a5c95b6c48d29cc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 30 Jan 2024 00:43:57 +0100 Subject: [PATCH 521/676] Fix logs filtering by client --- lib/models/applied_filters.dart | 2 +- lib/providers/logs_provider.dart | 16 ++++++++-------- lib/screens/home/top_items/top_items_lists.dart | 2 +- lib/screens/logs/logs_list_appbar.dart | 14 ++++++-------- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/lib/models/applied_filters.dart b/lib/models/applied_filters.dart index 2b60e71..f4ef1ee 100644 --- a/lib/models/applied_filters.dart +++ b/lib/models/applied_filters.dart @@ -1,7 +1,7 @@ class AppliedFiters { String selectedResultStatus = 'all'; String? searchText; - List? clients; + List clients; AppliedFiters({ required this.selectedResultStatus, diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index 63e81cd..cba46c0 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -30,7 +30,7 @@ class LogsProvider with ChangeNotifier { AppliedFiters _appliedFilters = AppliedFiters( selectedResultStatus: 'all', searchText: null, - clients: null + clients: [] ); LoadStatus get loadStatus { @@ -177,18 +177,18 @@ class LogsProvider with ChangeNotifier { if (loadingMore != null && loadingMore == true && logsData != null) { LogsData newLogsData = result.content; newLogsData.data = [...logsData!.data, ...(result.content as LogsData).data]; - if (appliedFilters.clients != null) { + if (appliedFilters.clients.isNotEmpty) { newLogsData.data = newLogsData.data.where( - (item) => appliedFilters.clients!.contains(item.client) + (item) => appliedFilters.clients.contains(item.client) ).toList(); } _logsData = newLogsData; } else { LogsData newLogsData = result.content; - if (appliedFilters.clients != null) { + if (appliedFilters.clients.isNotEmpty) { newLogsData.data = newLogsData.data.where( - (item) => appliedFilters.clients!.contains(item.client) + (item) => appliedFilters.clients.contains(item.client) ).toList(); } _logsData = newLogsData; @@ -217,7 +217,7 @@ class LogsProvider with ChangeNotifier { _appliedFilters = AppliedFiters( selectedResultStatus: 'all', searchText: null, - clients: null + clients: [] ); if (result.successful == true) { @@ -254,9 +254,9 @@ class LogsProvider with ChangeNotifier { if (result.successful == true) { LogsData newLogsData = result.content as LogsData; - if (appliedFilters.clients != null) { + if (appliedFilters.clients.isNotEmpty) { newLogsData.data = newLogsData.data.where( - (item) => appliedFilters.clients!.contains(item.client) + (item) => appliedFilters.clients.contains(item.client) ).toList(); } _logsData = newLogsData; diff --git a/lib/screens/home/top_items/top_items_lists.dart b/lib/screens/home/top_items/top_items_lists.dart index 758a0b6..7c24bd3 100644 --- a/lib/screens/home/top_items/top_items_lists.dart +++ b/lib/screens/home/top_items/top_items_lists.dart @@ -51,7 +51,7 @@ class TopItemsLists extends StatelessWidget { AppliedFiters( selectedResultStatus: 'all', searchText: value, - clients: null + clients: [] ) ); appConfigProvider.setSelectedScreen(2); diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 144a55e..01a870c 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -70,8 +70,6 @@ class LogsListAppBar extends StatelessWidget { forceElevated: innerBoxIsScrolled, surfaceTintColor: isDesktop(width) ? Colors.transparent : null, title: Text(AppLocalizations.of(context)!.logs), - expandedHeight: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null - ? 170 : null, actions: [ if (!(Platform.isAndroid || Platform.isIOS)) IconButton( onPressed: () => logsProvider.fetchLogs(inOffset: 0), @@ -87,7 +85,7 @@ class LogsListAppBar extends StatelessWidget { : const SizedBox(), const SizedBox(width: 5), ], - bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients != null + bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients.isNotEmpty ? PreferredSize( preferredSize: const Size(double.maxFinite, 70), child: Container( @@ -172,7 +170,7 @@ class LogsListAppBar extends StatelessWidget { }, ), ], - if (logsProvider.appliedFilters.clients != null) ...[ + if (logsProvider.appliedFilters.clients.isNotEmpty) ...[ const SizedBox(width: 15), Chip( avatar: const Icon( @@ -181,9 +179,9 @@ class LogsListAppBar extends StatelessWidget { label: Row( children: [ Text( - logsProvider.appliedFilters.clients!.length == 1 - ? logsProvider.appliedFilters.clients![0] - : "${logsProvider.appliedFilters.clients!.length} ${AppLocalizations.of(context)!.clients}", + logsProvider.appliedFilters.clients.length == 1 + ? logsProvider.appliedFilters.clients[0] + : "${logsProvider.appliedFilters.clients.length} ${AppLocalizations.of(context)!.clients}", ), ], ), @@ -196,7 +194,7 @@ class LogsListAppBar extends StatelessWidget { AppliedFiters( selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, searchText: logsProvider.appliedFilters.searchText, - clients: null + clients: [] ) ); logsProvider.setSelectedClients(null); From ae3e172033d71fe67ac39d9110ee7b78e45f249f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 30 Jan 2024 01:04:06 +0100 Subject: [PATCH 522/676] Changed response status bottom sheet --- .../logs/filters/filter_status_modal.dart | 244 ++++++++---------- .../logs/filters/logs_filters_modal.dart | 6 +- lib/widgets/list_bottom_sheet.dart | 14 +- 3 files changed, 122 insertions(+), 142 deletions(-) diff --git a/lib/screens/logs/filters/filter_status_modal.dart b/lib/screens/logs/filters/filter_status_modal.dart index c08d9a8..d4e4155 100644 --- a/lib/screens/logs/filters/filter_status_modal.dart +++ b/lib/screens/logs/filters/filter_status_modal.dart @@ -1,9 +1,11 @@ -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/widgets/list_bottom_sheet.dart'; + import 'package:adguard_home_manager/providers/logs_provider.dart'; class FilterStatusModal extends StatefulWidget { @@ -33,169 +35,141 @@ class _FilterStatusModalState extends State { Widget build(BuildContext context) { final logsProvider = Provider.of(context); - void apply() async { - logsProvider.setSelectedResultStatus(value: selectedResultStatus); - - Navigator.pop(context); - } - if (widget.dialog == true) { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( maxWidth: 400 ), - child: _Content( - onApply: apply, - updateSelectedResultStatus: (v) => setState(() => selectedResultStatus = v), - selectedResultStatus: selectedResultStatus, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Wrap( + children: [ + Padding( + padding: const EdgeInsets.only(top: 16, left: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + CloseButton( + onPressed: () => Navigator.pop(context), + ), + const SizedBox(width: 12), + Text( + AppLocalizations.of(context)!.responseStatus, + style: const TextStyle( + fontSize: 22 + ), + ) + ], + ), + ), + Container(height: 16), + _ItemsList( + selectedResultStatus: logsProvider.selectedResultStatus, + updateSelectedResultStatus: (v) => logsProvider.setSelectedResultStatus(value: v), + ), + Container(height: 16) + ], + ), + ), + ), + ], ) ), ); } else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28) - ), - color: Theme.of(context).dialogBackgroundColor + return SizedBox( + height: 700, + child: ListBottomSheet( + icon: Icons.shield_rounded, + title: AppLocalizations.of(context)!.responseStatus, + initialChildSize: 1, + minChildSize: 0.5, + children: [ + _ItemsList( + selectedResultStatus: logsProvider.selectedResultStatus, + updateSelectedResultStatus: (v) => logsProvider.setSelectedResultStatus(value: v), + ) + ] ), - child: SafeArea( - child: _Content( - onApply: apply, - updateSelectedResultStatus: (v) => setState(() => selectedResultStatus = v), - selectedResultStatus: selectedResultStatus, - ), - ) ); } } } -class _Content extends StatelessWidget { +class _ItemsList extends StatelessWidget { final String selectedResultStatus; final void Function(String) updateSelectedResultStatus; - final void Function() onApply; - const _Content({ + const _ItemsList({ required this.selectedResultStatus, - required this.updateSelectedResultStatus, - required this.onApply, + required this.updateSelectedResultStatus }); @override Widget build(BuildContext context) { return Column( - mainAxisSize: MainAxisSize.min, children: [ - Flexible( - child: SingleChildScrollView( - child: Wrap( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only( - top: 24, - bottom: 16, - ), - child: Icon( - Icons.shield_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - ), - Text( - AppLocalizations.of(context)!.responseStatus, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ) - ], - ), - Container(height: 16), - _Item( - selectedResultStatus: selectedResultStatus, - id: "all", - icon: Icons.shield_rounded, - label: AppLocalizations.of(context)!.all, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "filtered", - icon: Icons.shield_rounded, - label: AppLocalizations.of(context)!.filtered, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "processed", - icon: Icons.verified_user_rounded, - label: AppLocalizations.of(context)!.processedRow, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "whitelisted", - icon: Icons.verified_user_rounded, - label: AppLocalizations.of(context)!.processedWhitelistRow, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "blocked", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blocked, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "blocked_safebrowsing", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedSafeBrowsingRow, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "blocked_parental", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedParentalRow, - onChanged: updateSelectedResultStatus - ), - _Item( - selectedResultStatus: selectedResultStatus, - id: "safe_search", - icon: Icons.gpp_bad_rounded, - label: AppLocalizations.of(context)!.blockedSafeSearchRow, - onChanged: updateSelectedResultStatus - ), - ], - ), - ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "all", + icon: Icons.shield_rounded, + label: AppLocalizations.of(context)!.all, + onChanged: updateSelectedResultStatus ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: onApply, - child: Text(AppLocalizations.of(context)!.apply) - ) - ], - ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "filtered", + icon: Icons.shield_rounded, + label: AppLocalizations.of(context)!.filtered, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "processed", + icon: Icons.verified_user_rounded, + label: AppLocalizations.of(context)!.processedRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "whitelisted", + icon: Icons.verified_user_rounded, + label: AppLocalizations.of(context)!.processedWhitelistRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "blocked", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blocked, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "blocked_safebrowsing", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedSafeBrowsingRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "blocked_parental", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedParentalRow, + onChanged: updateSelectedResultStatus + ), + _Item( + selectedResultStatus: selectedResultStatus, + id: "safe_search", + icon: Icons.gpp_bad_rounded, + label: AppLocalizations.of(context)!.blockedSafeSearchRow, + onChanged: updateSelectedResultStatus ), - if (Platform.isIOS) const SizedBox(height: 16) ], ); } diff --git a/lib/screens/logs/filters/logs_filters_modal.dart b/lib/screens/logs/filters/logs_filters_modal.dart index 9f77666..b02dbd2 100644 --- a/lib/screens/logs/filters/logs_filters_modal.dart +++ b/lib/screens/logs/filters/logs_filters_modal.dart @@ -82,10 +82,9 @@ class _FiltersList extends StatelessWidget { final void Function() onClearSearch; const _FiltersList({ - Key? key, required this.searchController, required this.onClearSearch, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -125,7 +124,8 @@ class _FiltersList extends StatelessWidget { dialog: false, ), isScrollControlled: true, - backgroundColor: Colors.transparent + backgroundColor: Colors.transparent, + useSafeArea: true ); } } diff --git a/lib/widgets/list_bottom_sheet.dart b/lib/widgets/list_bottom_sheet.dart index 2f8bd03..219df8c 100644 --- a/lib/widgets/list_bottom_sheet.dart +++ b/lib/widgets/list_bottom_sheet.dart @@ -4,12 +4,18 @@ class ListBottomSheet extends StatelessWidget { final IconData icon; final String title; final List children; + final double? initialChildSize; + final double? minChildSize; + final double? maxChildSize; const ListBottomSheet({ super.key, required this.icon, required this.title, - required this.children + required this.children, + this.initialChildSize, + this.maxChildSize, + this.minChildSize, }); @override @@ -17,9 +23,9 @@ class ListBottomSheet extends StatelessWidget { return GestureDetector( onTap: () => Navigator.of(context).pop(), child: DraggableScrollableSheet( - initialChildSize: 0.6, - minChildSize: 0.3, - maxChildSize: 1, + initialChildSize: initialChildSize ?? 0.6, + minChildSize: minChildSize ?? 0.3, + maxChildSize: maxChildSize ?? 1, builder: (context, controller) { return Container( decoration: BoxDecoration( From 3eaf7143f28d61fc66fe5fa7a70c62528ef42ef1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 30 Jan 2024 01:06:08 +0100 Subject: [PATCH 523/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 2d64194..aa5c383 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.15.0+125 +version: 2.15.1+126 environment: sdk: '>=2.18.1 <3.0.0' From 794b690c916ada19669e29b4022b47a6eeda94a6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 2 Feb 2024 20:37:27 +0100 Subject: [PATCH 524/676] Save settings on shared preferences --- lib/main.dart | 92 +++--- lib/providers/app_config_provider.dart | 230 ++++++--------- .../settings/customization/customization.dart | 16 +- lib/services/db/database.dart | 270 +----------------- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 96 +++++++ pubspec.yaml | 1 + 7 files changed, 242 insertions(+), 465 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index e6fb4ec..98669e6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'package:dynamic_color/dynamic_color.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:store_checker/store_checker.dart'; import 'package:window_size/window_size.dart'; @@ -31,8 +32,8 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/colors.dart'; import 'package:adguard_home_manager/config/globals.dart'; import 'package:adguard_home_manager/config/theme.dart'; -import 'package:adguard_home_manager/classes/http_override.dart'; import 'package:adguard_home_manager/services/db/database.dart'; +import 'package:adguard_home_manager/classes/http_override.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -48,8 +49,12 @@ void main() async { } await dotenv.load(fileName: '.env'); + + final sharedPreferences = await SharedPreferences.getInstance(); - final AppConfigProvider appConfigProvider = AppConfigProvider(); + final AppConfigProvider appConfigProvider = AppConfigProvider( + sharedPreferencesInstance: sharedPreferences + ); final ServersProvider serversProvider = ServersProvider(); final StatusProvider statusProvider = StatusProvider(); final ClientsProvider clientsProvider = ClientsProvider(); @@ -69,9 +74,7 @@ void main() async { appConfigProvider.setIosInfo(iosInfo); } - final dbData = await loadDb(appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31); - - if (dbData['appConfig']['overrideSslCheck'] == 1) { + if (sharedPreferences.getBool('overrideSslCheck') == true) { HttpOverrides.global = MyHttpOverrides(); } @@ -80,10 +83,12 @@ void main() async { appConfigProvider.setInstallationSource(installationSource); } + final dbData = await loadDb(); serversProvider.setDbInstance(dbData['dbInstance']); - appConfigProvider.saveFromDb(dbData['dbInstance'], dbData['appConfig']); serversProvider.saveFromDb(dbData['servers']); + appConfigProvider.saveFromSharedPreferences(); + PackageInfo appInfo = await PackageInfo.fromPlatform(); appConfigProvider.setAppInfo(appInfo); @@ -208,42 +213,45 @@ class _MainState extends State

    { final appConfigProvider = Provider.of(context); return DynamicColorBuilder( - builder: (lightDynamic, darkDynamic) => MaterialApp( - title: 'AdGuard Home Manager', - theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? lightTheme(lightDynamic) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]), - darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? darkTheme(darkDynamic) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]), - themeMode: appConfigProvider.selectedTheme, - debugShowCheckedModeBanner: false, - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - AppLocalizations.delegate, - ], - supportedLocales: const [ - Locale('en', ''), - Locale('es', ''), - Locale('zh', ''), - Locale('zh', 'CN'), - Locale('pl', ''), - Locale('tr', ''), - Locale('ru', '') - ], - scaffoldMessengerKey: scaffoldMessengerKey, - navigatorKey: globalNavigatorKey, - builder: (context, child) => CustomMenuBar( - child: child!, - ), - home: const Layout(), - ), + builder: (lightDynamic, darkDynamic) { + appConfigProvider.setSupportsDynamicTheme(lightDynamic != null && darkDynamic != null); + return MaterialApp( + title: 'AdGuard Home Manager', + theme: lightDynamic != null + ? appConfigProvider.useDynamicColor == true + ? lightTheme(lightDynamic) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]), + darkTheme: darkDynamic != null + ? appConfigProvider.useDynamicColor == true + ? darkTheme(darkDynamic) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]), + themeMode: appConfigProvider.selectedTheme, + debugShowCheckedModeBanner: false, + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + AppLocalizations.delegate, + ], + supportedLocales: const [ + Locale('en', ''), + Locale('es', ''), + Locale('zh', ''), + Locale('zh', 'CN'), + Locale('pl', ''), + Locale('tr', ''), + Locale('ru', '') + ], + scaffoldMessengerKey: scaffoldMessengerKey, + navigatorKey: globalNavigatorKey, + builder: (context, child) => CustomMenuBar( + child: child!, + ), + home: const Layout(), + ); + } ); } } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 99e2f0f..6b73520 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -1,22 +1,23 @@ -import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/scheduler.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:store_checker/store_checker.dart'; import 'package:package_info_plus/package_info_plus.dart'; -import 'package:sqflite/sqlite_api.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/config/home_top_items_default_order.dart'; import 'package:adguard_home_manager/models/github_release.dart'; -import 'package:adguard_home_manager/services/db/queries.dart'; -import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/models/app_log.dart'; class AppConfigProvider with ChangeNotifier { - Database? _dbInstance; + final SharedPreferences sharedPreferencesInstance; + + AppConfigProvider({ + required this.sharedPreferencesInstance + }); PackageInfo? _appInfo; AndroidDeviceInfo? _androidDeviceInfo; @@ -28,6 +29,7 @@ class AppConfigProvider with ChangeNotifier { bool _showingSnackbar = false; + bool _supportsDynamicTheme = true; int _selectedTheme = 0; bool _useDynamicColor = true; int _staticColor = 0; @@ -38,19 +40,19 @@ class AppConfigProvider with ChangeNotifier { List _homeTopItemsOrder = homeTopItemsDefaultOrder; - int _hideServerAddress = 0; + bool _hideServerAddress = false; final List _logs = []; - int _overrideSslCheck = 0; + bool _overrideSslCheck = false; - int _hideZeroValues = 0; + bool _hideZeroValues = false; - int _showTimeLogs = 0; + bool _showTimeLogs = false; - int _showIpLogs = 0; + bool _showIpLogs = false; - int _combinedChartHome = 0; + bool _combinedChartHome = false; String? _doNotRememberVersion; @@ -88,6 +90,10 @@ class AppConfigProvider with ChangeNotifier { } } + bool get supportsDynamicTheme { + return _supportsDynamicTheme; + } + int get selectedThemeNumber { return _selectedTheme; } @@ -105,11 +111,11 @@ class AppConfigProvider with ChangeNotifier { } bool get overrideSslCheck { - return _overrideSslCheck == 1 ? true : false; + return _overrideSslCheck; } bool get hideZeroValues { - return _hideZeroValues == 1 ? true : false; + return _hideZeroValues; } int get selectedScreen { @@ -133,15 +139,15 @@ class AppConfigProvider with ChangeNotifier { } bool get showTimeLogs { - return _showTimeLogs == 1 ? true : false; + return _showTimeLogs; } bool get showIpLogs { - return _showIpLogs == 1 ? true : false; + return _showIpLogs; } bool get combinedChartHome { - return _combinedChartHome == 1 ? true : false; + return _combinedChartHome; } String? get doNotRememberVersion { @@ -165,11 +171,11 @@ class AppConfigProvider with ChangeNotifier { } bool get hideServerAddress { - return _hideServerAddress == 1 ? true : false; + return _hideServerAddress; } - void setDbInstance(Database db) { - _dbInstance = db; + void setSupportsDynamicTheme(bool value) { + _supportsDynamicTheme = value; } void setAppInfo(PackageInfo appInfo) { @@ -227,206 +233,145 @@ class AppConfigProvider with ChangeNotifier { } Future setOverrideSslCheck(bool status) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'overrideSslCheck', - value: status == true ? 1 : 0 - ); - if (updated == true) { - _overrideSslCheck = status == true ? 1 : 0; + try { + sharedPreferencesInstance.setBool('overrideSslCheck', status); + _overrideSslCheck = status; notifyListeners(); return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setHideZeroValues(bool status) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'hideZeroValues', - value: status == true ? 1 : 0 - ); - if (updated == true) { - _hideZeroValues = status == true ? 1 : 0; + try { + sharedPreferencesInstance.setBool('hideZeroValues', status); + _hideZeroValues = status; notifyListeners(); return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setshowTimeLogs(bool status) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'showTimeLogs', - value: status == true ? 1 : 0 - ); - if (updated == true) { - _showTimeLogs = status == true ? 1 : 0; + try { + sharedPreferencesInstance.setBool('showTimeLogs', status); + _showTimeLogs = status; notifyListeners(); return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setShowIpLogs(bool status) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'showIpLogs', - value: status == true ? 1 : 0 - ); - if (updated == true) { - _showIpLogs = status == true ? 1 : 0; + try { + sharedPreferencesInstance.setBool('showIpLogs', status); + _showIpLogs = status; notifyListeners(); return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setSelectedTheme(int value) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'theme', - value: value - ); - if (updated == true) { + try { + sharedPreferencesInstance.setInt('selectedTheme', value); _selectedTheme = value; notifyListeners(); return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setUseDynamicColor(bool value) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'useDynamicColor', - value: value == true ? 1 : 0 - ); - if (updated == true) { + try { + sharedPreferencesInstance.setBool('useDynamicColor', value); _useDynamicColor = value; notifyListeners(); return true; - } - else { - return false; - } - } - - Future setUseThemeColorForStatus(bool value) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'useThemeColorForStatus', - value: value == true ? 1 : 0 - ); - if (updated == true) { - _useThemeColorForStatus = value; - notifyListeners(); - return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setCombinedChartHome(bool value) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'combinedChart', - value: value == true ? 1 : 0 - ); - if (updated == true) { - _combinedChartHome = value == true ? 1 : 0; + try { + sharedPreferencesInstance.setBool('combinedChart', value); + _combinedChartHome = value; notifyListeners(); return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setStaticColor(int value) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'staticColor', - value: value - ); - if (updated == true) { + try { + sharedPreferencesInstance.setInt('staticColor', value); _staticColor = value; notifyListeners(); return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setHomeTopItemsOrder(List order) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'homeTopItemsOrder', - value: jsonEncode(List.from(order.map((e) => e.name))) - ); - if (updated == true) { + try { + sharedPreferencesInstance.setStringList('homeTopItemsOrder', List.from(order.map((e) => e.name))); _homeTopItemsOrder = order; notifyListeners(); return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setHideServerAddress(bool value) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'hideServerAddress', - value: value == true ? 1 : 0 - ); - if (updated == true) { - _hideServerAddress = value == true ? 1 : 0; + try { + sharedPreferencesInstance.setBool('hideServerAddress', value); + _hideServerAddress = value; notifyListeners(); return true; - } - else { + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); return false; } } Future setDoNotRememberVersion(String value) async { - final updated = await updateConfigQuery( - db: _dbInstance!, - column: 'doNotRememberVersion', - value: value - ); + final updated = await sharedPreferencesInstance.setString('hideServerAddress', value); return updated; } - - void saveFromDb(Database dbInstance, Map dbData) { - _selectedTheme = dbData['theme'] ?? 0; - _overrideSslCheck = dbData['overrideSslCheck'] ?? 0; - _hideZeroValues = dbData['hideZeroValues']; - _useDynamicColor = convertFromIntToBool(dbData['useDynamicColor'])!; - _staticColor = dbData['staticColor'] ?? 0; - _useThemeColorForStatus = dbData['useThemeColorForStatus'] != null ? convertFromIntToBool(dbData['useThemeColorForStatus'])! : false; - _showTimeLogs = dbData['showTimeLogs'] ?? 0; - _doNotRememberVersion = dbData['doNotRememberVersion']; - _showIpLogs = dbData['showIpLogs'] ?? 0; - _combinedChartHome = dbData['combinedChart'] ?? 0; - _hideServerAddress = dbData['hideServerAddress']; - if (dbData['homeTopItemsOrder'] != null) { + + void saveFromSharedPreferences() { + _selectedTheme = sharedPreferencesInstance.getInt('selectedTheme') ?? 0; + _overrideSslCheck = sharedPreferencesInstance.getBool('overrideSslCheck') ?? false; + _hideZeroValues = sharedPreferencesInstance.getBool('hideZeroValues') ?? false; + _useDynamicColor = sharedPreferencesInstance.getBool('useDynamicColor') ?? true; + _staticColor = sharedPreferencesInstance.getInt('staticColor') ?? 0; + _showTimeLogs = sharedPreferencesInstance.getBool('showTimeLogs') ?? false; + _doNotRememberVersion = sharedPreferencesInstance.getString('doNotRememberVersion'); + _showIpLogs = sharedPreferencesInstance.getBool('showIpLogs') ?? false; + _combinedChartHome = sharedPreferencesInstance.getBool('combinedChart') ?? false; + _hideServerAddress = sharedPreferencesInstance.getBool('hideServerAddress') ?? false; + if (sharedPreferencesInstance.getStringList('homeTopItemsOrder') != null) { try { final itemsOrder = List.from( - List.from(jsonDecode(dbData['homeTopItemsOrder'])).map((e) { + List.from(sharedPreferencesInstance.getStringList('homeTopItemsOrder')!).map((e) { switch (e) { case 'queriedDomains': return HomeTopItems.queriedDomains; @@ -458,8 +403,5 @@ class AppConfigProvider with ChangeNotifier { _homeTopItemsOrder = homeTopItemsDefaultOrder; } } - - _dbInstance = dbInstance; - notifyListeners(); } } \ No newline at end of file diff --git a/lib/screens/settings/customization/customization.dart b/lib/screens/settings/customization/customization.dart index 7bec949..38f93a3 100644 --- a/lib/screens/settings/customization/customization.dart +++ b/lib/screens/settings/customization/customization.dart @@ -120,7 +120,7 @@ class _CustomizationWidgetState extends State { label: AppLocalizations.of(context)!.color, padding: const EdgeInsets.only(top: 45, left: 16, right: 16, bottom: 5), ), - if (appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31) CustomSwitchListTile( + if (appConfigProvider.supportsDynamicTheme) CustomSwitchListTile( value: dynamicColor, onChanged: (value) { setState(() => dynamicColor = value); @@ -129,7 +129,10 @@ class _CustomizationWidgetState extends State { title: AppLocalizations.of(context)!.useDynamicTheme, ), if (!(appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31)) const SizedBox(height: 20), - if (dynamicColor == false) Padding( + if ( + appConfigProvider.supportsDynamicTheme == false || + (appConfigProvider.supportsDynamicTheme == true && dynamicColor == false) + ) Padding( padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16), child: Scrollbar( controller: _colorsScrollController, @@ -207,15 +210,6 @@ class _CustomizationWidgetState extends State { ), ), ), - CustomSwitchListTile( - value: useThemeColorInsteadGreenRed, - onChanged: (value) { - setState(() => useThemeColorInsteadGreenRed = value); - appConfigProvider.setUseThemeColorForStatus(value); - }, - title: AppLocalizations.of(context)!.useThemeColorStatus, - subtitle: AppLocalizations.of(context)!.useThemeColorStatusDescription, - ) ], ), ), diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index b60b38a..fa82957 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -1,141 +1,7 @@ import 'package:sqflite/sqflite.dart'; -import 'package:adguard_home_manager/config/home_top_items_default_order.dart'; - -Future> loadDb(bool acceptsDynamicTheme) async { +Future> loadDb() async { List>? servers; - List>? appConfig; - - Future rebuildAppConfig(Database db) async { - await db.execute("DROP TABLE appConfig"); - await db.execute("CREATE TABLE appConfig (theme NUMERIC, overrideSslCheck NUMERIC, hideZeroValues NUMERIC, useDynamicColor NUMERIC, staticColor NUMERIC, useThemeColorForStatus NUMERIC, showTimeLogs NUMERIC, showIpLogs NUMERIC, combinedChart NUMERIC, doNotRememberVersion TEXT)"); - await db.execute("INSERT INTO appConfig (theme, overrideSslCheck, hideZeroValues, useDynamicColor, staticColor, useThemeColorForStatus, showTimeLogs, showIpLogs, combinedChart) VALUES (0, 0, 0, ${acceptsDynamicTheme == true ? 1 : 0}, 0, 0, 0, 0, 0)"); - } - - Future upgradeDbToV2(Database db) async { - await db.execute("ALTER TABLE appConfig ADD COLUMN overrideSslCheck NUMERIC"); - await db.execute("UPDATE appConfig SET overrideSslCheck = 0"); - - await db.transaction((txn) async{ - await txn.rawQuery( - 'SELECT * FROM appConfig', - ); - }); - } - - Future upgradeDbToV3(Database db) async { - await db.execute("ALTER TABLE appConfig ADD COLUMN hideZeroValues NUMERIC"); - await db.execute("UPDATE appConfig SET hideZeroValues = 0"); - - await db.transaction((txn) async{ - await txn.rawQuery( - 'SELECT * FROM appConfig', - ); - }); - } - - Future upgradeDbToV4(Database db) async { - await db.execute("ALTER TABLE servers ADD COLUMN runningOnHa INTEGER"); - await db.execute("UPDATE servers SET runningOnHa = 0"); - - await db.transaction((txn) async{ - await txn.rawQuery( - 'SELECT * FROM servers', - ); - }); - } - - Future upgradeDbToV5(Database db) async { - await db.execute("ALTER TABLE appConfig ADD COLUMN useDynamicColor NUMERIC"); - await db.execute("ALTER TABLE appConfig ADD COLUMN staticColor NUMERIC"); - await db.execute("ALTER TABLE appConfig ADD COLUMN useThemeColorForStatus NUMERIC"); - await db.execute("UPDATE appConfig SET useDynamicColor = ${acceptsDynamicTheme == true ? 1 : 0}, staticColor = 0, useThemeColorForStatus = 0"); - - await db.transaction((txn) async{ - await txn.rawQuery( - 'SELECT * FROM appConfig', - ); - }); - } - - Future upgradeDbToV6(Database db) async { - await db.execute("ALTER TABLE appConfig ADD COLUMN showNameTimeLogs NUMERIC"); - await db.execute("UPDATE appConfig SET showNameTimeLogs = 0"); - - await db.transaction((txn) async{ - await txn.rawQuery( - 'SELECT * FROM appConfig', - ); - }); - } - - Future upgradeDbToV7(Database db) async { - await db.execute("ALTER TABLE appConfig ADD COLUMN doNotRememberVersion TEXT"); - - await db.transaction((txn) async{ - await txn.rawQuery( - 'SELECT * FROM appConfig', - ); - }); - } - - Future upgradeDbToV8(Database db) async { - try { - final data = await db.rawQuery( - 'SELECT * FROM appConfig', - ); - await rebuildAppConfig(db); - await db.update( - 'appConfig', - { - 'theme': data[0]['theme'], - 'overrideSslCheck': data[0]['overrideSslCheck'], - 'hideZeroValues': data[0]['hideZeroValues'], - 'useDynamicColor': data[0]['useDynamicColor'], - 'staticColor': data[0]['staticColor'], - 'useThemeColorForStatus': data[0]['useThemeColorForStatus'], - 'showTimeLogs': data[0]['showNameTimeLogs'], - 'showIpLogs': data[0]['showIpLogs'], - 'combinedChart': data[0]['combinedChart'], - } - ); - } catch (e) { - await rebuildAppConfig(db); - } - } - - Future upgradeDbToV9(Database db) async { - await db.execute("ALTER TABLE appConfig ADD COLUMN hideServerAddress NUMERIC"); - await db.execute("ALTER TABLE appConfig ADD COLUMN homeTopItemsOrder TEXT"); - await db.execute("UPDATE appConfig SET hideServerAddress = 0, homeTopItemsOrder = '$homeTopItemsDefaultOrderString'"); - - await db.transaction((txn) async{ - await txn.rawQuery( - 'SELECT * FROM appConfig', - ); - }); - } - - Future upgradeDbToV10(Database db) async { - await db.execute("ALTER TABLE appConfig ADD COLUMN showTopItemsChart NUMERIC"); - await db.execute("UPDATE appConfig SET showTopItemsChart = 1"); - - await db.transaction((txn) async{ - await txn.rawQuery( - 'SELECT * FROM appConfig', - ); - }); - } - - Future upgradeDbToV11(Database db) async { - await db.execute("ALTER TABLE appConfig DROP COLUMN showTopItemsChart"); - - await db.transaction((txn) async{ - await txn.rawQuery( - 'SELECT * FROM appConfig', - ); - }); - } Database db = await openDatabase( 'adguard_home_manager.db', @@ -159,135 +25,9 @@ Future> loadDb(bool acceptsDynamicTheme) async { ) """ ); - - await db.execute( - """ - CREATE TABLE - appConfig ( - theme NUMERIC, - overrideSslCheck NUMERIC, - hideZeroValues NUMERIC, - useDynamicColor NUMERIC, - staticColor NUMERIC, - useThemeColorForStatus NUMERIC, - showTimeLogs NUMERIC, - showIpLogs NUMERIC, - combinedChart NUMERIC, - doNotRememberVersion TEXT, - hideServerAddress NUMERIC, - homeTopItemsOrder TEXT - ) - """ - ); - - await db.execute( - """ - INSERT INTO - appConfig ( - theme, - overrideSslCheck, - hideZeroValues, - useDynamicColor, - staticColor, - useThemeColorForStatus, - showTimeLogs, - showIpLogs, - combinedChart, - hideServerAddress, - homeTopItemsOrder - ) - VALUES ( - 0, - 0, - 0, - ${acceptsDynamicTheme == true ? 1 : 0}, - 0, - 0, - 0, - 0, - 0, - 0, - '$homeTopItemsDefaultOrderString' - ) - """ - ); }, onUpgrade: (Database db, int oldVersion, int newVersion) async { - if (oldVersion == 1) { - await upgradeDbToV2(db); - await upgradeDbToV3(db); - await upgradeDbToV4(db); - await upgradeDbToV5(db); - await upgradeDbToV6(db); - await upgradeDbToV7(db); - await upgradeDbToV8(db); - await upgradeDbToV9(db); - await upgradeDbToV10(db); - await upgradeDbToV11(db); - } - if (oldVersion == 2) { - await upgradeDbToV3(db); - await upgradeDbToV4(db); - await upgradeDbToV5(db); - await upgradeDbToV6(db); - await upgradeDbToV7(db); - await upgradeDbToV8(db); - await upgradeDbToV9(db); - await upgradeDbToV10(db); - await upgradeDbToV11(db); - } - if (oldVersion == 3) { - await upgradeDbToV4(db); - await upgradeDbToV5(db); - await upgradeDbToV6(db); - await upgradeDbToV7(db); - await upgradeDbToV8(db); - await upgradeDbToV9(db); - await upgradeDbToV10(db); - await upgradeDbToV11(db); - } - if (oldVersion == 4) { - await upgradeDbToV5(db); - await upgradeDbToV6(db); - await upgradeDbToV7(db); - await upgradeDbToV8(db); - await upgradeDbToV9(db); - await upgradeDbToV10(db); - await upgradeDbToV11(db); - } - if (oldVersion == 5) { - await upgradeDbToV6(db); - await upgradeDbToV7(db); - await upgradeDbToV8(db); - await upgradeDbToV9(db); - await upgradeDbToV10(db); - await upgradeDbToV11(db); - } - if (oldVersion == 6) { - await upgradeDbToV7(db); - await upgradeDbToV8(db); - await upgradeDbToV9(db); - await upgradeDbToV10(db); - await upgradeDbToV11(db); - } - if (oldVersion == 7) { - await upgradeDbToV8(db); - await upgradeDbToV9(db); - await upgradeDbToV10(db); - await upgradeDbToV11(db); - } - if (oldVersion == 8) { - await upgradeDbToV9(db); - await upgradeDbToV10(db); - await upgradeDbToV11(db); - } - if (oldVersion == 9) { - await upgradeDbToV10(db); - await upgradeDbToV11(db); - } - if (oldVersion == 10) { - await upgradeDbToV11(db); - } + }, onOpen: (Database db) async { await db.transaction((txn) async{ @@ -295,17 +35,11 @@ Future> loadDb(bool acceptsDynamicTheme) async { 'SELECT * FROM servers', ); }); - await db.transaction((txn) async{ - appConfig = await txn.rawQuery( - 'SELECT * FROM appConfig', - ); - }); } ); return { "servers": servers, - "appConfig": appConfig![0], "dbInstance": db, }; } \ No newline at end of file diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 31a4f66..045b44f 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,6 +9,7 @@ import device_info_plus import dynamic_color import package_info_plus import sentry_flutter +import shared_preferences_foundation import sqflite import sqlite3_flutter_libs import url_launcher_macos @@ -19,6 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/pubspec.lock b/pubspec.lock index d584bfa..0f65427 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -502,6 +502,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" percent_indicator: dependency: "direct main" description: @@ -526,6 +550,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.4.0" + platform: + dependency: transitive + description: + name: platform + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + url: "https://pub.dev" + source: hosted + version: "3.1.4" plugin_platform_interface: dependency: transitive description: @@ -574,6 +606,62 @@ packages: url: "https://pub.dev" source: hosted version: "7.15.0" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" + url: "https://pub.dev" + source: hosted + version: "2.3.5" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + url: "https://pub.dev" + source: hosted + version: "2.3.2" sky_engine: dependency: transitive description: flutter @@ -852,6 +940,14 @@ packages: url: "https://github.com/google/flutter-desktop-embedding" source: git version: "0.1.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" + source: hosted + version: "1.0.4" xml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index aa5c383..c4119e9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -77,6 +77,7 @@ dependencies: timezone: ^0.9.2 flutter_custom_tabs: ^2.0.0+1 url_launcher: ^6.2.4 + shared_preferences: ^2.2.2 dev_dependencies: flutter_test: From 9b1e36df5b6d415d863322d9f98ecbfedfd62129 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 2 Feb 2024 20:40:42 +0100 Subject: [PATCH 525/676] Updated macos stuff --- macos/Podfile.lock | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 1bad97f..f5e5c0c 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -13,6 +13,9 @@ PODS: - FlutterMacOS - Sentry/HybridSDK (= 8.18.0) - SentryPrivate (8.18.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS - sqflite (0.0.3): - Flutter - FlutterMacOS @@ -42,6 +45,7 @@ DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) @@ -64,6 +68,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos sentry_flutter: :path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos + shared_preferences_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin sqflite: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin sqlite3_flutter_libs: @@ -81,6 +87,7 @@ SPEC CHECKSUMS: Sentry: 8984a4ffb2b9bd2894d74fb36e6f5833865bc18e sentry_flutter: c87a0556eeb6cbf7f9f924d30e878bdedf22d364 SentryPrivate: 2f0c9ba4c3fc993f70eab6ca95673509561e0085 + shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: f307b6291c4db7b5086c38d6237446b98a738581 sqlite3_flutter_libs: 6b9913d8fbb718e5ebf23658aa6934a0fb509c0f From 2585826a29cef82917b4c40229863e9bdb008bb9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 3 Feb 2024 01:58:45 +0100 Subject: [PATCH 526/676] Show client name on logs --- lib/screens/logs/filters/clients_modal.dart | 53 ++++++++------------- lib/services/db/database.dart | 3 -- 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index cf8a94f..6500717 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -7,6 +7,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; import 'package:adguard_home_manager/widgets/list_bottom_sheet.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; @@ -228,39 +229,25 @@ class _ListItem extends StatelessWidget { @override Widget build(BuildContext context) { - return Material( - color: Colors.transparent, - child: InkWell( - onTap: () => onChanged(!checkboxActive), - child: Padding( - padding: const EdgeInsets.only( - left: 24, - top: 4, - right: 12, - bottom: 4 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Text( - label, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - Checkbox( - value: checkboxActive, - onChanged: (v) => onChanged(!checkboxActive), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5) - ), - ) - ], - ), - ), + final statusProvider = Provider.of(context); + + String? name; + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(label)).name; + } catch (e) { + // ---- // + } + + return CustomCheckboxListTile( + value: checkboxActive, + onChanged: (v) => onChanged(v), + title: label, + subtitle: name, + padding: const EdgeInsets.only( + left: 24, + top: 8, + right: 12, + bottom: 8 ), ); } diff --git a/lib/services/db/database.dart b/lib/services/db/database.dart index fa82957..fe09d16 100644 --- a/lib/services/db/database.dart +++ b/lib/services/db/database.dart @@ -25,9 +25,6 @@ Future> loadDb() async { ) """ ); - }, - onUpgrade: (Database db, int oldVersion, int newVersion) async { - }, onOpen: (Database db) async { await db.transaction((txn) async{ From 5f448f0af0485357d666ef8431ff66bd373c4575 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 3 Feb 2024 02:38:00 +0100 Subject: [PATCH 527/676] Added search clients filter --- lib/screens/logs/filters/clients_modal.dart | 438 ++++++++++++-------- lib/widgets/list_bottom_sheet.dart | 105 +++-- 2 files changed, 316 insertions(+), 227 deletions(-) diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index 6500717..ca15219 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -11,7 +11,17 @@ import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; -class ClientsModal extends StatelessWidget { +class _ClientLog { + final String ip; + final String? name; + + const _ClientLog({ + required this.ip, + required this.name + }); +} + +class ClientsModal extends StatefulWidget { final List? value; final bool dialog; @@ -22,196 +32,278 @@ class ClientsModal extends StatelessWidget { }); @override - Widget build(BuildContext context) { - final clientsProvider = Provider.of(context); - final logsProvider = Provider.of(context); - - if (dialog == true) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: _ModalContent( - selectedClients: logsProvider.selectedClients, - onClientsSelected: (v) => logsProvider.setSelectedClients(v), - ) - ), - ); - } - else { - return ListBottomSheet( - icon: Icons.smartphone_rounded, - title: AppLocalizations.of(context)!.clients, - children: [ - Card( - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Icon( - Icons.info_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(width: 16), - Flexible( - child: Text(AppLocalizations.of(context)!.selectClientsFiltersInfo) - ) - ], - ), - ), - ), - CustomCheckboxListTile( - padding: const EdgeInsets.only( - left: 24, - top: 8, - right: 12, - bottom: 8 - ), - value: logsProvider.selectedClients.length == clientsProvider.clients!.autoClients.length, - onChanged: (v) { - if (v == true) { - logsProvider.setSelectedClients(clientsProvider.clients!.autoClients.map((e) => e.ip).toList()); - } - else { - logsProvider.setSelectedClients([]); - } - }, - title: AppLocalizations.of(context)!.selectAll - ), - ListView.builder( - shrinkWrap: true, - primary: false, - itemCount: clientsProvider.clients!.autoClients.length, - itemBuilder: (context, index) => _ListItem( - label: clientsProvider.clients!.autoClients[index].ip, - checkboxActive: logsProvider.selectedClients.contains(clientsProvider.clients!.autoClients[index].ip), - onChanged: (isSelected) { - if (isSelected == true) { - logsProvider.setSelectedClients([ - ...logsProvider.selectedClients, - clientsProvider.clients!.autoClients[index].ip - ]); - } - else { - logsProvider.setSelectedClients( - logsProvider.selectedClients.where( - (item) => item != clientsProvider.clients!.autoClients[index].ip - ).toList() - ); - } - } - ) - ) - ] - ); - } - } + State createState() => _ClientsModalState(); } -class _ModalContent extends StatelessWidget { - final List selectedClients; - final void Function(List) onClientsSelected; +class _ClientsModalState extends State { + List<_ClientLog> _filteredClients = []; + final _searchController = TextEditingController(); - const _ModalContent({ - required this.selectedClients, - required this.onClientsSelected, - }); + @override + void initState() { + final clientsProvider = Provider.of(context, listen: false); + final statusProvider = Provider.of(context, listen: false); + _filteredClients = clientsProvider.clients!.autoClients.map((e) { + String? name; + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(e.ip)).name; + } catch (e) { + // ---- // + } + return _ClientLog( + ip: e.ip, + name: name + ); + }).toList(); + + super.initState(); + } @override Widget build(BuildContext context) { final clientsProvider = Provider.of(context); final logsProvider = Provider.of(context); + final statusProvider = Provider.of(context); - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - CloseButton( - onPressed: () => Navigator.pop(context), - ), - const SizedBox(width: 12), - Text( - AppLocalizations.of(context)!.clients, - style: const TextStyle( - fontSize: 22 - ), - ) - ], + void onSearch(String value) { + final filtered = clientsProvider.clients!.autoClients.map((e) { + String? name; + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(e.ip)).name; + } catch (e) { + // ---- // + } + return _ClientLog( + ip: e.ip, + name: name + ); + }).where( + (c) => c.ip.contains(value.toLowerCase()) || (c.name != null && c.name!.toLowerCase().contains(value.toLowerCase())) + ).toList(); + setState(() => _filteredClients = filtered); + } + + if (widget.dialog == true) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 ), - ), - Flexible( - child: ListView( + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Card( - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Icon( - Icons.info_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, + Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + CloseButton( + onPressed: () => Navigator.pop(context), + ), + const SizedBox(width: 12), + Text( + AppLocalizations.of(context)!.clients, + style: const TextStyle( + fontSize: 22 ), - const SizedBox(width: 16), - Flexible( - child: Text(AppLocalizations.of(context)!.selectClientsFiltersInfo) + ) + ], + ), + ), + Flexible( + child: ListView( + children: [ + _SearchField( + controller: _searchController, + onClear: () => setState(() => _searchController.text = ""), + onSearch: onSearch + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 16), + Flexible( + child: Text(AppLocalizations.of(context)!.selectClientsFiltersInfo) + ) + ], + ), + ), + ), + CustomCheckboxListTile( + padding: const EdgeInsets.only( + left: 24, + top: 8, + right: 12, + bottom: 8 + ), + value: logsProvider.selectedClients.length == clientsProvider.clients!.autoClients.length, + onChanged: (v) { + if (v == true) { + logsProvider.setSelectedClients(clientsProvider.clients!.autoClients.map((e) => e.ip).toList()); + } + else { + logsProvider.setSelectedClients([]); + } + }, + title: AppLocalizations.of(context)!.selectAll + ), + ListView.builder( + primary: false, + shrinkWrap: true, + itemCount: _filteredClients.length, + itemBuilder: (context, index) => _ListItem( + label: _filteredClients[index].ip, + checkboxActive: logsProvider.selectedClients.contains(_filteredClients[index].ip), + onChanged: (isSelected) { + if (isSelected == true) { + logsProvider.setSelectedClients([ + ...logsProvider.selectedClients, + _filteredClients[index].ip + ]); + } + else { + logsProvider.setSelectedClients( + logsProvider.selectedClients.where( + (item) => item != _filteredClients[index].ip + ).toList() + ); + } + } ) - ], - ), - ), - ), - CustomCheckboxListTile( - padding: const EdgeInsets.only( - left: 24, - top: 8, - right: 12, - bottom: 8 - ), - value: logsProvider.selectedClients.length == clientsProvider.clients!.autoClients.length, - onChanged: (v) { - if (v == true) { - logsProvider.setSelectedClients(clientsProvider.clients!.autoClients.map((e) => e.ip).toList()); - } - else { - logsProvider.setSelectedClients([]); - } - }, - title: AppLocalizations.of(context)!.selectAll - ), - ListView.builder( - primary: false, - shrinkWrap: true, - itemCount: clientsProvider.clients!.autoClients.length, - itemBuilder: (context, index) => _ListItem( - label: clientsProvider.clients!.autoClients[index].ip, - checkboxActive: selectedClients.contains(clientsProvider.clients!.autoClients[index].ip), - onChanged: (isSelected) { - if (isSelected == true) { - onClientsSelected([ - ...selectedClients, - clientsProvider.clients!.autoClients[index].ip - ]); - } - else { - onClientsSelected( - selectedClients.where( - (item) => item != clientsProvider.clients!.autoClients[index].ip - ).toList() - ); - } - } + ), + ], ) ), + if (Platform.isIOS) const SizedBox(height: 16) ], ) ), - if (Platform.isIOS) const SizedBox(height: 16) - ], + ); + } + else { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: ListBottomSheet( + icon: Icons.smartphone_rounded, + title: AppLocalizations.of(context)!.clients, + children: [ + _SearchField( + controller: _searchController, + onClear: () => setState(() => _searchController.text = ""), + onSearch: onSearch + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 16), + Flexible( + child: Text(AppLocalizations.of(context)!.selectClientsFiltersInfo) + ) + ], + ), + ), + ), + CustomCheckboxListTile( + padding: const EdgeInsets.only( + left: 24, + top: 8, + right: 12, + bottom: 8 + ), + value: logsProvider.selectedClients.length == clientsProvider.clients!.autoClients.length, + onChanged: (v) { + if (v == true) { + logsProvider.setSelectedClients(clientsProvider.clients!.autoClients.map((e) => e.ip).toList()); + } + else { + logsProvider.setSelectedClients([]); + } + }, + title: AppLocalizations.of(context)!.selectAll + ), + ListView.builder( + shrinkWrap: true, + primary: false, + itemCount: _filteredClients.length, + itemBuilder: (context, index) => _ListItem( + label: _filteredClients[index].ip, + checkboxActive: logsProvider.selectedClients.contains(_filteredClients[index].ip), + onChanged: (isSelected) { + if (isSelected == true) { + logsProvider.setSelectedClients([ + ...logsProvider.selectedClients, + _filteredClients[index].ip + ]); + } + else { + logsProvider.setSelectedClients( + logsProvider.selectedClients.where( + (item) => item != _filteredClients[index].ip + ).toList() + ); + } + } + ) + ) + ] + ), + ); + } + } +} + +class _SearchField extends StatelessWidget { + final TextEditingController controller; + final void Function(String) onSearch; + final void Function() onClear; + + const _SearchField({ + required this.controller, + required this.onClear, + required this.onSearch, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: TextFormField( + controller: controller, + onChanged: onSearch, + decoration: InputDecoration( + hintText: AppLocalizations.of(context)!.search, + prefixIcon: const Icon(Icons.search_rounded), + border: InputBorder.none, + filled: true, + fillColor: Colors.grey.withOpacity(0.2), + suffixIcon: controller.text != "" + ? IconButton( + onPressed: onClear, + icon: const Icon( + Icons.close_rounded, + size: 20, + ), + tooltip: AppLocalizations.of(context)!.clearSearch, + ) + : null + ), + ), + ), ); } } diff --git a/lib/widgets/list_bottom_sheet.dart b/lib/widgets/list_bottom_sheet.dart index 219df8c..83f9c78 100644 --- a/lib/widgets/list_bottom_sheet.dart +++ b/lib/widgets/list_bottom_sheet.dart @@ -20,67 +20,64 @@ class ListBottomSheet extends StatelessWidget { @override Widget build(BuildContext context) { - return GestureDetector( - onTap: () => Navigator.of(context).pop(), - child: DraggableScrollableSheet( - initialChildSize: initialChildSize ?? 0.6, - minChildSize: minChildSize ?? 0.3, - maxChildSize: maxChildSize ?? 1, - builder: (context, controller) { - return Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28), - ), + return DraggableScrollableSheet( + initialChildSize: initialChildSize ?? 0.6, + minChildSize: minChildSize ?? 0.3, + maxChildSize: maxChildSize ?? 1, + builder: (context, controller) { + return Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(28), + topRight: Radius.circular(28), ), - child: SafeArea( - child: ListView( - controller: controller, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, + ), + child: SafeArea( + child: ListView( + controller: controller, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.all(16), + width: 36, + height: 4, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Colors.grey + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Column( children: [ - Container( - margin: const EdgeInsets.all(16), - width: 36, - height: 4, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.grey + Icon( + icon, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + title, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: Theme.of(context).colorScheme.onSurface ), ), ], ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16), - child: Column( - children: [ - Icon( - icon, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(height: 16), - Text( - title, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ], - ), - ), - ...children - ], - ), + ), + ...children + ], ), - ); - }, - ), + ), + ); + }, ); } } \ No newline at end of file From 8df0781da62b4ceddfeca63c429efa677249205b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 3 Feb 2024 14:38:38 +0100 Subject: [PATCH 528/676] Added ipv4 and ipv6 subnet prefix length fields --- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/models/dns_info.dart | 12 +- lib/providers/dns_provider.dart | 2 + .../settings/dns/dns_server_settings.dart | 214 +++++++++++------- 5 files changed, 148 insertions(+), 88 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index bdd9f99..ab2a561 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -758,5 +758,7 @@ "invalidTime": "Invalid time", "removeDomain": "Remove domain", "addDomain": "Add domain", - "notLess1Hour": "Time cannot be less than 1 hour" + "notLess1Hour": "Time cannot be less than 1 hour", + "subnetPrefixLengthIpv4": "Subnet prefix length for IPv4", + "subnetPrefixLengthIpv6": "Subnet prefix length for IPv6" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index d9b2f9a..6a701d1 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -758,5 +758,7 @@ "invalidTime": "Tiempo no válido", "removeDomain": "Eliminar dominio", "addDomain": "Añadir dominio", - "notLess1Hour": "El tiempo no puede ser inferior a 1 hora" + "notLess1Hour": "El tiempo no puede ser inferior a 1 hora", + "subnetPrefixLengthIpv4": "Longitud del prefijo de subred para IPv4", + "subnetPrefixLengthIpv6": "Longitud del prefijo de subred para IPv6" } \ No newline at end of file diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index c0cabd6..d4152c8 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -23,6 +23,8 @@ class DnsInfo { String blockingIpv6; List defaultLocalPtrUpstreams; int? blockedResponseTtl; + int? ratelimitSubnetLenIpv4; + int? ratelimitSubnetLenIpv6; DnsInfo({ required this.upstreamDns, @@ -49,6 +51,8 @@ class DnsInfo { required this.blockingIpv6, required this.defaultLocalPtrUpstreams, required this.blockedResponseTtl, + required this.ratelimitSubnetLenIpv4, + required this.ratelimitSubnetLenIpv6, }); factory DnsInfo.fromJson(Map json) => DnsInfo( @@ -75,7 +79,9 @@ 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"] + blockedResponseTtl: json["blocked_response_ttl"], + ratelimitSubnetLenIpv4: json["ratelimit_subnet_len_ipv4"], + ratelimitSubnetLenIpv6: json["ratelimit_subnet_len_ipv6"], ); Map toJson() => { @@ -102,6 +108,8 @@ class DnsInfo { "blocking_ipv4": blockingIpv4, "blocking_ipv6": blockingIpv6, "default_local_ptr_upstreams": List.from(defaultLocalPtrUpstreams.map((x) => x)), - "blocked_response_ttl": blockedResponseTtl + "blocked_response_ttl": blockedResponseTtl, + "ratelimit_subnet_len_ipv4": ratelimitSubnetLenIpv4, + "ratelimit_subnet_len_ipv6": ratelimitSubnetLenIpv6, }; } diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index 84b86cd..9c8d705 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -162,6 +162,8 @@ class DnsProvider with ChangeNotifier { data.blockingIpv4 = value['blocking_ipv4']; data.blockingIpv6 = value['blocking_ipv6']; data.blockedResponseTtl = value['blocked_response_ttl']; + data.ratelimitSubnetLenIpv4 = value['ratelimit_subnet_len_ipv4']; + data.ratelimitSubnetLenIpv6 = value['ratelimit_subnet_len_ipv6']; 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 b13f593..6e747f3 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -23,49 +23,49 @@ class DnsServerSettingsScreen extends StatefulWidget { } class _DnsServerSettingsScreenState extends State { - final TextEditingController limitRequestsController = TextEditingController(); - String? limitRequestsError; + final _limitRequestsController = TextEditingController(); + final _ipv4PrefixSubnetController = TextEditingController(); + String? _ipv4PrefixSubnetError; + final _ipv6PrefixSubnetController = TextEditingController(); + String? _ipv6PrefixSubnetError; + String? _limitRequestsError; final _expandableCustomEdns = ExpandableController(); final _expandableEdnsIp = ExpandableController(); - bool enableEdns = false; - bool useCustomIpEdns = false; + bool _enableEdns = false; + bool _useCustomIpEdns = false; final _customIpEdnsController = TextEditingController(); - String? ednsIpError; - bool enableDnssec = false; - bool disableIpv6Resolving = false; + String? _ednsIpError; + bool _enableDnssec = false; + bool _disableIpv6Resolving = false; String blockingMode = "default"; - final TextEditingController ipv4controller = TextEditingController(); - String? ipv4error; - final TextEditingController ipv6controller = TextEditingController(); + final _ipv4controller = TextEditingController(); + String? _ipv4error; + final _ipv6controller = TextEditingController(); String? ipv6error; final _ttlController = TextEditingController(); String? _ttlError; - bool isDataValid = false; - void validateIpv4(String value) { RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$'); if (ipAddress.hasMatch(value) == true) { - setState(() => ipv4error = null); + setState(() => _ipv4error = null); } else { - setState(() => ipv4error = AppLocalizations.of(context)!.invalidIp); + setState(() => _ipv4error = AppLocalizations.of(context)!.invalidIp); } - validateData(); } void validateEdns(String value) { RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); if (ipAddress.hasMatch(value) == true) { - setState(() => ednsIpError = null); + setState(() => _ednsIpError = null); } else { - setState(() => ednsIpError = AppLocalizations.of(context)!.ipNotValid); + setState(() => _ednsIpError = AppLocalizations.of(context)!.ipNotValid); } - validateData(); } void validateIpv6(String value) { @@ -76,63 +76,77 @@ class _DnsServerSettingsScreenState extends State { else { setState(() => ipv6error = AppLocalizations.of(context)!.invalidIp); } - validateData(); } - void validateData() { + bool validateData() { if ( - limitRequestsController.text != '' && - limitRequestsError == null && + (_limitRequestsController.text == "" || (_limitRequestsController.text != "" && _limitRequestsError == null)) && ( blockingMode != 'custom_ip' || ( blockingMode == 'custom_ip' && - ipv4controller.text != '' && - ipv4error == null && - ipv6controller.text != '' && + _ipv4controller.text != '' && + _ipv4error == null && + _ipv6controller.text != '' && ipv6error == null ) ) == true && - ednsIpError == null && - _ttlError == null + _ednsIpError == null && + _ttlController.text != "" && _ttlError == null && + (_ipv4PrefixSubnetController.text == "" || (_ipv4PrefixSubnetController.text != "" && _ipv4PrefixSubnetError == null)) && + (_ipv6PrefixSubnetController.text == "" || (_ipv6PrefixSubnetController.text != "" && _ipv6PrefixSubnetError == null)) ) { - setState(() => isDataValid = true); + return true; } else { - setState(() => isDataValid = false); + return false; } } - void validateNumber(String value) { - final regex = RegExp(r'^(\d)+$'); - if (regex.hasMatch(value) == true) { - setState(() => _ttlError = null); + String? validateTtl(String value) { + if (value == "") return AppLocalizations.of(context)!.valueNotNumber; + if (int.tryParse(value) != null) { + return null; } else { - setState(() => _ttlError = AppLocalizations.of(context)!.invalidValue); + return AppLocalizations.of(context)!.valueNotNumber; + } + } + + String? validateNumber(String value) { + if (value == "") return null; + if (int.tryParse(value) != null) { + return null; + } + else { + return AppLocalizations.of(context)!.valueNotNumber; } - validateData(); } @override void initState() { final dnsProvider = Provider.of(context, listen: false); - limitRequestsController.text = dnsProvider.dnsInfo!.ratelimit.toString(); - enableEdns = dnsProvider.dnsInfo!.ednsCsEnabled; - useCustomIpEdns = dnsProvider.dnsInfo!.ednsCsUseCustom ?? false; + _limitRequestsController.text = dnsProvider.dnsInfo!.ratelimit.toString(); + _enableEdns = dnsProvider.dnsInfo!.ednsCsEnabled; + _useCustomIpEdns = dnsProvider.dnsInfo!.ednsCsUseCustom ?? false; _customIpEdnsController.text = dnsProvider.dnsInfo!.ednsCsCustomIp ?? ""; if (dnsProvider.dnsInfo!.ednsCsEnabled == true) _expandableCustomEdns.toggle(); if (dnsProvider.dnsInfo!.ednsCsUseCustom == true) _expandableEdnsIp.toggle(); - enableDnssec = dnsProvider.dnsInfo!.dnssecEnabled; - disableIpv6Resolving = dnsProvider.dnsInfo!.disableIpv6; + _enableDnssec = dnsProvider.dnsInfo!.dnssecEnabled; + _disableIpv6Resolving = dnsProvider.dnsInfo!.disableIpv6; blockingMode = dnsProvider.dnsInfo!.blockingMode; - ipv4controller.text = dnsProvider.dnsInfo!.blockingIpv4; - ipv6controller.text = dnsProvider.dnsInfo!.blockingIpv6; - isDataValid = true; + _ipv4controller.text = dnsProvider.dnsInfo!.blockingIpv4; + _ipv6controller.text = dnsProvider.dnsInfo!.blockingIpv6; _ttlController.text = dnsProvider.dnsInfo!.blockedResponseTtl != null ? dnsProvider.dnsInfo!.blockedResponseTtl.toString() : ""; + _ipv4PrefixSubnetController.text = dnsProvider.dnsInfo!.ratelimitSubnetLenIpv4 != null + ? dnsProvider.dnsInfo!.ratelimitSubnetLenIpv4.toString() + : ""; + _ipv6PrefixSubnetController.text = dnsProvider.dnsInfo!.ratelimitSubnetLenIpv6 != null + ? dnsProvider.dnsInfo!.ratelimitSubnetLenIpv6.toString() + : ""; super.initState(); } @@ -147,16 +161,18 @@ class _DnsServerSettingsScreenState extends State { processModal.open(AppLocalizations.of(context)!.savingConfig); final result = await dnsProvider.saveDnsServerConfig({ - "ratelimit": int.parse(limitRequestsController.text), - "edns_cs_enabled": enableEdns, - "edns_cs_use_custom": useCustomIpEdns, + "ratelimit": int.parse(_limitRequestsController.text), + "edns_cs_enabled": _enableEdns, + "edns_cs_use_custom": _useCustomIpEdns, "edns_cs_custom_ip": _customIpEdnsController.text, - "dnssec_enabled": enableDnssec, - "disable_ipv6": disableIpv6Resolving, + "dnssec_enabled": _enableDnssec, + "disable_ipv6": _disableIpv6Resolving, "blocking_mode": blockingMode, - "blocking_ipv4": ipv4controller.text, - "blocking_ipv6": ipv6controller.text, - "blocked_response_ttl": int.tryParse(_ttlController.text) + "blocking_ipv4": _ipv4controller.text, + "blocking_ipv6": _ipv6controller.text, + "blocked_response_ttl": int.tryParse(_ttlController.text), + "ratelimit_subnet_len_ipv4": int.tryParse(_ipv4PrefixSubnetController.text), + "ratelimit_subnet_len_ipv6": int.tryParse(_ipv6PrefixSubnetController.text), }); processModal.close(); @@ -186,22 +202,24 @@ class _DnsServerSettingsScreenState extends State { void updateBlockingMode(String mode) { if (mode != 'custom_ip') { - ipv4controller.text = ''; - ipv4error = null; - ipv6controller.text = ''; + _ipv4controller.text = ''; + _ipv4error = null; + _ipv6controller.text = ''; ipv6error = null; } setState(() => blockingMode = mode); validateData(); } + final dataValid = validateData(); + return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.dnsServerSettings), surfaceTintColor: isDesktop(width) ? Colors.transparent : null, actions: [ IconButton( - onPressed: isDataValid == true + onPressed: dataValid == true ? () => saveData() : null, icon: const Icon(Icons.save_rounded), @@ -217,16 +235,8 @@ class _DnsServerSettingsScreenState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: TextFormField( - controller: limitRequestsController, - onChanged: (value) { - if (int.tryParse(value) != null) { - setState(() => limitRequestsError = null); - } - else { - setState(() => limitRequestsError = AppLocalizations.of(context)!.valueNotNumber); - } - validateData(); - }, + controller: _limitRequestsController, + onChanged: (v) => setState(() => _limitRequestsError = validateNumber(v)), decoration: InputDecoration( prefixIcon: const Icon(Icons.looks_one_rounded), border: const OutlineInputBorder( @@ -235,22 +245,58 @@ class _DnsServerSettingsScreenState extends State { ) ), labelText: AppLocalizations.of(context)!.limitRequestsSecond, - errorText: limitRequestsError + errorText: _limitRequestsError ), keyboardType: TextInputType.number, ), ), - const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + child: TextFormField( + controller: _ipv4PrefixSubnetController, + onChanged: (v) => setState(() => _ipv4PrefixSubnetError = validateNumber(v)), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_previous_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.subnetPrefixLengthIpv4, + errorText: _ipv4PrefixSubnetError + ), + keyboardType: TextInputType.number, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: TextFormField( + controller: _ipv6PrefixSubnetController, + onChanged: (v) => setState(() => _ipv6PrefixSubnetError = validateNumber(v)), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.skip_previous_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.subnetPrefixLengthIpv6, + errorText: _ipv6PrefixSubnetError + ), + keyboardType: TextInputType.number, + ), + ), + const SizedBox(height: 16), CustomSwitchListTile( - value: enableEdns, + value: _enableEdns, onChanged: (value) => setState(() { - enableEdns = value; + _enableEdns = value; _expandableCustomEdns.toggle(); if (value == false) { - useCustomIpEdns = false; + _useCustomIpEdns = false; if (_expandableEdnsIp.expanded == true) _expandableEdnsIp.toggle(); _customIpEdnsController.text = ""; - ednsIpError = null; + _ednsIpError = null; } validateData(); }), @@ -270,13 +316,13 @@ class _DnsServerSettingsScreenState extends State { bottom: 12, right: 16 ), - value: useCustomIpEdns, + value: _useCustomIpEdns, onChanged: (value) => setState(() { - useCustomIpEdns = value; + _useCustomIpEdns = value; _expandableEdnsIp.toggle(); - if (useCustomIpEdns == false) { + if (_useCustomIpEdns == false) { _customIpEdnsController.text = ""; - ednsIpError = null; + _ednsIpError = null; } validateData(); }), @@ -304,7 +350,7 @@ class _DnsServerSettingsScreenState extends State { Radius.circular(10) ) ), - errorText: ednsIpError, + errorText: _ednsIpError, labelText: AppLocalizations.of(context)!.ipAddress, ), ), @@ -316,14 +362,14 @@ class _DnsServerSettingsScreenState extends State { ) ), CustomSwitchListTile( - value: enableDnssec, - onChanged: (value) => setState(() => enableDnssec = value), + value: _enableDnssec, + onChanged: (value) => setState(() => _enableDnssec = value), title: AppLocalizations.of(context)!.enableDnssec, subtitle: AppLocalizations.of(context)!.enableDnssecDescription, ), CustomSwitchListTile( - value: disableIpv6Resolving, - onChanged: (value) => setState(() => disableIpv6Resolving = value), + value: _disableIpv6Resolving, + onChanged: (value) => setState(() => _disableIpv6Resolving = value), title: AppLocalizations.of(context)!.disableResolvingIpv6, subtitle: AppLocalizations.of(context)!.disableResolvingIpv6Description, ), @@ -373,7 +419,7 @@ class _DnsServerSettingsScreenState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: TextFormField( - controller: ipv4controller, + controller: _ipv4controller, onChanged: validateIpv4, decoration: InputDecoration( prefixIcon: const Icon(Icons.link_rounded), @@ -382,7 +428,7 @@ class _DnsServerSettingsScreenState extends State { Radius.circular(10) ) ), - errorText: ipv4error, + errorText: _ipv4error, helperText: AppLocalizations.of(context)!.blockingIpv4Description, helperMaxLines: 10, labelText: AppLocalizations.of(context)!.blockingIpv4, @@ -394,7 +440,7 @@ class _DnsServerSettingsScreenState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: TextFormField( - controller: ipv6controller, + controller: _ipv6controller, onChanged: validateIpv6, decoration: InputDecoration( prefixIcon: const Icon(Icons.link_rounded), @@ -417,7 +463,7 @@ class _DnsServerSettingsScreenState extends State { padding: const EdgeInsets.all(16), child: TextFormField( controller: _ttlController, - onChanged: validateNumber, + onChanged: (v) => setState(() => _ttlError = validateTtl(v)), decoration: InputDecoration( prefixIcon: const Icon(Icons.timer_rounded), border: const OutlineInputBorder( From 1bc1efbe5686e548c7ee013109c7e77bd2b59889 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 3 Feb 2024 19:56:27 +0100 Subject: [PATCH 529/676] Added rate limit whitelist --- lib/l10n/app_en.arb | 6 +- lib/l10n/app_es.arb | 6 +- lib/models/dns_info.dart | 4 + lib/providers/dns_provider.dart | 1 + .../settings/dns/dns_server_settings.dart | 42 +++- .../dns/rate_limit_allowlist_modal.dart | 186 ++++++++++++++++++ 6 files changed, 240 insertions(+), 5 deletions(-) create mode 100644 lib/screens/settings/dns/rate_limit_allowlist_modal.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ab2a561..238b380 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -759,6 +759,10 @@ "removeDomain": "Remove domain", "addDomain": "Add domain", "notLess1Hour": "Time cannot be less than 1 hour", + "rateLimit": "Rate limit", "subnetPrefixLengthIpv4": "Subnet prefix length for IPv4", - "subnetPrefixLengthIpv6": "Subnet prefix length for IPv6" + "subnetPrefixLengthIpv6": "Subnet prefix length for IPv6", + "rateLimitAllowlist": "Rate limit allowlist", + "rateLimitAllowlistDescription": "IP addresses excluded from rate limiting", + "dnsOptions": "DNS options" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 6a701d1..718a093 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -759,6 +759,10 @@ "removeDomain": "Eliminar dominio", "addDomain": "Añadir dominio", "notLess1Hour": "El tiempo no puede ser inferior a 1 hora", + "rateLimit": "Limitación de velocidad", "subnetPrefixLengthIpv4": "Longitud del prefijo de subred para IPv4", - "subnetPrefixLengthIpv6": "Longitud del prefijo de subred para IPv6" + "subnetPrefixLengthIpv6": "Longitud del prefijo de subred para IPv6", + "rateLimitAllowlist": "Lista de permitidos de limitación de velocidad", + "rateLimitAllowlistDescription": "Direcciones IP excluidas de la limitación de velocidad", + "dnsOptions": "Opciones de DNS" } \ No newline at end of file diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index d4152c8..5a53023 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -25,6 +25,7 @@ class DnsInfo { int? blockedResponseTtl; int? ratelimitSubnetLenIpv4; int? ratelimitSubnetLenIpv6; + List? ratelimitWhitelist; DnsInfo({ required this.upstreamDns, @@ -53,6 +54,7 @@ class DnsInfo { required this.blockedResponseTtl, required this.ratelimitSubnetLenIpv4, required this.ratelimitSubnetLenIpv6, + required this.ratelimitWhitelist, }); factory DnsInfo.fromJson(Map json) => DnsInfo( @@ -82,6 +84,7 @@ class DnsInfo { blockedResponseTtl: json["blocked_response_ttl"], ratelimitSubnetLenIpv4: json["ratelimit_subnet_len_ipv4"], ratelimitSubnetLenIpv6: json["ratelimit_subnet_len_ipv6"], + ratelimitWhitelist: json["ratelimit_whitelist"] != null ? List.from(json["ratelimit_whitelist"].map((x) => x)) : [], ); Map toJson() => { @@ -111,5 +114,6 @@ class DnsInfo { "blocked_response_ttl": blockedResponseTtl, "ratelimit_subnet_len_ipv4": ratelimitSubnetLenIpv4, "ratelimit_subnet_len_ipv6": ratelimitSubnetLenIpv6, + "ratelimit_whitelist": ratelimitWhitelist != null ? List.from(ratelimitWhitelist!.map((x) => x)) : null, }; } diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index 9c8d705..198053b 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -164,6 +164,7 @@ class DnsProvider with ChangeNotifier { data.blockedResponseTtl = value['blocked_response_ttl']; data.ratelimitSubnetLenIpv4 = value['ratelimit_subnet_len_ipv4']; data.ratelimitSubnetLenIpv6 = value['ratelimit_subnet_len_ipv6']; + data.ratelimitWhitelist = value['ratelimit_whitelist']; 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 6e747f3..ddae1e3 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -5,6 +5,8 @@ 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/settings/dns/rate_limit_allowlist_modal.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/custom_radio_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; @@ -28,6 +30,7 @@ class _DnsServerSettingsScreenState extends State { String? _ipv4PrefixSubnetError; final _ipv6PrefixSubnetController = TextEditingController(); String? _ipv6PrefixSubnetError; + List _rateLimitAllowlist = []; String? _limitRequestsError; final _expandableCustomEdns = ExpandableController(); final _expandableEdnsIp = ExpandableController(); @@ -147,6 +150,7 @@ class _DnsServerSettingsScreenState extends State { _ipv6PrefixSubnetController.text = dnsProvider.dnsInfo!.ratelimitSubnetLenIpv6 != null ? dnsProvider.dnsInfo!.ratelimitSubnetLenIpv6.toString() : ""; + _rateLimitAllowlist = dnsProvider.dnsInfo!.ratelimitWhitelist ?? []; super.initState(); } @@ -173,6 +177,7 @@ class _DnsServerSettingsScreenState extends State { "blocked_response_ttl": int.tryParse(_ttlController.text), "ratelimit_subnet_len_ipv4": int.tryParse(_ipv4PrefixSubnetController.text), "ratelimit_subnet_len_ipv6": int.tryParse(_ipv6PrefixSubnetController.text), + "ratelimit_whitelist": _rateLimitAllowlist }); processModal.close(); @@ -230,10 +235,14 @@ class _DnsServerSettingsScreenState extends State { ), body: SafeArea( child: ListView( - padding: const EdgeInsets.only(top: 10), + padding: const EdgeInsets.only(top: 0), children: [ + SectionLabel( + label: AppLocalizations.of(context)!.rateLimit, + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 24, top: 8), + ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 24, top: 4), child: TextFormField( controller: _limitRequestsController, onChanged: (v) => setState(() => _limitRequestsError = validateNumber(v)), @@ -251,7 +260,7 @@ class _DnsServerSettingsScreenState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 24), child: TextFormField( controller: _ipv4PrefixSubnetController, onChanged: (v) => setState(() => _ipv4PrefixSubnetError = validateNumber(v)), @@ -287,6 +296,33 @@ class _DnsServerSettingsScreenState extends State { ), ), const SizedBox(height: 16), + CustomListTile( + title: AppLocalizations.of(context)!.rateLimitAllowlist, + subtitle: AppLocalizations.of(context)!.rateLimitAllowlistDescription, + onTap: () => showDialog( + context: context, + builder: (context) => RateLimitAllowlistModal( + values: _rateLimitAllowlist, + onConfirm: (ips) => setState(() => _rateLimitAllowlist = ips) + ), + ), + trailing: _rateLimitAllowlist.isNotEmpty ? Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(40) + ), + child: Text( + _rateLimitAllowlist.length.toString(), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onPrimaryContainer + ), + ), + ) : null, + ), + SectionLabel(label: AppLocalizations.of(context)!.dnsOptions), CustomSwitchListTile( value: _enableEdns, onChanged: (value) => setState(() { diff --git a/lib/screens/settings/dns/rate_limit_allowlist_modal.dart b/lib/screens/settings/dns/rate_limit_allowlist_modal.dart new file mode 100644 index 0000000..e5b678e --- /dev/null +++ b/lib/screens/settings/dns/rate_limit_allowlist_modal.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:uuid/uuid.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class _IpListItemController { + final String id; + final TextEditingController controller; + bool error; + + _IpListItemController({ + required this.id, + required this.controller, + required this.error + }); +} + +class RateLimitAllowlistModal extends StatefulWidget { + final List values; + final void Function(List) onConfirm; + + const RateLimitAllowlistModal({ + super.key, + required this.values, + required this.onConfirm, + }); + + @override + State createState() => _RateLimitAllowlistModalState(); +} + +class _RateLimitAllowlistModalState extends State { + final Uuid uuid = const Uuid(); + List<_IpListItemController> _controllersList = []; + + void _validateIp(String value, _IpListItemController item) { + final regexp = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); + if (regexp.hasMatch(value)) { + setState(() => _controllersList = _controllersList.map((e) { + if (e.id == item.id) { + return _IpListItemController( + id: e.id, + controller: e.controller, + error: false + ); + } + return e; + }).toList()); + } + else { + setState(() => _controllersList = _controllersList.map((e) { + if (e.id == item.id) { + return _IpListItemController( + id: e.id, + controller: e.controller, + error: true + ); + } + return e; + }).toList()); + } + } + + @override + void initState() { + _controllersList = widget.values.map((e) => _IpListItemController( + id: uuid.v4(), + controller: TextEditingController(text: e), + error: false + )).toList(); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + final validData = _controllersList.where((e) => e.error == true).isEmpty; + + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 500), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Center( + child: Icon( + Icons.check_circle_rounded, + size: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.rateLimitAllowlist, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 24, + ), + ), + const SizedBox(height: 16), + ..._controllersList.map((item) => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Row( + children: [ + Expanded( + child: TextFormField( + controller: item.controller, + onChanged: (v) => _validateIp(v, item), + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.ipAddress, + errorText: item.error == true + ? AppLocalizations.of(context)!.invalidIp + : null + ), + keyboardType: TextInputType.number, + ), + ), + const SizedBox(width: 16), + IconButton( + onPressed: () => setState( + () => _controllersList = _controllersList.where((c) => c.id != item.id).toList() + ), + icon: const Icon(Icons.remove_circle_outline_rounded), + tooltip: AppLocalizations.of(context)!.remove, + ) + ], + ), + )), + Center( + child: ElevatedButton.icon( + onPressed: () => setState(() => _controllersList.add( + _IpListItemController( + id: uuid.v4(), + controller: TextEditingController(), + error: false + ), + )), + icon: const Icon(Icons.add_rounded), + label: Text(AppLocalizations.of(context)!.addItem), + ), + ) + ], + ), + ) + ), + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + const SizedBox(width: 8), + TextButton( + onPressed: validData == true + ? () { + widget.onConfirm( + _controllersList.map((e) => e.controller.text).toList() + ); + Navigator.pop(context); + } + : null, + child: Text(AppLocalizations.of(context)!.confirm) + ), + ], + ) + ], + ), + ), + ), + ); + } +} \ No newline at end of file From 2fca44f1957fa26535070e266c7c63489ae91a47 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 3 Feb 2024 20:00:06 +0100 Subject: [PATCH 530/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index c4119e9..32eca7e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.15.1+126 +version: 2.16.0-beta.1+127 environment: sdk: '>=2.18.1 <3.0.0' From c150d2ba230c3ba8cd532f9a2a92d392bbb1663b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 4 Feb 2024 21:23:45 +0100 Subject: [PATCH 531/676] Added edit custom rules --- lib/l10n/app_en.arb | 7 +- lib/l10n/app_es.arb | 7 +- lib/providers/filtering_provider.dart | 17 + lib/screens/filters/add_button.dart | 84 +++- lib/screens/filters/custom_rules_list.dart | 29 +- .../filters/modals/add_custom_rule.dart | 416 ------------------ .../add_custom_rule/add_custom_rule.dart | 326 ++++++++++++++ .../add_custom_rule/custom_rule_docs.dart | 166 +++++++ .../add_custom_rule/edit_custom_rules.dart | 167 +++++++ lib/widgets/tab_content_list.dart | 6 +- 10 files changed, 789 insertions(+), 436 deletions(-) delete mode 100644 lib/screens/filters/modals/add_custom_rule.dart create mode 100644 lib/screens/filters/modals/add_custom_rule/add_custom_rule.dart create mode 100644 lib/screens/filters/modals/add_custom_rule/custom_rule_docs.dart create mode 100644 lib/screens/filters/modals/add_custom_rule/edit_custom_rules.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 238b380..4786d6b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -764,5 +764,10 @@ "subnetPrefixLengthIpv6": "Subnet prefix length for IPv6", "rateLimitAllowlist": "Rate limit allowlist", "rateLimitAllowlistDescription": "IP addresses excluded from rate limiting", - "dnsOptions": "DNS options" + "dnsOptions": "DNS options", + "editor": "Editor", + "editCustomRules": "Edit custom rules", + "savingCustomRules": "Saving custom rules...", + "customRulesUpdatedSuccessfully": "Custom rules updated successfully", + "customRulesNotUpdated": "Custom rules could not be updated" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 718a093..d7ba7a0 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -764,5 +764,10 @@ "subnetPrefixLengthIpv6": "Longitud del prefijo de subred para IPv6", "rateLimitAllowlist": "Lista de permitidos de limitación de velocidad", "rateLimitAllowlistDescription": "Direcciones IP excluidas de la limitación de velocidad", - "dnsOptions": "Opciones de DNS" + "dnsOptions": "Opciones de DNS", + "editor": "Editor", + "editCustomRules": "Editar reglas personalizadas", + "savingCustomRules": "Guardando reglas personalizadas...", + "customRulesUpdatedSuccessfully": "Reglas personalizadas actualizadas correctamente", + "customRulesNotUpdated": "Las reglas personalizadas no pudieron ser actualizadas" } \ No newline at end of file diff --git a/lib/providers/filtering_provider.dart b/lib/providers/filtering_provider.dart index a264429..d43a1b5 100644 --- a/lib/providers/filtering_provider.dart +++ b/lib/providers/filtering_provider.dart @@ -289,6 +289,23 @@ class FilteringProvider with ChangeNotifier { } } + Future setCustomRules(List rules) async { + final newRules = rules.where((r) => r != " " && r != "").toList(); + final result = await _serversProvider!.apiClient2!.setCustomRules(rules: newRules); + + if (result.successful == true) { + Filtering filteringData = filtering!; + filteringData.userRules = newRules; + _filtering = filteringData; + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + Future> addList({required String name, required String url, required String type}) async { final result1 = await _serversProvider!.apiClient2!.addFilteringList( data: { diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index dc652bc..bc5a22f 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -6,7 +6,8 @@ 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/filters/modals/add_custom_rule.dart'; +import 'package:adguard_home_manager/screens/filters/modals/add_custom_rule/edit_custom_rules.dart'; +import 'package:adguard_home_manager/screens/filters/modals/add_custom_rule/add_custom_rule.dart'; import 'package:adguard_home_manager/screens/filters/details/add_list_modal.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; @@ -19,10 +20,10 @@ class AddFiltersButton extends StatelessWidget { final Widget Function(void Function()) widget; const AddFiltersButton({ - Key? key, + super.key, required this.type, required this.widget - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -56,6 +57,31 @@ class AddFiltersButton extends StatelessWidget { } } + void confirmEditCustomRules(List rules) async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.savingCustomRules); + + final result = await filteringProvider.setCustomRules(rules); + + processModal.close(); + + if (!context.mounted) return; + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.customRulesUpdatedSuccessfully, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.customRulesNotUpdated, + color: Colors.red + ); + } + } + void openAddCustomRule() { showGeneralDialog( context: context, @@ -83,6 +109,33 @@ class AddFiltersButton extends StatelessWidget { ); } + void openEditCustomRule() { + showGeneralDialog( + context: context, + barrierColor: !(width > 700 || !(Platform.isAndroid || Platform.isIOS)) + ?Colors.transparent + : Colors.black54, + transitionBuilder: (context, anim1, anim2, child) { + return SlideTransition( + position: Tween( + begin: const Offset(0, 1), + end: const Offset(0, 0) + ).animate( + CurvedAnimation( + parent: anim1, + curve: Curves.easeInOutCubicEmphasized + ) + ), + child: child, + ); + }, + pageBuilder: (context, animation, secondaryAnimation) => EditCustomRules( + fullScreen: !(width > 700 || !(Platform.isAndroid || Platform.isIOS)), + onConfirm: confirmEditCustomRules, + ), + ); + } + void confirmAddList({required String name, required String url, required String type}) async { ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingList); @@ -147,10 +200,25 @@ class AddFiltersButton extends StatelessWidget { } } - return widget( - type == 'blacklist' || type == 'whitelist' - ? () => openAddWhitelistBlacklist() - : () => openAddCustomRule(), - ); + switch (type) { + case 'blacklist': + case 'whitelist': + return widget( + () => openAddWhitelistBlacklist(), + ); + + case 'add_custom_rule': + return widget( + () => openAddCustomRule(), + ); + + case 'edit_custom_rule': + return widget( + () => openEditCustomRule(), + ); + + default: + return const SizedBox(); + } } } \ No newline at end of file diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 8706f1a..25a1d4c 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -20,12 +20,12 @@ class CustomRulesList extends StatefulWidget { final void Function(String) onRemoveCustomRule; const CustomRulesList({ - Key? key, + super.key, required this.loadStatus, required this.scrollController, required this.data, required this.onRemoveCustomRule - }) : super(key: key); + }); @override State createState() => _CustomRulesListState(); @@ -210,13 +210,26 @@ class _CustomRulesListState extends State { ); } }, - fab: AddFiltersButton( - type: 'custom_rule', - widget: (fn) => FloatingActionButton( - onPressed: fn, - child: const Icon(Icons.add), - ), + fab: Column( + children: [ + AddFiltersButton( + type: 'edit_custom_rule', + widget: (fn) => FloatingActionButton.small( + onPressed: fn, + child: const Icon(Icons.edit_rounded), + ), + ), + const SizedBox(height: 16), + AddFiltersButton( + type: 'add_custom_rule', + widget: (fn) => FloatingActionButton( + onPressed: fn, + child: const Icon(Icons.add), + ), + ), + ], ), + heightFabHidden: -120, fabVisible: isVisible, ); } diff --git a/lib/screens/filters/modals/add_custom_rule.dart b/lib/screens/filters/modals/add_custom_rule.dart deleted file mode 100644 index abe68bc..0000000 --- a/lib/screens/filters/modals/add_custom_rule.dart +++ /dev/null @@ -1,416 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:segmented_button_slide/segmented_button_slide.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/functions/open_url.dart'; -import 'package:adguard_home_manager/constants/urls.dart'; - -class AddCustomRule extends StatefulWidget { - final void Function(String) onConfirm; - final bool fullScreen; - - const AddCustomRule({ - super.key, - required this.onConfirm, - required this.fullScreen - }); - - @override - State createState() => _AddCustomRuleState(); -} - -enum BlockingPresets { block, unblock, custom } - -class _AddCustomRuleState extends State { - final TextEditingController domainController = TextEditingController(); - String? domainError; - - BlockingPresets preset = BlockingPresets.block; - - bool addImportant = false; - - bool checkValidValues() { - if ( - domainController.text != '' && - domainError == null - ) { - return true; - } - else { - return false; - } - } - - void validateDomain(String value) { - final domainRegex = RegExp(r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$'); - if (domainRegex.hasMatch(value)) { - setState(() => domainError = null); - } - else { - setState(() => domainError = AppLocalizations.of(context)!.domainNotValid); - } - checkValidValues(); - } - - String buildRule({String?value}) { - String rule = ""; - - String fieldValue = value ?? domainController.text; - - if (preset == BlockingPresets.block) { - rule = "||${fieldValue.trim()}^"; - } - else if (preset == BlockingPresets.unblock) { - rule = "@@||${fieldValue.trim()}^"; - } - else { - rule = fieldValue.trim(); - } - - if (addImportant == true) { - rule = "$rule\$important"; - } - - return rule; - } - - @override - Widget build(BuildContext context) { - - List content() { - return [ - const SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5 - ), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(30), - border: Border.all( - color: Theme.of(context).colorScheme.primary - ) - ), - child: Text( - buildRule(), - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.w500 - ), - ) - ), - ], - ), - Container(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: TextFormField( - controller: domainController, - onChanged: (value) => setState(() => {}), - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - errorText: domainError, - labelText: AppLocalizations.of(context)!.domain, - ), - ), - ), - Container(height: 30), - SegmentedButtonSlide( - entries: [ - SegmentedButtonSlideEntry(label: AppLocalizations.of(context)!.block), - SegmentedButtonSlideEntry(label: AppLocalizations.of(context)!.unblock), - SegmentedButtonSlideEntry(label: AppLocalizations.of(context)!.custom), - ], - selectedEntry: preset.index, - onChange: (v) => setState(() => preset = BlockingPresets.values[v]), - colors: SegmentedButtonSlideColors( - barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), - backgroundSelectedColor: Theme.of(context).colorScheme.primary, - foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, - foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, - hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, - ), - textOverflow: TextOverflow.ellipsis, - fontSize: 14, - height: 40, - margin: const EdgeInsets.symmetric( - horizontal: 24, - ), - ), - Container(height: 20), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => setState(() => addImportant = !addImportant), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 28), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only(left: 10), - child: Text( - AppLocalizations.of(context)!.addImportant, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - Switch( - value: addImportant, - onChanged: (value) => setState(() => addImportant = value), - ) - ], - ), - ), - ), - ), - Container(height: 20), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Card( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - Row( - children: [ - Icon( - Icons.info, - color: Theme.of(context).colorScheme.onSurface - ), - const SizedBox(width: 20), - Text( - AppLocalizations.of(context)!.examples, - style: TextStyle( - fontSize: 18, - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - const SizedBox(height: 20), - SizedBox( - width: double.maxFinite, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "||example.org^", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 5), - Text( - AppLocalizations.of(context)!.example1, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 20), - Text( - "@@||example.org^", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 5), - Text( - AppLocalizations.of(context)!.example2, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 20), - Text( - "! Here goes a comment", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - Text( - "# Also a comment", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 5), - Text( - AppLocalizations.of(context)!.example3, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 20), - Text( - "/REGEX/", - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.primary - ), - ), - const SizedBox(height: 5), - Text( - AppLocalizations.of(context)!.example4, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.primary - ), - ), - ], - ), - ) - ], - ), - ), - ), - ), - Container(height: 20), - Material( - color: Colors.transparent, - child: InkWell( - onTap: () => openUrl(Urls.customRuleDocs), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 10), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only(left: 10), - child: Text( - AppLocalizations.of(context)!.moreInformation, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 15), - child: Icon( - Icons.open_in_new, - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - ), - ), - ), - Container(height: 20) - ]; - } - - if (widget.fullScreen == true) { - return Dialog.fullscreen( - child: Scaffold( - appBar: AppBar( - leading: CloseButton(onPressed: () => Navigator.pop(context)), - title: Text(AppLocalizations.of(context)!.addCustomRule), - actions: [ - IconButton( - onPressed: checkValidValues() == true - ? () { - Navigator.pop(context); - widget.onConfirm(buildRule()); - } - : null, - icon: const Icon(Icons.check) - ), - const SizedBox(width: 10) - ], - ), - body: SafeArea( - child: ListView( - children: content(), - ), - ) - ), - ); - } - else { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.clear_rounded), - tooltip: AppLocalizations.of(context)!.close, - ), - const SizedBox(width: 8), - Text( - AppLocalizations.of(context)!.addCustomRule, - style: const TextStyle( - fontSize: 22 - ), - ), - ], - ), - IconButton( - onPressed: checkValidValues() == true - ? () { - Navigator.pop(context); - widget.onConfirm(buildRule()); - } - : null, - icon: const Icon(Icons.check) - ) - ], - ), - ), - Flexible( - child: SingleChildScrollView( - child: Wrap( - alignment: WrapAlignment.center, - children: content(), - ), - ), - ) - ], - ), - ), - ); - } - } -} \ No newline at end of file diff --git a/lib/screens/filters/modals/add_custom_rule/add_custom_rule.dart b/lib/screens/filters/modals/add_custom_rule/add_custom_rule.dart new file mode 100644 index 0000000..ad43ebb --- /dev/null +++ b/lib/screens/filters/modals/add_custom_rule/add_custom_rule.dart @@ -0,0 +1,326 @@ +import 'package:flutter/material.dart'; +import 'package:segmented_button_slide/segmented_button_slide.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/screens/filters/modals/add_custom_rule/custom_rule_docs.dart'; + +enum _BlockingPresets { block, unblock, custom } + +class AddCustomRule extends StatefulWidget { + final void Function(String) onConfirm; + final bool fullScreen; + + const AddCustomRule({ + super.key, + required this.onConfirm, + required this.fullScreen + }); + + @override + State createState() => _AddCustomRuleState(); +} + +class _AddCustomRuleState extends State { + final TextEditingController _domainController = TextEditingController(); + String? _domainError; + + _BlockingPresets _preset = _BlockingPresets.block; + + bool _addImportant = false; + + bool _checkValidValues() { + if ( + _domainController.text != '' && + _domainError == null + ) { + return true; + } + else { + return false; + } + } + + void validateDomain(String value) { + final domainRegex = RegExp(r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$'); + if (domainRegex.hasMatch(value)) { + setState(() => _domainError = null); + } + else { + setState(() => _domainError = AppLocalizations.of(context)!.domainNotValid); + } + _checkValidValues(); + } + + @override + Widget build(BuildContext context) { + if (widget.fullScreen == true) { + return Dialog.fullscreen( + child: Scaffold( + appBar: AppBar( + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.addCustomRule), + actions: [ + IconButton( + onPressed: _checkValidValues() == true + ? () { + Navigator.pop(context); + widget.onConfirm( + _buildRule( + domainController: _domainController, + important: _addImportant, + preset: _preset + ) + ); + } + : null, + icon: const Icon(Icons.check) + ), + const SizedBox(width: 10) + ], + ), + body: SafeArea( + child: ListView( + children: [ + _CustomRuleEditor( + domainController: _domainController, + domainError: _domainError, + important: _addImportant, + preset: _preset, + setImportant: (v) => setState(() => _addImportant = v), + setPreset: (v) => setState(() => _preset = v), + validateDomain: validateDomain + ) + ] + ), + ) + ), + ); + } + else { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, + ), + const SizedBox(width: 8), + Text( + AppLocalizations.of(context)!.addCustomRule, + style: const TextStyle( + fontSize: 22 + ), + ), + ], + ), + IconButton( + onPressed: _checkValidValues() == true + ? () { + Navigator.pop(context); + widget.onConfirm( + _buildRule( + domainController: _domainController, + important: _addImportant, + preset: _preset + ) + ); + } + : null, + icon: const Icon(Icons.check) + ) + ], + ), + ), + Flexible( + child: SingleChildScrollView( + child: Wrap( + alignment: WrapAlignment.center, + children: [ + _CustomRuleEditor( + domainController: _domainController, + domainError: _domainError, + important: _addImportant, + preset: _preset, + setImportant: (v) => setState(() => _addImportant = v), + setPreset: (v) => setState(() => _preset = v), + validateDomain: validateDomain + ) + ] + ), + ), + ) + ], + ), + ), + ); + } + } +} + +class _CustomRuleEditor extends StatelessWidget { + final TextEditingController domainController; + final String? domainError; + final bool important; + final void Function(bool) setImportant; + final _BlockingPresets preset; + final void Function(_BlockingPresets) setPreset; + final void Function(String) validateDomain; + + const _CustomRuleEditor({ + required this.domainController, + required this.domainError, + required this.important, + required this.setImportant, + required this.preset, + required this.setPreset, + required this.validateDomain, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5 + ), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(30), + border: Border.all( + color: Theme.of(context).colorScheme.primary + ) + ), + child: Text( + _buildRule( + domainController: domainController, + important: important, + preset: preset, + ), + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w500 + ), + ) + ), + ], + ), + Container(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: TextFormField( + controller: domainController, + onChanged: validateDomain, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: domainError, + labelText: AppLocalizations.of(context)!.domain, + ), + ), + ), + Container(height: 30), + SegmentedButtonSlide( + entries: [ + SegmentedButtonSlideEntry(label: AppLocalizations.of(context)!.block), + SegmentedButtonSlideEntry(label: AppLocalizations.of(context)!.unblock), + SegmentedButtonSlideEntry(label: AppLocalizations.of(context)!.custom), + ], + selectedEntry: preset.index, + onChange: (v) => setPreset(_BlockingPresets.values[v]), + colors: SegmentedButtonSlideColors( + barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), + backgroundSelectedColor: Theme.of(context).colorScheme.primary, + foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, + foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, + hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, + ), + textOverflow: TextOverflow.ellipsis, + fontSize: 14, + height: 40, + margin: const EdgeInsets.symmetric( + horizontal: 24, + ), + ), + Container(height: 20), + Material( + color: Colors.transparent, + child: InkWell( + onTap: () => setImportant(!important), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 28), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 10), + child: Text( + AppLocalizations.of(context)!.addImportant, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ), + Switch( + value: important, + onChanged: setImportant, + ) + ], + ), + ), + ), + ), + Container(height: 20), + const CustomRuleDocs(), + Container(height: 20) + ] + ); + } +} + + String _buildRule({ + String? value, + required TextEditingController domainController, + required _BlockingPresets preset, + required bool important +}) { + String rule = ""; + String fieldValue = value ?? domainController.text; + if (preset == _BlockingPresets.block) { + rule = "||${fieldValue.trim()}^"; + } + else if (preset == _BlockingPresets.unblock) { + rule = "@@||${fieldValue.trim()}^"; + } + else { + rule = fieldValue.trim(); + } + if (important == true) { + rule = "$rule\$important"; + } + return rule; + } \ No newline at end of file diff --git a/lib/screens/filters/modals/add_custom_rule/custom_rule_docs.dart b/lib/screens/filters/modals/add_custom_rule/custom_rule_docs.dart new file mode 100644 index 0000000..3d2c359 --- /dev/null +++ b/lib/screens/filters/modals/add_custom_rule/custom_rule_docs.dart @@ -0,0 +1,166 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/constants/urls.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; + +class CustomRuleDocs extends StatelessWidget { + const CustomRuleDocs({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + Row( + children: [ + Icon( + Icons.info, + color: Theme.of(context).colorScheme.onSurface + ), + const SizedBox(width: 20), + Text( + AppLocalizations.of(context)!.examples, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + const SizedBox(height: 20), + SizedBox( + width: double.maxFinite, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "||example.org^", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 5), + Text( + AppLocalizations.of(context)!.example1, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 20), + Text( + "@@||example.org^", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 5), + Text( + AppLocalizations.of(context)!.example2, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 20), + Text( + "! Here goes a comment", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + Text( + "# Also a comment", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 5), + Text( + AppLocalizations.of(context)!.example3, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 20), + Text( + "/REGEX/", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.primary + ), + ), + const SizedBox(height: 5), + Text( + AppLocalizations.of(context)!.example4, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.primary + ), + ), + ], + ), + ) + ], + ), + ), + ), + ), + Container(height: 8), + Material( + color: Colors.transparent, + child: InkWell( + onTap: () => openUrl(Urls.customRuleDocs), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 10), + child: Text( + AppLocalizations.of(context)!.moreInformation, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 15), + child: Icon( + Icons.open_in_new, + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + ), + ), + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/filters/modals/add_custom_rule/edit_custom_rules.dart b/lib/screens/filters/modals/add_custom_rule/edit_custom_rules.dart new file mode 100644 index 0000000..e1fc1d1 --- /dev/null +++ b/lib/screens/filters/modals/add_custom_rule/edit_custom_rules.dart @@ -0,0 +1,167 @@ +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/filters/modals/add_custom_rule/custom_rule_docs.dart'; + +import 'package:adguard_home_manager/providers/filtering_provider.dart'; + +class EditCustomRules extends StatefulWidget { + final bool fullScreen; + final void Function(List) onConfirm; + + const EditCustomRules({ + super.key, + required this.fullScreen, + required this.onConfirm, + }); + + @override + State createState() => _EditCustomRulesState(); +} + +class _EditCustomRulesState extends State { + final _fieldController = TextEditingController(); + + @override + void initState() { + final filteringProvider = Provider.of(context, listen: false); + print(filteringProvider.filtering!.userRules); + if (filteringProvider.filtering != null) { + _fieldController.text = filteringProvider.filtering!.userRules.join("\n"); + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { + if (widget.fullScreen == true) { + return Dialog.fullscreen( + child: Scaffold( + appBar: AppBar( + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.editCustomRules), + actions: [ + IconButton( + onPressed: () { + Navigator.pop(context); + widget.onConfirm(_fieldController.text.split("\n")); + }, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 10) + ], + ), + body: SafeArea( + child: ListView( + children: [ + _CustomRulesRawEditor(fieldController: _fieldController) + ] + ), + ) + ), + ); + } + else { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded), + tooltip: AppLocalizations.of(context)!.close, + ), + const SizedBox(width: 8), + Text( + AppLocalizations.of(context)!.addCustomRule, + style: const TextStyle( + fontSize: 22 + ), + ), + ], + ), + IconButton( + onPressed: () { + Navigator.pop(context); + widget.onConfirm(_fieldController.text.split("\n")); + }, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ) + ], + ), + ), + Flexible( + child: SingleChildScrollView( + child: Wrap( + alignment: WrapAlignment.center, + children: [ + _CustomRulesRawEditor(fieldController: _fieldController) + ] + ), + ), + ) + ], + ), + ), + ); + } + } +} + +class _CustomRulesRawEditor extends StatelessWidget { + final TextEditingController fieldController; + + const _CustomRulesRawEditor({ + required this.fieldController + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + const SizedBox(height: 24), + SizedBox( + height: 300, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 28), + child: TextField( + controller: fieldController, + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.rules, + floatingLabelBehavior: FloatingLabelBehavior.always + ), + autocorrect: false, + expands: true, + minLines: null, + maxLines: null, + textAlignVertical: TextAlignVertical.top, + ), + ), + ), + const SizedBox(height: 24), + const CustomRuleDocs(), + const SizedBox(height: 16), + ], + ); + } +} \ No newline at end of file diff --git a/lib/widgets/tab_content_list.dart b/lib/widgets/tab_content_list.dart index 92b7913..0e09a4f 100644 --- a/lib/widgets/tab_content_list.dart +++ b/lib/widgets/tab_content_list.dart @@ -17,6 +17,7 @@ class CustomTabContentList extends StatelessWidget { final bool? fabVisible; final bool? noSliver; final EdgeInsets? listPadding; + final double? heightFabHidden; const CustomTabContentList({ super.key, @@ -31,7 +32,8 @@ class CustomTabContentList extends StatelessWidget { this.fab, this.fabVisible, this.noSliver, - this.listPadding + this.listPadding, + this.heightFabHidden, }); @override @@ -150,7 +152,7 @@ class CustomTabContentList extends StatelessWidget { bottom: fabVisible != null && fabVisible == true ? appConfigProvider.showingSnackbar ? 90 : 20 - : -90, + : (heightFabHidden ?? -90), right: 20, child: SafeArea(child: fab!) ), From ed0bc6528569569e4d7b11a8145ed6905035493d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 4 Feb 2024 21:28:08 +0100 Subject: [PATCH 532/676] Bug fixes --- lib/models/clients.dart | 4 +++- lib/models/server_status.dart | 2 +- lib/screens/settings/logs_settings/config_widgets.dart | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 2ebcccd..9527804 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -130,7 +130,9 @@ class Client { ignoreStatistics: json["ignore_statistics"], upstreamsCacheEnabled: json["upstreams_cache_enabled"], upstreamsCacheSize: json["upstreams_cache_size"], - blockedServicesSchedule: BlockedServicesSchedule.fromJson(json["blocked_services_schedule"]) + blockedServicesSchedule: json["blocked_services_schedule"] != null + ? BlockedServicesSchedule.fromJson(json["blocked_services_schedule"]) + : null ); Map toJson() => { diff --git a/lib/models/server_status.dart b/lib/models/server_status.dart index fb7c1b4..16e20b4 100644 --- a/lib/models/server_status.dart +++ b/lib/models/server_status.dart @@ -66,6 +66,6 @@ class ServerStatus { safeSearchPixabay: json['safeSearch']['pixabay'], safeSearchYandex: json['safeSearch']['yandex'], safeSearchYoutube: json['safeSearch']['youtube'], - dhcpAvailable: json['status']['dhcp_available'] + dhcpAvailable: json['status']['dhcp_available'] ?? false ); } \ No newline at end of file diff --git a/lib/screens/settings/logs_settings/config_widgets.dart b/lib/screens/settings/logs_settings/config_widgets.dart index 5896a2b..002fd96 100644 --- a/lib/screens/settings/logs_settings/config_widgets.dart +++ b/lib/screens/settings/logs_settings/config_widgets.dart @@ -92,7 +92,7 @@ class LogsConfigOptions extends StatelessWidget { child: Text(dropdownItemTranslation[item.key]), )).toList(), value: retentionTime, - onChanged: (value) => updateRetentionTime(value as double), + onChanged: (value) => updateRetentionTime(double.tryParse(value.toString())), decoration: InputDecoration( border: const OutlineInputBorder( borderRadius: BorderRadius.all( From 3e152db6ac9c329dc4f1dee13dfce2701329cac2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 7 Feb 2024 19:46:35 +0100 Subject: [PATCH 533/676] Added show and hide top items --- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- .../general_settings/general_settings.dart | 6 +- .../reorderable_top_items_home.dart | 174 ++++++++---------- .../show_hide_top_items_list.dart | 87 +++++++++ .../top_items_list_settings.dart | 131 +++++++++++++ lib/widgets/custom_switch_list_tile.dart | 15 +- 7 files changed, 317 insertions(+), 104 deletions(-) rename lib/screens/settings/general_settings/{ => top_items_list}/reorderable_top_items_home.dart (62%) create mode 100644 lib/screens/settings/general_settings/top_items_list/show_hide_top_items_list.dart create mode 100644 lib/screens/settings/general_settings/top_items_list/top_items_list_settings.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 4786d6b..6bb805e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -769,5 +769,7 @@ "editCustomRules": "Edit custom rules", "savingCustomRules": "Saving custom rules...", "customRulesUpdatedSuccessfully": "Custom rules updated successfully", - "customRulesNotUpdated": "Custom rules could not be updated" + "customRulesNotUpdated": "Custom rules could not be updated", + "reorder": "Reorder", + "showHide": "Show/hide" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index d7ba7a0..afe0758 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -769,5 +769,7 @@ "editCustomRules": "Editar reglas personalizadas", "savingCustomRules": "Guardando reglas personalizadas...", "customRulesUpdatedSuccessfully": "Reglas personalizadas actualizadas correctamente", - "customRulesNotUpdated": "Las reglas personalizadas no pudieron ser actualizadas" + "customRulesNotUpdated": "Las reglas personalizadas no pudieron ser actualizadas", + "reorder": "Reordenar", + "showHide": "Mostrar/ocultar" } \ No newline at end of file diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index fb0560c..7439353 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -8,7 +8,7 @@ import 'package:provider/provider.dart'; import 'package:store_checker/store_checker.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/settings/general_settings/reorderable_top_items_home.dart'; +import 'package:adguard_home_manager/screens/settings/general_settings/top_items_list/top_items_list_settings.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; @@ -199,10 +199,10 @@ class _GeneralSettingsState extends State { title: AppLocalizations.of(context)!.topItemsOrder, subtitle: AppLocalizations.of(context)!.topItemsOrderDescription, onTap: () => widget.splitView == true - ? SplitView.of(context).push(const ReorderableTopItemsHome()) + ? SplitView.of(context).push(const TopItemsListSettings()) : Navigator.of(context).push( MaterialPageRoute( - builder: (context) => const ReorderableTopItemsHome() + builder: (context) => const TopItemsListSettings() ) ) ), diff --git a/lib/screens/settings/general_settings/reorderable_top_items_home.dart b/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart similarity index 62% rename from lib/screens/settings/general_settings/reorderable_top_items_home.dart rename to lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart index 46e3a58..cdb39b7 100644 --- a/lib/screens/settings/general_settings/reorderable_top_items_home.dart +++ b/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_reorderable_list/flutter_reorderable_list.dart' as reorderable_list; @@ -8,8 +7,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/functions/desktop_mode.dart'; -import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -29,7 +26,14 @@ enum DraggingMode { } class ReorderableTopItemsHome extends StatefulWidget { - const ReorderableTopItemsHome({super.key}); + final List persistHomeTopItems; + final void Function(List value) setPersistHomeTopItems; + + const ReorderableTopItemsHome({ + super.key, + required this.persistHomeTopItems, + required this.setPersistHomeTopItems, + }); @override State createState() => _ReorderableTopItemsHomeState(); @@ -37,7 +41,6 @@ class ReorderableTopItemsHome extends StatefulWidget { class _ReorderableTopItemsHomeState extends State { List homeTopItemsList = []; - List persistHomeTopItemsList = []; List<_ItemData> renderItems = []; int _indexOfKey(Key key) { @@ -63,7 +66,7 @@ class _ReorderableTopItemsHomeState extends State { void _reorderDone(Key item) { renderItems[_indexOfKey(item)]; - setState(() => persistHomeTopItemsList = homeTopItemsList); + widget.setPersistHomeTopItems(homeTopItemsList); } List reorderEnumItems(int oldIndex, int newIndex) { @@ -75,10 +78,8 @@ class _ReorderableTopItemsHomeState extends State { @override void initState() { - final appConfigProvider = Provider.of(context, listen: false); - homeTopItemsList = appConfigProvider.homeTopItemsOrder; - persistHomeTopItemsList = appConfigProvider.homeTopItemsOrder; - renderItems = appConfigProvider.homeTopItemsOrder.asMap().entries.map( + homeTopItemsList = widget.persistHomeTopItems; + renderItems = widget.persistHomeTopItems.asMap().entries.map( (e) => _ItemData( key: ValueKey(e.key), title: e.value, @@ -136,99 +137,80 @@ class _ReorderableTopItemsHomeState extends State { } } - void saveSettings() async { - final result = await appConfigProvider.setHomeTopItemsOrder(homeTopItemsList); - if (!mounted) return; - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.settingsSaved, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.settingsNotSaved, - color: Colors.red - ); - } - } + final draggingMode = Platform.isAndroid ? DraggingMode.android : DraggingMode.iOS; - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.topItemsOrder), - surfaceTintColor: isDesktop(width) ? Colors.transparent : null, - actions: [ - IconButton( - onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList) - ? () => saveSettings() - : null, - icon: const Icon(Icons.save_rounded), - tooltip: AppLocalizations.of(context)!.save, - ), - const SizedBox(width: 8) - ], - ), - body: Column( - children: [ - Card( - margin: const EdgeInsets.all(16), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Icon( - Icons.info_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(width: 16), - Flexible( - child: Text(AppLocalizations.of(context)!.topItemsReorderInfo) - ) - ], - ), - ), - ), - Expanded( - child: reorderable_list.ReorderableList( - onReorder: _reorderCallback, - onReorderDone: _reorderDone, - child: ListView.builder( - itemBuilder: (context, index) => reorderable_list.ReorderableItem( - key: renderItems[index].key, - childBuilder: (context, state) { - if (draggingMode == DraggingMode.android) { - return reorderable_list.DelayedReorderableListener( - child: _Tile( - draggingMode: draggingMode, - isFirst: index == 0, - isLast: index == renderItems.length - 1, - state: state, - tileWidget: tile(renderItems[index].title), + return SafeArea( + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + Card( + margin: const EdgeInsets.all(16), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon( + Icons.info_rounded, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ); - } - else { - return _Tile( - draggingMode: draggingMode, - isFirst: index == 0, - isLast: index == renderItems.length - 1, - state: state, - tileWidget: tile(renderItems[index].title), - ); - } - }, + const SizedBox(width: 16), + Flexible( + child: Text(AppLocalizations.of(context)!.topItemsReorderInfo) + ) + ], + ), + ), ), - itemCount: renderItems.length, - ) - ), - ), - ], + reorderable_list.ReorderableList( + onReorder: _reorderCallback, + onReorderDone: _reorderDone, + child: ListView.builder( + primary: false, + shrinkWrap: true, + padding: const EdgeInsets.only(top: 0), + itemBuilder: (context, index) => reorderable_list.ReorderableItem( + key: renderItems[index].key, + childBuilder: (context, state) { + if (draggingMode == DraggingMode.android) { + return reorderable_list.DelayedReorderableListener( + child: _Tile( + draggingMode: draggingMode, + isFirst: index == 0, + isLast: index == renderItems.length - 1, + state: state, + tileWidget: tile(renderItems[index].title), + ), + ); + } + else { + return _Tile( + draggingMode: draggingMode, + isFirst: index == 0, + isLast: index == renderItems.length - 1, + state: state, + tileWidget: tile(renderItems[index].title), + ); + } + }, + ), + itemCount: renderItems.length, + ) + ), + ] + ) + ], + ), ), ); } diff --git a/lib/screens/settings/general_settings/top_items_list/show_hide_top_items_list.dart b/lib/screens/settings/general_settings/top_items_list/show_hide_top_items_list.dart new file mode 100644 index 0000000..3088692 --- /dev/null +++ b/lib/screens/settings/general_settings/top_items_list/show_hide_top_items_list.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; + +class ShowHideTopItemsList extends StatelessWidget { + final List enabledHomeTopItems; + final void Function(List) setEnabledHomeTopItems; + + const ShowHideTopItemsList({ + super.key, + required this.enabledHomeTopItems, + required this.setEnabledHomeTopItems, + }); + + @override + Widget build(BuildContext context) { + const padding = EdgeInsets.symmetric(horizontal: 16, vertical: 8); + + void updateValue(HomeTopItems value, bool newStatus) { + if (newStatus == true) { + setEnabledHomeTopItems([ + ...enabledHomeTopItems, + value + ]); + } + else { + setEnabledHomeTopItems(enabledHomeTopItems.where((e) => e != value).toList()); + } + } + + return SafeArea( + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + const SizedBox(height: 8), + CustomSwitchListTile( + value: enabledHomeTopItems.contains(HomeTopItems.queriedDomains), + onChanged: (v) => updateValue(HomeTopItems.queriedDomains, v), + title: AppLocalizations.of(context)!.topQueriedDomains, + leadingIcon: Icons.install_desktop_outlined, + padding: padding, + ), + CustomSwitchListTile( + value: enabledHomeTopItems.contains(HomeTopItems.blockedDomains), + onChanged: (v) => updateValue(HomeTopItems.blockedDomains, v), + title: AppLocalizations.of(context)!.topBlockedDomains, + leadingIcon: Icons.block_rounded, + padding: padding, + ), + CustomSwitchListTile( + value: enabledHomeTopItems.contains(HomeTopItems.recurrentClients), + onChanged: (v) => updateValue(HomeTopItems.recurrentClients, v), + title: AppLocalizations.of(context)!.topClients, + leadingIcon: Icons.smartphone_rounded, + padding: padding, + ), + CustomSwitchListTile( + value: enabledHomeTopItems.contains(HomeTopItems.topUpstreams), + onChanged: (v) => updateValue(HomeTopItems.topUpstreams, v), + title: AppLocalizations.of(context)!.topUpstreams, + leadingIcon: Icons.upload_file_rounded, + padding: padding, + ), + CustomSwitchListTile( + value: enabledHomeTopItems.contains(HomeTopItems.avgUpstreamResponseTime), + onChanged: (v) => updateValue(HomeTopItems.avgUpstreamResponseTime, v), + title: AppLocalizations.of(context)!.averageUpstreamResponseTime, + leadingIcon: Icons.timer_rounded, + padding: padding, + ), + ] + ) + ], + ), + ) + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/general_settings/top_items_list/top_items_list_settings.dart b/lib/screens/settings/general_settings/top_items_list/top_items_list_settings.dart new file mode 100644 index 0000000..9e9c836 --- /dev/null +++ b/lib/screens/settings/general_settings/top_items_list/top_items_list_settings.dart @@ -0,0 +1,131 @@ +import 'package:flutter/foundation.dart'; +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/settings/general_settings/top_items_list/show_hide_top_items_list.dart'; +import 'package:adguard_home_manager/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; + +class TopItemsListSettings extends StatefulWidget { + const TopItemsListSettings({super.key}); + + @override + State createState() => _TopItemsListSettingsState(); +} + +class _TopItemsListSettingsState extends State with TickerProviderStateMixin { + late TabController _tabController; + + List persistHomeTopItemsList = []; + + @override + void initState() { + final appConfigProvider = Provider.of(context, listen: false); + persistHomeTopItemsList = appConfigProvider.homeTopItemsOrder; + + super.initState(); + + _tabController = TabController(length: 2, vsync: this); + } + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + + final width = MediaQuery.of(context).size.width; + + void saveSettings() async { + final result = await appConfigProvider.setHomeTopItemsOrder(persistHomeTopItemsList); + if (!context.mounted) return; + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.settingsSaved, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.settingsNotSaved, + color: Colors.red + ); + } + } + + return Scaffold( + body: DefaultTabController( + length: 2, + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, + title: Text(AppLocalizations.of(context)!.topItemsOrder), + actions: [ + IconButton( + onPressed: !listEquals(appConfigProvider.homeTopItemsOrder, persistHomeTopItemsList) + ? () => saveSettings() + : null, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 8) + ], + bottom: TabBar( + controller: _tabController, + unselectedLabelColor: Theme.of(context).colorScheme.onSurfaceVariant, + tabs: [ + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.reorder_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.reorder) + ], + ), + ), + Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.remove_red_eye_rounded), + const SizedBox(width: 8), + Text(AppLocalizations.of(context)!.showHide) + ], + ), + ), + ] + ) + ), + ) + ], + body: TabBarView( + controller: _tabController, + children: [ + ReorderableTopItemsHome( + persistHomeTopItems: persistHomeTopItemsList, + setPersistHomeTopItems: (v) => setState(() => persistHomeTopItemsList = v), + ), + ShowHideTopItemsList( + enabledHomeTopItems: persistHomeTopItemsList, + setEnabledHomeTopItems: (v) => setState(() => persistHomeTopItemsList = v), + ) + ] + ) + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/custom_switch_list_tile.dart b/lib/widgets/custom_switch_list_tile.dart index 84db718..84e65c5 100644 --- a/lib/widgets/custom_switch_list_tile.dart +++ b/lib/widgets/custom_switch_list_tile.dart @@ -7,16 +7,18 @@ class CustomSwitchListTile extends StatelessWidget { final String? subtitle; final bool? disabled; final EdgeInsets? padding; + final IconData? leadingIcon; const CustomSwitchListTile({ - Key? key, + super.key, required this.value, required this.onChanged, required this.title, this.disabled, this.subtitle, - this.padding - }) : super(key: key); + this.padding, + this.leadingIcon, + }); @override Widget build(BuildContext context) { @@ -33,6 +35,13 @@ class CustomSwitchListTile extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + if (leadingIcon != null) ...[ + Icon( + leadingIcon, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(width: 16), + ], Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, From 5ca3c04c89fedb5e469bab323d8f979465d96376 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 7 Feb 2024 19:49:25 +0100 Subject: [PATCH 534/676] Improvements --- .../reorderable_top_items_home.dart | 115 +++++++++--------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart b/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart index cdb39b7..dc513a7 100644 --- a/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart +++ b/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart @@ -1,14 +1,12 @@ import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; import 'package:flutter_reorderable_list/flutter_reorderable_list.dart' as reorderable_list; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; class _ItemData { final HomeTopItems title; @@ -90,55 +88,7 @@ class _ReorderableTopItemsHomeState extends State { } @override - Widget build(BuildContext context) { - final appConfigProvider = Provider.of(context); - - final width = MediaQuery.of(context).size.width; - - Widget tile(HomeTopItems title) { - switch (title) { - case HomeTopItems.queriedDomains: - return CustomListTile( - title: AppLocalizations.of(context)!.topQueriedDomains, - icon: Icons.install_desktop_outlined, - padding: const EdgeInsets.all(16) - ); - - case HomeTopItems.blockedDomains: - return CustomListTile( - title: AppLocalizations.of(context)!.topBlockedDomains, - icon: Icons.block_rounded, - padding: const EdgeInsets.all(16) - ); - - case HomeTopItems.recurrentClients: - return CustomListTile( - title: AppLocalizations.of(context)!.topClients, - icon: Icons.smartphone_rounded, - padding: const EdgeInsets.all(16) - ); - - case HomeTopItems.topUpstreams: - return CustomListTile( - title: AppLocalizations.of(context)!.topUpstreams, - icon: Icons.upload_file_rounded, - padding: const EdgeInsets.all(16) - ); - - case HomeTopItems.avgUpstreamResponseTime: - return CustomListTile( - title: AppLocalizations.of(context)!.averageUpstreamResponseTime, - icon: Icons.timer_rounded, - padding: const EdgeInsets.all(16) - ); - - default: - return const SizedBox(); - } - } - - - + Widget build(BuildContext context) { final draggingMode = Platform.isAndroid ? DraggingMode.android : DraggingMode.iOS; @@ -184,22 +134,22 @@ class _ReorderableTopItemsHomeState extends State { childBuilder: (context, state) { if (draggingMode == DraggingMode.android) { return reorderable_list.DelayedReorderableListener( - child: _Tile( + child: _ReorderableTile( draggingMode: draggingMode, isFirst: index == 0, isLast: index == renderItems.length - 1, state: state, - tileWidget: tile(renderItems[index].title), + tileWidget: _TopItemTile(tile: renderItems[index].title), ), ); } else { - return _Tile( + return _ReorderableTile( draggingMode: draggingMode, isFirst: index == 0, isLast: index == renderItems.length - 1, state: state, - tileWidget: tile(renderItems[index].title), + tileWidget: _TopItemTile(tile: renderItems[index].title), ); } }, @@ -216,14 +166,65 @@ class _ReorderableTopItemsHomeState extends State { } } -class _Tile extends StatelessWidget { +class _TopItemTile extends StatelessWidget { + final HomeTopItems tile; + + const _TopItemTile({ + required this.tile, + }); + + @override + Widget build(BuildContext context) { + switch (tile) { + case HomeTopItems.queriedDomains: + return CustomListTile( + title: AppLocalizations.of(context)!.topQueriedDomains, + icon: Icons.install_desktop_outlined, + padding: const EdgeInsets.all(16) + ); + + case HomeTopItems.blockedDomains: + return CustomListTile( + title: AppLocalizations.of(context)!.topBlockedDomains, + icon: Icons.block_rounded, + padding: const EdgeInsets.all(16) + ); + + case HomeTopItems.recurrentClients: + return CustomListTile( + title: AppLocalizations.of(context)!.topClients, + icon: Icons.smartphone_rounded, + padding: const EdgeInsets.all(16) + ); + + case HomeTopItems.topUpstreams: + return CustomListTile( + title: AppLocalizations.of(context)!.topUpstreams, + icon: Icons.upload_file_rounded, + padding: const EdgeInsets.all(16) + ); + + case HomeTopItems.avgUpstreamResponseTime: + return CustomListTile( + title: AppLocalizations.of(context)!.averageUpstreamResponseTime, + icon: Icons.timer_rounded, + padding: const EdgeInsets.all(16) + ); + + default: + return const SizedBox(); + } + } +} + +class _ReorderableTile extends StatelessWidget { final Widget tileWidget; final bool isFirst; final bool isLast; final reorderable_list.ReorderableItemState state; final DraggingMode draggingMode; - const _Tile({ + const _ReorderableTile({ required this.tileWidget, required this.isFirst, required this.isLast, From 11dd6b23bd806cb6f0417580048f7d0c3d7753a5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 7 Feb 2024 19:55:44 +0100 Subject: [PATCH 535/676] Added no items to reorder message --- lib/l10n/app_en.arb | 3 ++- lib/l10n/app_es.arb | 3 ++- lib/providers/app_config_provider.dart | 7 +------ .../reorderable_top_items_home.dart | 21 ++++++++++++++++++- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 6bb805e..a928180 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -771,5 +771,6 @@ "customRulesUpdatedSuccessfully": "Custom rules updated successfully", "customRulesNotUpdated": "Custom rules could not be updated", "reorder": "Reorder", - "showHide": "Show/hide" + "showHide": "Show/hide", + "noElementsReorderMessage": "Enable some elements on the show/hide tab to reorder them here." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index afe0758..b744b99 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -771,5 +771,6 @@ "customRulesUpdatedSuccessfully": "Reglas personalizadas actualizadas correctamente", "customRulesNotUpdated": "Las reglas personalizadas no pudieron ser actualizadas", "reorder": "Reordenar", - "showHide": "Mostrar/ocultar" + "showHide": "Mostrar/ocultar", + "noElementsReorderMessage": "Activa algunos elementos en la pestaña de mostrar/ocultar para reordenarlos aquí." } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 6b73520..f31eb3c 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -370,7 +370,7 @@ class AppConfigProvider with ChangeNotifier { _hideServerAddress = sharedPreferencesInstance.getBool('hideServerAddress') ?? false; if (sharedPreferencesInstance.getStringList('homeTopItemsOrder') != null) { try { - final itemsOrder = List.from( + _homeTopItemsOrder = List.from( List.from(sharedPreferencesInstance.getStringList('homeTopItemsOrder')!).map((e) { switch (e) { case 'queriedDomains': @@ -393,11 +393,6 @@ class AppConfigProvider with ChangeNotifier { } }).where((e) => e != null).toList() ); - final missingItems = homeTopItemsDefaultOrder.where((e) => !itemsOrder.contains(e)); - _homeTopItemsOrder = [ - ...itemsOrder, - ...missingItems - ]; } catch (e) { Sentry.captureException(e); _homeTopItemsOrder = homeTopItemsDefaultOrder; diff --git a/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart b/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart index dc513a7..332a64b 100644 --- a/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart +++ b/lib/screens/settings/general_settings/top_items_list/reorderable_top_items_home.dart @@ -122,7 +122,26 @@ class _ReorderableTopItemsHomeState extends State { ), ), ), - reorderable_list.ReorderableList( + if (homeTopItemsList.isEmpty) Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Center( + child: Text( + AppLocalizations.of(context)!.noElementsReorderMessage, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), + ], + ), + ), + if (homeTopItemsList.isNotEmpty) reorderable_list.ReorderableList( onReorder: _reorderCallback, onReorderDone: _reorderDone, child: ListView.builder( From b977aed9bdff67a5f2cfee888d07431569015632 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 7 Feb 2024 19:57:54 +0100 Subject: [PATCH 536/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 32eca7e..c9ad2f4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.16.0-beta.1+127 +version: 2.16.0-beta.2+128 environment: sdk: '>=2.18.1 <3.0.0' From 3f057062f12a56d4906d160077f8d21cee9fe307 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 7 Feb 2024 23:35:20 +0100 Subject: [PATCH 537/676] Added plain dns control --- lib/l10n/app_en.arb | 4 +++- lib/l10n/app_es.arb | 4 +++- lib/models/encryption.dart | 4 ++++ lib/screens/settings/encryption/encryption.dart | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index a928180..1869104 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -772,5 +772,7 @@ "customRulesNotUpdated": "Custom rules could not be updated", "reorder": "Reorder", "showHide": "Show/hide", - "noElementsReorderMessage": "Enable some elements on the show/hide tab to reorder them here." + "noElementsReorderMessage": "Enable some elements on the show/hide tab to reorder them here.", + "enablePlainDns": "Enable plain DNS", + "enablePlainDnsDescription": "Plain DNS is enabled by default. You can disable it to force all devices to use encrypted DNS. To do this, you must enable at least one encrypted DNS protocol." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index b744b99..7070fea 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -772,5 +772,7 @@ "customRulesNotUpdated": "Las reglas personalizadas no pudieron ser actualizadas", "reorder": "Reordenar", "showHide": "Mostrar/ocultar", - "noElementsReorderMessage": "Activa algunos elementos en la pestaña de mostrar/ocultar para reordenarlos aquí." + "noElementsReorderMessage": "Activa algunos elementos en la pestaña de mostrar/ocultar para reordenarlos aquí.", + "enablePlainDns": "Activar DNS simple (sin cifrado)", + "enablePlainDnsDescription": "El DNS simple (sin cifrado) está activado de forma predeterminada. Puedes desactivarlo para obligar a todos los dispositivos a utilizar DNS cifrado. Para ello, debes habilitar al menos un protocolo DNS cifrado." } \ No newline at end of file diff --git a/lib/models/encryption.dart b/lib/models/encryption.dart index 1315868..5fff3e0 100644 --- a/lib/models/encryption.dart +++ b/lib/models/encryption.dart @@ -39,6 +39,7 @@ class EncryptionData { final String certificatePath; final String privateKeyPath; final bool privateKeySaved; + final bool? servePlainDns; EncryptionData({ required this.validCert, @@ -65,6 +66,7 @@ class EncryptionData { required this.certificatePath, required this.privateKeyPath, required this.privateKeySaved, + required this.servePlainDns, }); @@ -93,6 +95,7 @@ class EncryptionData { certificatePath: json["certificate_path"], privateKeyPath: json["private_key_path"], privateKeySaved: json["private_key_saved"], + servePlainDns: json["serve_plain_dns"], ); Map toJson() => { @@ -120,6 +123,7 @@ class EncryptionData { "certificate_path": certificatePath, "private_key_path": privateKeyPath, "private_key_saved": privateKeySaved, + "serve_plain_dns": servePlainDns, }; } diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 1efdad4..1929ef7 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/screens/settings/encryption/status.dart'; @@ -35,6 +36,8 @@ class _EncryptionSettingsState extends State { bool enabled = false; + bool? _plainDns; + final TextEditingController domainNameController = TextEditingController(); String? domainError; @@ -112,6 +115,7 @@ class _EncryptionSettingsState extends State { privateKeyPathController.text = data.privateKeyPath; } usePreviouslySavedKey = data.privateKeySaved; + _plainDns = data.servePlainDns; loadStatus = LoadStatus.loaded; }); } @@ -224,6 +228,7 @@ class _EncryptionSettingsState extends State { "private_key_saved": usePreviouslySavedKey, "certificate_path": certificatePathController.text, "private_key_path": privateKeyPathController.text, + "serve_plain_dns": _plainDns } ); @@ -271,6 +276,7 @@ class _EncryptionSettingsState extends State { "private_key_saved": false, "certificate_path": "", "private_key_path": "", + "serve_plain_dns": true } ); if (!mounted) return; @@ -372,6 +378,15 @@ class _EncryptionSettingsState extends State { onEditValidate(); } ), + if (_plainDns != null) ...[ + const SizedBox(height: 8), + CustomCheckboxListTile( + value: _plainDns!, + onChanged: (v) => setState(() => _plainDns = v), + title: AppLocalizations.of(context)!.enablePlainDns, + subtitle: AppLocalizations.of(context)!.enablePlainDnsDescription, + ), + ], SectionLabel( label: AppLocalizations.of(context)!.serverConfiguration, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), From 2f4bf402fe53fc55095c15df4acad4a7b3f5f315 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 7 Feb 2024 23:44:32 +0100 Subject: [PATCH 538/676] Fix keyboard closes on edit encryption --- lib/screens/settings/encryption/encryption.dart | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 1929ef7..3c678b8 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -73,7 +73,7 @@ class _EncryptionSettingsState extends State { bool localValidationValid = false; String? validDataError; - int certKeyValidApi = 0; + bool _dataValidApi = true; EncryptionValidation? certKeyValid; String? encryptionResultMessage; @@ -125,8 +125,6 @@ class _EncryptionSettingsState extends State { } Future checkValidDataApi({Map? data}) async { - setState(() => certKeyValidApi = 0); - final result = await Provider.of(context, listen: false).apiClient2!.checkEncryptionSettings( data: data ?? { "enabled": enabled, @@ -150,11 +148,11 @@ class _EncryptionSettingsState extends State { final object = data.encryptionValidation!; setState(() { if (object.warningValidation != null && object.warningValidation != '') { - certKeyValidApi = 2; + _dataValidApi = false; validDataError = object.warningValidation; } else { - certKeyValidApi = 1; + _dataValidApi = true; validDataError = null; } certKeyValid = object; @@ -163,7 +161,7 @@ class _EncryptionSettingsState extends State { else { setState(() { encryptionResultMessage = data.message; - certKeyValidApi = 2; + _dataValidApi = false; }); } } @@ -351,7 +349,7 @@ class _EncryptionSettingsState extends State { case LoadStatus.loaded: return ListView( children: [ - if (certKeyValidApi == 2 && (validDataError != null || encryptionResultMessage != null)) Card( + if (_dataValidApi == false && (validDataError != null || encryptionResultMessage != null)) Card( margin: const EdgeInsets.all(16), color: Colors.red.withOpacity(0.2), elevation: 0, From 7d2da49bc86969f1e48c33f45d4f2d3aad6bb393 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 00:25:58 +0100 Subject: [PATCH 539/676] Changed logs search --- .../logs/filters/logs_filters_modal.dart | 67 +--------- lib/screens/logs/logs_list_appbar.dart | 124 ++++++++++++++++-- 2 files changed, 122 insertions(+), 69 deletions(-) diff --git a/lib/screens/logs/filters/logs_filters_modal.dart b/lib/screens/logs/filters/logs_filters_modal.dart index b02dbd2..b506cff 100644 --- a/lib/screens/logs/filters/logs_filters_modal.dart +++ b/lib/screens/logs/filters/logs_filters_modal.dart @@ -15,7 +15,7 @@ import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; -class LogsFiltersModal extends StatefulWidget { +class LogsFiltersModal extends StatelessWidget { final bool dialog; const LogsFiltersModal({ @@ -23,22 +23,9 @@ class LogsFiltersModal extends StatefulWidget { required this.dialog }); - @override - State createState() => _LogsFiltersModalState(); -} - -class _LogsFiltersModalState extends State { - TextEditingController searchController = TextEditingController(); - - @override - void initState() { - searchController.text = Provider.of(context, listen: false).searchText ?? ''; - super.initState(); - } - @override Widget build(BuildContext context) { - if (widget.dialog == true) { + if (dialog == true) { return Padding( padding: MediaQuery.of(context).viewInsets, child: Dialog( @@ -46,10 +33,7 @@ class _LogsFiltersModalState extends State { constraints: const BoxConstraints( maxWidth: 500 ), - child: _FiltersList( - searchController: searchController, - onClearSearch: () => setState(() => searchController.text = "") - ) + child: const _FiltersList() ) ), ); @@ -65,11 +49,8 @@ class _LogsFiltersModalState extends State { topRight: Radius.circular(28) ) ), - child: SafeArea( - child: _FiltersList( - searchController: searchController, - onClearSearch: () => setState(() => searchController.text = "") - ), + child: const SafeArea( + child: _FiltersList(), ) ), ); @@ -78,13 +59,7 @@ class _LogsFiltersModalState extends State { } class _FiltersList extends StatelessWidget { - final TextEditingController searchController; - final void Function() onClearSearch; - - const _FiltersList({ - required this.searchController, - required this.onClearSearch, - }); + const _FiltersList(); @override Widget build(BuildContext context) { @@ -194,35 +169,6 @@ class _FiltersList extends StatelessWidget { ), ], ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( - children: [ - Expanded( - child: TextFormField( - controller: searchController, - onChanged: logsProvider.setSearchText, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.search_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.search, - suffixIcon: IconButton( - onPressed: () { - onClearSearch(); - logsProvider.setSearchText(null); - }, - icon: const Icon(Icons.clear) - ), - ), - ), - ) - ], - ), - ), Container(height: 16), CustomListTile( title: AppLocalizations.of(context)!.client, @@ -300,7 +246,6 @@ class _FiltersList extends StatelessWidget { children: [ TextButton( onPressed: () { - searchController.text = ""; logsProvider.requestResetFilters(); }, child: Text(AppLocalizations.of(context)!.resetFilters) diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 01a870c..ee4dfd1 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -76,14 +76,31 @@ class LogsListAppBar extends StatelessWidget { icon: const Icon(Icons.refresh_rounded), tooltip: AppLocalizations.of(context)!.refresh, ), - logsProvider.loadStatus == LoadStatus.loaded - ? IconButton( - onPressed: openFilersModal, - icon: const Icon(Icons.filter_list_rounded), - tooltip: AppLocalizations.of(context)!.filters, - ) - : const SizedBox(), - const SizedBox(width: 5), + if (logsProvider.loadStatus == LoadStatus.loaded) IconButton( + onPressed: () => showDialog( + context: context, + builder: (context) => _Search( + onSearch: (v) { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: v != "" ? v : null, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.filterLogs(); + }, + ), + ), + icon: const Icon(Icons.search_rounded), + tooltip: AppLocalizations.of(context)!.search, + ), + if (logsProvider.loadStatus == LoadStatus.loaded) IconButton( + onPressed: openFilersModal, + icon: const Icon(Icons.filter_list_rounded), + tooltip: AppLocalizations.of(context)!.filters, + ), + const SizedBox(width: 8), ], bottom: logsProvider.appliedFilters.searchText != null || logsProvider.appliedFilters.selectedResultStatus != 'all' || logsProvider.appliedFilters.clients.isNotEmpty ? PreferredSize( @@ -213,4 +230,95 @@ class LogsListAppBar extends StatelessWidget { : null, ); } +} + +class _Search extends StatefulWidget { + final void Function(String) onSearch; + + const _Search({ + required this.onSearch + }); + + @override + State<_Search> createState() => _SearchState(); +} + +class _SearchState extends State<_Search> { + final _searchController = TextEditingController(); + + @override + void initState() { + final logsProvider = Provider.of(context, listen: false); + _searchController.text = logsProvider.appliedFilters.searchText ?? ""; + + super.initState(); + } + + @override + Widget build(BuildContext context) { + final logsProvider = Provider.of(context); + + return GestureDetector( + onTap: () => Navigator.pop(context), + child: Material( + color: Colors.transparent, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () => {}, + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 500), + child: Container( + margin: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(16) + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: TextFormField( + controller: _searchController, + onChanged: (v) { + if (v == "") { + logsProvider.setSearchText(null); + return; + } + logsProvider.setSearchText(v); + }, + onFieldSubmitted: (v) { + widget.onSearch(v); + Navigator.pop(context); + }, + autofocus: true, + decoration: InputDecoration( + hintText: AppLocalizations.of(context)!.search, + prefixIcon: const Icon(Icons.search_rounded), + border: InputBorder.none, + filled: true, + fillColor: Colors.grey.withOpacity(0.2), + suffixIcon: _searchController.text != "" + ? IconButton( + onPressed: () { + _searchController.text = ""; + logsProvider.setSearchText(null); + }, + icon: const Icon( + Icons.close_rounded, + size: 20, + ), + tooltip: AppLocalizations.of(context)!.clearSearch, + ) + : null + ), + ), + ), + ), + ), + ) + ], + ), + ), + ); + } } \ No newline at end of file From 6e8ecf11a0d3eb81a2123546e9c2b2cbd4da078d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 00:28:05 +0100 Subject: [PATCH 540/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index c9ad2f4..5b76b9a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.16.0-beta.2+128 +version: 2.16.0-beta.3+129 environment: sdk: '>=2.18.1 <3.0.0' From 5f4580b6a063c002341a2a37fd634494efabcb54 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo <47545344+JGeek00@users.noreply.github.com> Date: Thu, 8 Feb 2024 00:54:07 +0100 Subject: [PATCH 541/676] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..53a21e8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,31 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**App info (please complete the following information):** + - OS version: [e.g. iOS 17.2] + - App version [e.g. v2.16.0] + +**Additional context** +Add any other context about the problem here. From 5dbe1e3f740e5eb583366bdb12ba15abdcf9a9f0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 01:02:11 +0100 Subject: [PATCH 542/676] Updated bug template --- .github/ISSUE_TEMPLATE/bug_report.md | 31 ------------------- .github/ISSUE_TEMPLATE/bug_report.yml | 43 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 31 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 53a21e8..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**App info (please complete the following information):** - - OS version: [e.g. iOS 17.2] - - App version [e.g. v2.16.0] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..4bd774c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,43 @@ +name: Report a bug +description: | + You detected something wrong on the application. +body: + - type: textarea + attributes: + label: Steps to reproduce + description: Steps to reproduce the problem you are running into. + placeholder: | + 1. ... + 2. ... + 3. ... + validations: + required: true + - type: textarea + attributes: + label: Expected results + description: What is expected to happen. + validations: + required: true + - type: textarea + attributes: + label: Actual results + description: What is actually happening. + validations: + required: true + - type: textarea + attributes: + label: Screenshots or Video + description: | + Upload any screenshots or video of the bug. + value: | + Screenshots or video demonstration + required: true + - type: textarea + attributes: + label: App and OS details + description: | + Some details about the app version and the OS where you are running the application. + value: | + - App version: (eg: v2.16.0) + - Device OS version: (eg: Android 14) + required: true \ No newline at end of file From 034280afa80525d99b1852f80de31f7879813ab2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 01:05:24 +0100 Subject: [PATCH 543/676] Updated bug template --- .github/ISSUE_TEMPLATE/bug_report.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 4bd774c..a50a380 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,8 +1,11 @@ name: Report a bug description: | You detected something wrong on the application. +title: "[Bug]: " +labels: ["bug"] body: - type: textarea + id: steps attributes: label: Steps to reproduce description: Steps to reproduce the problem you are running into. @@ -13,18 +16,21 @@ body: validations: required: true - type: textarea + id: expected-results attributes: label: Expected results description: What is expected to happen. validations: required: true - type: textarea + id: actual-results attributes: label: Actual results description: What is actually happening. validations: required: true - type: textarea + id: screenshots attributes: label: Screenshots or Video description: | @@ -33,6 +39,7 @@ body: Screenshots or video demonstration required: true - type: textarea + id: app-os-details attributes: label: App and OS details description: | From 7fa5eee0143347232934fb7b4b57a862a9848758 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 01:08:02 +0100 Subject: [PATCH 544/676] Updated bug template --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index a50a380..ff90375 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -47,4 +47,5 @@ body: value: | - App version: (eg: v2.16.0) - Device OS version: (eg: Android 14) + validations: required: true \ No newline at end of file From c249b757b25fc1c15a70883e9c1d4054251c9502 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 01:08:34 +0100 Subject: [PATCH 545/676] Updated bug template --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index ff90375..e5406c3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -37,6 +37,7 @@ body: Upload any screenshots or video of the bug. value: | Screenshots or video demonstration + validations: required: true - type: textarea id: app-os-details From d51964de32f44fcfc55aa63cefc1447b896de87b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 01:14:09 +0100 Subject: [PATCH 546/676] Added agh feature request --- .../ISSUE_TEMPLATE/feature_request_agh.yml | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/feature_request_agh.yml diff --git a/.github/ISSUE_TEMPLATE/feature_request_agh.yml b/.github/ISSUE_TEMPLATE/feature_request_agh.yml new file mode 100644 index 0000000..aeaf999 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request_agh.yml @@ -0,0 +1,33 @@ +name: Request a new feature that has been added to AdGuard Home +description: | + The AdGuard Home team added recently a new feature that you want on the app. +title: "[AGH Feature Request]: " +labels: ["feature request"] +body: + - type: textarea + id: description + attributes: + label: Description + description: Describe the feature that you want on the app. + placeholder: | + Write the details here... + validations: + required: true + - type: textarea + id: screenshots + attributes: + label: Screenshots + description: Attach some screenshots of where that new feature is located on the web administration panel. + placeholder: | + Screenshots here. + validations: + required: true + - type: textarea + id: version-introduced + attributes: + label: Version where feature was introduced + description: Version of the AdGuard Home server where this feature was introduced. + placeholder: | + - Version: (eg: v0.107.44) + validations: + required: true \ No newline at end of file From a2d8e9d1c18e9b94cdb73827890dd448e1807081 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 01:20:11 +0100 Subject: [PATCH 547/676] Added app feature request --- .../ISSUE_TEMPLATE/feature_request_app.yml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/feature_request_app.yml diff --git a/.github/ISSUE_TEMPLATE/feature_request_app.yml b/.github/ISSUE_TEMPLATE/feature_request_app.yml new file mode 100644 index 0000000..0323540 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request_app.yml @@ -0,0 +1,20 @@ +name: Request a new feature or an improvement for the app itself +description: | + You want a new feature for the application, or an improvement for an existing one. +title: "[App Feature Request]: " +labels: ["feature request"] +body: + - type: markdown + attributes: + value: | + â„¹ï¸ IMPORTANT INFO â„¹ï¸ + Please note that if the functionality is related to data representation, it may not be implemented, as AdGuard Home Manager depends on the capabilities of the AdGuard Home API. + - type: textarea + id: description + attributes: + label: Description + description: Describe the feature that you want on the app. + placeholder: | + Write the details here... + validations: + required: true \ No newline at end of file From 0dc10abc29e55d9b3edcf1935732085dd6628888 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 01:21:53 +0100 Subject: [PATCH 548/676] Fix template --- .github/ISSUE_TEMPLATE/feature_request_app.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request_app.yml b/.github/ISSUE_TEMPLATE/feature_request_app.yml index 0323540..b558105 100644 --- a/.github/ISSUE_TEMPLATE/feature_request_app.yml +++ b/.github/ISSUE_TEMPLATE/feature_request_app.yml @@ -4,7 +4,8 @@ description: | title: "[App Feature Request]: " labels: ["feature request"] body: - - type: markdown + - type: markdown + id: important-info attributes: value: | â„¹ï¸ IMPORTANT INFO â„¹ï¸ From 00f77fc12c43cbf9e2eac2a189f1dc33fd4c435d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 8 Feb 2024 01:28:38 +0100 Subject: [PATCH 549/676] Updated templates --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 - .../ISSUE_TEMPLATE/feature_request_agh.yml | 3 +-- .../ISSUE_TEMPLATE/feature_request_app.yml | 3 +-- .github/ISSUE_TEMPLATE/question.yml | 19 +++++++++++++++++++ 4 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/question.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e5406c3..cf174cb 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,7 +1,6 @@ name: Report a bug description: | You detected something wrong on the application. -title: "[Bug]: " labels: ["bug"] body: - type: textarea diff --git a/.github/ISSUE_TEMPLATE/feature_request_agh.yml b/.github/ISSUE_TEMPLATE/feature_request_agh.yml index aeaf999..55972db 100644 --- a/.github/ISSUE_TEMPLATE/feature_request_agh.yml +++ b/.github/ISSUE_TEMPLATE/feature_request_agh.yml @@ -1,8 +1,7 @@ name: Request a new feature that has been added to AdGuard Home description: | The AdGuard Home team added recently a new feature that you want on the app. -title: "[AGH Feature Request]: " -labels: ["feature request"] +labels: ["agh feature request"] body: - type: textarea id: description diff --git a/.github/ISSUE_TEMPLATE/feature_request_app.yml b/.github/ISSUE_TEMPLATE/feature_request_app.yml index b558105..3cf08e6 100644 --- a/.github/ISSUE_TEMPLATE/feature_request_app.yml +++ b/.github/ISSUE_TEMPLATE/feature_request_app.yml @@ -1,8 +1,7 @@ name: Request a new feature or an improvement for the app itself description: | You want a new feature for the application, or an improvement for an existing one. -title: "[App Feature Request]: " -labels: ["feature request"] +labels: ["app feature request"] body: - type: markdown id: important-info diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 0000000..805783f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,19 @@ +name: You have a question about the app +description: | + You want ask something that's not related with a feature request or a bug. +labels: ["question"] +body: + - type: markdown + id: important-info + attributes: + value: | + Having problems while adding a connection to a server? Check out [this guide](https://github.com/JGeek00/adguard-home-manager/wiki/Create-a-connection). + - type: textarea + id: question + attributes: + label: Question + description: Write your question here giving the maximum detail possible. + placeholder: | + Write your question here... + validations: + required: true \ No newline at end of file From 3a210fb9fda3d84b164aa942a09e5f30db17e343 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 9 Feb 2024 01:22:05 +0100 Subject: [PATCH 550/676] Updated turkish translation --- lib/l10n/app_tr.arb | 256 +++++++++++++++++++++++++++++--------------- 1 file changed, 171 insertions(+), 85 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 06c3b08..12c8980 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -11,7 +11,7 @@ "port": "BaÄŸlantı noktası", "username": "Kullanıcı adı", "password": "Åžifre", - "defaultServer": "Varsayılan sunucu", + "defaultServer": "Varsayılan sunucu olarak ayarla", "general": "Genel", "connection": "BaÄŸlantı", "authentication": "Kimlik doÄŸrulama", @@ -40,18 +40,18 @@ "removeWarning": "Bu AdGuard Home sunucusuyla olan baÄŸlantıyı kaldırmak istediÄŸinizden emin misiniz?", "cancel": "İptal", "defaultConnection": "Varsayılan baÄŸlantı", - "setDefault": "Varsayılan ayarla", + "setDefault": "Varsayılan sunucu yap", "edit": "Düzenle", "delete": "Sil", "save": "Kaydet", "serverStatus": "Sunucu durumu", "connectionNotUpdated": "BaÄŸlantı Güncellenmedi", "ruleFilteringWidget": "Kural filtreleme", - "safeBrowsingWidget": "Güvenli gezinti", + "safeBrowsingWidget": "Güvenli gezinme", "parentalFilteringWidget": "Ebeveyn filtreleme", "safeSearchWidget": "Güvenli arama", "ruleFiltering": "Kural filtreleme", - "safeBrowsing": "Güvenli gezinti", + "safeBrowsing": "Güvenli gezinme", "parentalFiltering": "Ebeveyn filtreleme", "safeSearch": "Güvenli arama", "serverStatusNotRefreshed": "Sunucu durumu yenilenemedi", @@ -63,9 +63,9 @@ "topBlockedDomains": "En çok engellenenler", "appSettings": "Uygulama ayarları", "theme": "Tema", - "light": "Aydınlık", - "dark": "Karanlık", - "systemDefined": "Sistemle uyumlu hale getir", + "light": "Açık", + "dark": "Koyu", + "systemDefined": "Otomatik (Cihazınızın renk düzenine göre)", "close": "Kapat", "connectedTo": "BaÄŸlandı:", "selectedServer": "Seçili sunucu:", @@ -80,8 +80,8 @@ "appVersion": "Uygulama sürümü", "createdBy": "GeliÅŸtirici", "clients": "İstemciler", - "allowed": "İzin verildi", - "blocked": "Engellendi", + "allowed": "İzin verilen", + "blocked": "Engellenen", "noClientsList": "Bu listede hiç istemci yok", "activeClients": "Etkin", "removeClient": "İstemciyi kaldır", @@ -102,7 +102,7 @@ "copyLogsClipboard": "Günlükleri panoya kopyala", "logsCopiedClipboard": "Günlükler panoya kopyalandı", "advancedSettings": "GeliÅŸmiÅŸ ayarlar", - "dontCheckCertificate": "SSL sertifikasını asla kontrol etme", + "dontCheckCertificate": "SSL sertifikasını kontrol etme", "dontCheckCertificateDescription": "Sunucunun SSL sertifikası doÄŸrulamasını geçersiz kılar", "advancedSetupDescription": "GeliÅŸmiÅŸ seçenekleri yönet", "settingsUpdatedSuccessfully": "Ayarlar baÅŸarıyla güncellendi.", @@ -114,8 +114,8 @@ "processedRow": "İşlendi (Liste yok)", "blockedBlacklist": "Engellendi\nKara Liste", "blockedBlacklistRow": "Engellendi (Kara liste)", - "blockedSafeBrowsing": "Engellendi\nGüvenli gezinti", - "blockedSafeBrowsingRow": "Engellendi (Güvenli gezinti)", + "blockedSafeBrowsing": "Engellendi\nGüvenli gezinme", + "blockedSafeBrowsingRow": "Engellendi (Güvenli gezinme)", "blockedParental": "Engellendi\nEbeveyn filtreleme", "blockedParentalRow": "Engellendi (Ebeveyn filtreleme)", "blockedInvalid": "Engellendi\nGeçersiz", @@ -181,7 +181,7 @@ "visitGooglePlay": "Google Play sayfasını ziyaret et", "gitHub": "Kaynak kodlarına GitHub'dan ulaÅŸabilirsiniz", "blockClient": "İstemciyi engelle", - "selectTags": "Etiketleri seçin", + "selectTags": "Etiketleri seç", "noTagsSelected": "Seçili etiket yok", "tags": "Etiketler", "identifiers": "Tanımlayıcılar", @@ -190,19 +190,19 @@ "noIdentifiers": "Tanımlayıcı eklenmedi", "useGlobalSettings": "Küresel ayarları kullan", "enableFiltering": "Filtrelemeyi etkinleÅŸtir", - "enableSafeBrowsing": "Güvenli gezintiyi etkinleÅŸtir", + "enableSafeBrowsing": "Güvenli gezinmeyi etkinleÅŸtir", "enableParentalControl": "Ebeveyn kontrolünü etkinleÅŸtir", - "enableSafeSearch": "Güvenli aramayı aktif et", + "enableSafeSearch": "Güvenli aramayı etkinleÅŸtir", "blockedServices": "Engellenen hizmetler", "selectBlockedServices": "Engellenen hizmetleri seç", "noBlockedServicesSelected": "Engellenen hizmetler seçilmedi", "services": "Hizmetler", "servicesBlocked": "Hizmetler engellendi", - "tagsSelected": "Seçilen etiketler", - "upstreamServers": "Üst kaynak sunucuları", + "tagsSelected": "Etiket seçildi", + "upstreamServers": "Üst sunucular", "serverAddress": "Sunucu adresi", - "noUpstreamServers": "Üst kaynak sunucusu yok.", - "willBeUsedGeneralServers": "Genel üst kaynak sunucuları kullanılacak.", + "noUpstreamServers": "Üst sunucu yok.", + "willBeUsedGeneralServers": "Genel üst sunucular kullanılacak.", "added": "Eklenenler", "clientUpdatedSuccessfully": "İstemci baÅŸarıyla güncellendi", "clientNotUpdated": "İstemci güncellenemedi", @@ -215,7 +215,7 @@ "blacklists": "Kara listeler", "rules": "Kurallar", "customRules": "Özel kurallar", - "enabledRules": "Etkin kurallar", + "enabledRules": "Etkin kural", "enabled": "Etkin", "disabled": "Devre dışı", "rule": "Kural", @@ -234,7 +234,7 @@ "addWhitelist": "Beyaz liste ekle", "addBlacklist": "Kara liste ekle", "urlNotValid": "BaÄŸlantı adresi geçerli deÄŸil", - "urlAbsolutePath": "BaÄŸlantı adresi veya kesin dosya yolu", + "urlAbsolutePath": "BaÄŸlantı adresi veya dosya yolu", "addingList": "Liste ekleniyor...", "listAdded": "Liste baÅŸarıyla eklendi. Eklenen öğeler:", "listAlreadyAdded": "Liste zaten eklenmiÅŸ", @@ -267,13 +267,13 @@ "seeDnsAddresses": "DNS adreslerine göz at", "dnsPort": "DNS baÄŸlantı noktası", "httpPort": "HTTP baÄŸlantı noktası", - "protectionEnabled": "Koruma etkin mi?", - "dhcpAvailable": "DHCP mevcut mu?", - "serverRunning": "Sunucu çalışıyor mu?", + "protectionEnabled": "Koruma durumu", + "dhcpAvailable": "DHCP durumu", + "serverRunning": "Sunucu durumu", "serverVersion": "Sunucu sürümü", "serverLanguage": "Sunucu dili", - "yes": "Evet", - "no": "Hayır", + "yes": "Etkin", + "no": "Mevcut deÄŸil", "allowedClients": "İzin verilen istemciler", "disallowedClients": "İzin verilmeyen istemciler", "disallowedDomains": "İzin verilmeyen alan adları", @@ -288,7 +288,7 @@ "addClientFieldDescription": "CIDR'ler, IP adresi veya ClientID", "clientIdentifier": "İstemci tanımlayıcısı", "allowClient": "İstemciye izin ver", - "disallowClient": "İstemciye izin verme", + "disallowClient": "İstemciyi engelle", "noDisallowedDomains": "İzin verilmeyen alan adı yok", "domainNotAdded": "Alan adı eklenemedi", "statusSelected": "Durum seçildi.", @@ -305,11 +305,11 @@ "block": "Engelle", "unblock": "Engeli kaldır", "custom": "Özel", - "addImportant": "Ekle ($important)", + "addImportant": "Başına $important ekle", "howCreateRules": "Özel kurallar nasıl oluÅŸturulur?", "examples": "Örnekler", - "example1": "example.org ve tüm alt alan adlarına eriÅŸimi engeller.", - "example2": "example.org ve tüm alt alan adlarına eriÅŸimi engellemeyi kaldırır.", + "example1": "example.org (ornek.org) ve tüm alt alan adlarına eriÅŸimi engeller.", + "example2": "example.org (ornek.org) ve tüm alt alan adlarına eriÅŸimi engellemeyi kaldırır.", "example3": "Yorum ekler.", "example4": "Belirtilen düzenli ifadeye uyan alan adlarına eriÅŸimi engeller.", "moreInformation": "Daha fazla bilgi", @@ -342,7 +342,7 @@ "dhcpSettingsNotLoaded": "DHCP ayarları yüklenemedi", "loadingDhcp": "DHCP ayarları yükleniyor...", "enableDhcpServer": "DHCP sunucusunu etkinleÅŸtir", - "selectInterface": "Arayüz seçin", + "selectInterface": "Arayüz seç", "hardwareAddress": "Donanım adresi", "gatewayIp": "AÄŸ Geçidi IP'si", "ipv4addresses": "IPv4 adresleri", @@ -368,37 +368,37 @@ "restoringConfig": "Yapılandırma geri yükleniyor...", "configRestored": "Yapılandırma baÅŸarıyla sıfırlandı", "configNotRestored": "Yapılandırma sıfırlanamadı", - "dhcpStatic": "DHCP statik kiralamaları", - "noDhcpStaticLeases": "DHCP statik kiralamaları bulunamadı", + "dhcpStatic": "DHCP statik kiraları", + "noDhcpStaticLeases": "DHCP statik kirası bulunamadı", "deleting": "Siliniyor...", - "staticLeaseDeleted": "DHCP statik kiralama baÅŸarıyla silindi", - "staticLeaseNotDeleted": "DHCP statik kiralaması silinemedi", - "deleteStaticLease": "Statik kiralamayı sil", + "staticLeaseDeleted": "DHCP statik kirası baÅŸarıyla silindi", + "staticLeaseNotDeleted": "DHCP statik kirası silinemedi", + "deleteStaticLease": "Statik kirasını sil", "deleteStaticLeaseDescription": "DHCP statik kirası silinecek. Bu iÅŸlem geri alınamaz.", - "addStaticLease": "Statik kiralama ekleyin", + "addStaticLease": "Statik kira ekleyin", "macAddress": "MAC adresi", "macAddressNotValid": "MAC adresi geçersiz", "hostName": "Ana bilgisayar adı", "hostNameError": "Ana bilgisayar adı boÅŸ olamaz", "creating": "OluÅŸturuluyor...", - "staticLeaseCreated": "DHCP statik kiralaması baÅŸarıyla oluÅŸturuldu", - "staticLeaseNotCreated": "DHCP statik kiralaması oluÅŸturulamadı", - "staticLeaseExists": "DHCP statik kiralaması zaten mevcut", + "staticLeaseCreated": "DHCP statik kirası baÅŸarıyla oluÅŸturuldu", + "staticLeaseNotCreated": "DHCP statik kirası oluÅŸturulamadı", + "staticLeaseExists": "DHCP statik kirası zaten mevcut", "serverNotConfigured": "Sunucu yapılandırılmamış", - "restoreLeases": "Kiralamaları sıfırla", - "restoreLeasesMessage": "Devam etmek istediÄŸinizden emin misiniz? Bu, mevcut tüm kiralamaları sıfırlayacaktır. Bu iÅŸlem geri alınamaz.", - "restoringLeases": "Kiralamalar sıfırlanıyor...", - "leasesRestored": "Kiralamalar baÅŸarıyla sıfırlandı", + "restoreLeases": "Kiraları sıfırla", + "restoreLeasesMessage": "Devam etmek istediÄŸinizden emin misiniz? Bu, mevcut tüm kiraları sıfırlayacaktır. Bu iÅŸlem geri alınamaz.", + "restoringLeases": "Kiralar sıfırlanıyor...", + "leasesRestored": "Kiralar baÅŸarıyla sıfırlandı", "leasesNotRestored": "Kiralar sıfırlanamadı", - "dhcpLeases": "DHCP kiralamaları", - "noLeases": "Kullanılabilir DHCP kiralaması yok", + "dhcpLeases": "DHCP kiraları", + "noLeases": "Kullanılabilir DHCP kiraları yok", "dnsRewrites": "DNS yeniden yazımları", "dnsRewritesDescription": "Özel DNS kurallarını yapılandır", "loadingRewriteRules": "Yeniden yazım kuralları yükleniyor...", "rewriteRulesNotLoaded": "DNS yeniden yazım kuralları yüklenemedi.", "noRewriteRules": "DNS yeniden yazım kuralları yok", "answer": "Yanıt", - "deleteDnsRewrite": "DNS yeniden yazımı sil", + "deleteDnsRewrite": "DNS yeniden yazımını sil", "deleteDnsRewriteMessage": "Bu DNS yeniden yazımını silmek istediÄŸinizden emin misiniz? Bu iÅŸlem geri alınamaz.", "dnsRewriteRuleDeleted": "DNS yeniden yazım kuralı baÅŸarıyla silindi", "dnsRewriteRuleNotDeleted": "DNS yeniden yazım kuralı silinemedi", @@ -409,7 +409,7 @@ "logsSettings": "Günlük ayarları", "enableLog": "Günlüğü etkinleÅŸtir", "clearLogs": "Günlükleri temizle", - "anonymizeClientIp": "İstemci IP'sini anonimleÅŸtir", + "anonymizeClientIp": "İstemci IP'sini gizle", "hours6": "6 saat", "days30": "30 gün", "days90": "90 gün", @@ -427,17 +427,17 @@ "noItems": "Burada gösterilecek öğe yok", "dnsSettings": "DNS ayarları", "dnsSettingsDescription": "DNS sunucuları ile baÄŸlantıyı yapılandır", - "upstreamDns": "Üst kaynak DNS sunucuları", + "upstreamDns": "Üst DNS sunucuları", "bootstrapDns": "Önyükleme DNS sunucuları", - "noUpstreamDns": "Üst kaynak DNS sunucuları eklenmedi.", + "noUpstreamDns": "Üst DNS sunucuları eklenmedi.", "dnsMode": "DNS modu", "noDnsMode": "DNS modu seçili deÄŸil", "loadBalancing": "Yük dengeleme", "parallelRequests": "Paralel istekler", "fastestIpAddress": "En hızlı IP adresi", - "loadBalancingDescription": "Her seferinde bir üst kaynak sunucusuna sorgu yap. AdGuard Home, sunucuyu seçmek için ağırlıklı rastgele algoritmasını kullanır, böylece en hızlı sunucu daha sık kullanılır.", - "parallelRequestsDescription": "Tüm üst kaynak sunucularını aynı anda sorgulayarak çözümlemeyi hızlandırmak için paralel sorgular kullanın.", - "fastestIpAddressDescription": "Tüm DNS sunucularına sorgu yapın ve tüm yanıtlar arasında en hızlı IP adresini döndürün. Bu, AdGuard Home'un tüm DNS sunucularından yanıtları beklemesi gerektiÄŸi için DNS sorgularını yavaÅŸlatır, ancak genel baÄŸlantıyı iyileÅŸtirir.", + "loadBalancingDescription": "Her seferinde bir üst sunucuya sorgu yapar. AdGuard Home, sunucuyu seçmek için ağırlıklı rastgele algoritmasını kullanır, böylece en hızlı sunucu daha sık kullanılır.", + "parallelRequestsDescription": "Tüm üst sunucuları aynı anda sorgulayarak çözümlemeyi hızlandırmak için paralel sorgular kullanır.", + "fastestIpAddressDescription": "Tüm DNS sunucularına sorgu yapın ve tüm yanıtlar arasında en hızlı IP adresini döndürür. Bu, AdGuard Home'un tüm DNS sunucularından yanıtları beklemesi gerektiÄŸi için DNS sorgularını yavaÅŸlatır, ancak genel baÄŸlantıyı iyileÅŸtirir.", "noBootstrapDns": "Önyükleme DNS sunucuları eklenmedi.", "bootstrapDnsServersInfo": "Önyükleme ​​DNS sunucuları, üst kaynaklarda belirttiÄŸiniz DoH/DoT çözümleyicilerinin IP adreslerini çözmek için kullanılır.", "privateReverseDnsServers": "Özel ters DNS sunucuları", @@ -446,36 +446,36 @@ "addItem": "Öğe ekle", "noServerAddressesAdded": "Sunucu adresleri eklenmedi.", "usePrivateReverseDnsResolvers": "Özel ters DNS çözümleyicilerini kullan", - "usePrivateReverseDnsResolversDescription": "Bu üst kaynak sunucularını kullanarak yerel olarak sunulan adresler için ters DNS sorguları gerçekleÅŸtirin. Devre dışı bırakılırsa, AdGuard Home, DHCP, /etc/hosts vb. kaynaklardan bilinen istemciler dışında tüm PTR isteklerine NXDOMAIN yanıtı verir.", + "usePrivateReverseDnsResolversDescription": "Bu üst sunucuları kullanarak yerel olarak sunulan adresler için ters DNS sorguları gerçekleÅŸtirin. Devre dışı bırakılırsa, AdGuard Home, DHCP, /etc/hosts vb. kaynaklardan bilinen istemciler dışında tüm PTR isteklerine NXDOMAIN yanıtı verir.", "enableReverseResolving": "İstemcilerin IP adreslerinin ters çözümlemesini etkinleÅŸtir", - "enableReverseResolvingDescription": "İstemcilerin IP adreslerini karşılık gelen çözücülere PTR sorguları göndererek IP adreslerini tersine çözümleyerek (yerel istemciler için özel DNS sunucuları, genel IP adresine sahip istemciler için üst kaynak sunucuları) istemcilerin ana bilgisayar adlarını tersine çöz.", + "enableReverseResolvingDescription": "Karşılık gelen çözümleyicilere (yerel istemciler için özel DNS sunucuları, genel IP adresleri olan istemciler için üst sunuculara) PTR sorguları göndererek istemcilerin IP adreslerini ana makine adlarının tersine çözer.", "dnsServerSettings": "AdGuard Home DNS sunucusu ayarları", - "limitRequestsSecond": "Saniye başına sınırlama isteÄŸi", + "limitRequestsSecond": "Sıklık limiti", "valueNotNumber": "DeÄŸer bir sayı deÄŸil", "enableEdns": "EDNS istemci alt ağını etkinleÅŸtir", - "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı SeçeneÄŸi (ECS) ekleyin ve istemciler tarafından gönderilen deÄŸerleri sorgu günlüğüne kaydedin.", + "enableEdnsDescription": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı SeçeneÄŸi (ECS) ekler ve istemciler tarafından gönderilen deÄŸerleri sorgu günlüğüne kaydeder.", "enableDnssec": "DNSSEC'i etkinleÅŸtir", - "enableDnssecDescription": "Giden DNS sorguları için DNSSEC özelliÄŸini etkinleÅŸtir ve sonucu kontrol edin.(DNSSEC etkinleÅŸtirilmiÅŸ bir çözümleyici gerekli)", + "enableDnssecDescription": "Giden DNS sorguları için DNSSEC özelliÄŸini etkinleÅŸtirir ve sonucu kontrol eder. (DNSSEC etkinleÅŸtirilmiÅŸ bir çözümleyici gerekli)", "disableResolvingIpv6": "IPv6 adreslerinin çözümlenmesini devre dışı bırak", - "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını bırakın (AAAA yazın) ve HTTPS yanıtlarından IPv6 ipuçlarını kaldırın.", + "disableResolvingIpv6Description": "IPv6 adresleri için tüm DNS sorgularını bırakır (AAAA yazar) ve HTTPS yanıtlarından IPv6 ipuçlarını kaldırır.", "blockingMode": "Engelleme modu", "defaultMode": "Varsayılan", - "defaultDescription": "Reklam engelleme tarzı bir kural tarafından engellendiÄŸinde sıfır IP adresi ile yanıt verin. (A için 0.0.0.0; :: AAAA için) /etc/hosts tarzı bir kural tarafından engellendiÄŸinde kuralda belirtilen IP adresi ile yanıt verin.", - "refusedDescription": "REFUSED kodu ile yanıt verin.", - "nxdomainDescription": "NXDOMAIN kodu ile yanıt verin.", + "defaultDescription": "Reklam engelleme tarzı bir kural tarafından engellendiÄŸinde sıfır IP adresi ile yanıt verir. (A için 0.0.0.0; :: AAAA için) /etc/hosts tarzı bir kural tarafından engellendiÄŸinde kuralda belirtilen IP adresi ile yanıt verir.", + "refusedDescription": "REFUSED kodu ile yanıt verir.", + "nxdomainDescription": "NXDOMAIN kodu ile yanıt verir.", "nullIp": "BoÅŸ IP", - "nullIpDescription": "Sıfır IP adresi ile yanıt verin. (A için 0.0.0.0; :: AAAA için)", + "nullIpDescription": "Sıfır IP adresi ile yanıt verir. (A için 0.0.0.0; :: AAAA için)", "customIp": "Özel IP", - "customIpDescription": "Manuel olarak ayarlanmış bir IP adresi ile yanıt verin.", + "customIpDescription": "Manuel olarak ayarlanmış bir IP adresi ile yanıt verir.", "dnsCacheConfig": "DNS önbellek yapılandırması", "cacheSize": "Önbellek boyutu", - "inBytes": "Bayt olarak", + "inBytes": "Alınacak önbelleÄŸin boyutunu ayarla (bayt olarak)", "overrideMinimumTtl": "Minimum kullanım süresini geçersiz kıl", - "overrideMinimumTtlDescription": "DNS yanıtlarını önbelleÄŸe alırken üst sunucudan alınan minimum kullanım süresi deÄŸerini ayarlayın (saniye olarak)", + "overrideMinimumTtlDescription": "DNS yanıtlarını önbelleÄŸe alırken üst sunucudan alınan minimum kullanım süresi deÄŸerini (TTL) saniye olarak ayarlayın.", "overrideMaximumTtl": "Maksimum kullanım süresini geçersiz kıl", - "overrideMaximumTtlDescription": "DNS önbelleÄŸindeki giriÅŸler için maksimum kullanım süresi deÄŸerini ayarlayın (saniye olarak)", + "overrideMaximumTtlDescription": "DNS yanıtlarını önbelleÄŸe alırken üst sunucudan alınan maksimum kullanım süresi deÄŸerini (TTL) saniye olarak ayarlayın.", "optimisticCaching": "İyimser önbelleÄŸe alma", - "optimisticCachingDescription": "GiriÅŸlerin süresi dolmuÅŸ olsa bile Adguard Home'un önbellekten yanıt vermesini saÄŸlayın ve aynı zamanda bunları yenilemeye çalışın.", + "optimisticCachingDescription": "GiriÅŸlerin süresi dolmuÅŸ olsa bile Adguard Home'un önbellekten yanıt vermesini saÄŸlar ve aynı zamanda bunları yenilemeye çalışır.", "loadingDnsConfig": "DNS yapılandırması yükleniyor...", "dnsConfigNotLoaded": "DNS yapılandırması yüklenemedi.", "blockingIpv4": "IPv4 engelleniyor", @@ -487,7 +487,7 @@ "dnsConfigNotSaved": "DNS sunucusu yapılandırması kaydedilemedi", "savingConfig": "Yapılandırma kaydediliyor...", "someValueNotValid": "Bazı deÄŸerler geçerli deÄŸil", - "upstreamDnsDescription": "Üst kaynak sunucularını ve DNS modunu yapılandır", + "upstreamDnsDescription": "Üst sunucuları ve DNS modunu yapılandır", "bootstrapDnsDescription": "Önyükleme DNS sunucularını yapılandır", "privateReverseDnsDescription": "Özel DNS çözümleyicileri yapılandır ve özel ters DNS çözümlemeyi etkinleÅŸtir", "dnsServerSettingsDescription": "Hız limiti, engelleme modu ve daha fazlasını yapılandır", @@ -513,13 +513,13 @@ "certificatesDescription": "Åžifreleme kullanmak için, alan adınız için geçerli bir SSL sertifikası zinciri saÄŸlamanız gereklidir. letsencrypt.org'dan ücretsiz bir sertifika alabilir veya güvenilir sertifika yetkililerinden satın alabilirsiniz.", "certificateFilePath": "Sertifika dosyası belirle", "pasteCertificateContent": "Sertifika içeriÄŸini yapıştır", - "certificatePath": "Sertifika dosya yolu", + "certificatePath": "Sertifikanın dosya yolu", "certificateContent": "Sertifika içeriÄŸi", "privateKey": "Özel anahtarlar", "privateKeyFile": "Özel anahtar dosyası belirle", "pastePrivateKey": "Özel anahtar içeriÄŸini yapıştır", - "usePreviousKey": "Önceden kaydedilmiÅŸ anahtarı kullan", - "privateKeyPath": "Özel anahtar dosya yolu", + "usePreviousKey": "Önceden kaydedilmiÅŸ olan anahtarı kullan", + "privateKeyPath": "Özel anahtarın dosya yolu", "invalidCertificate": "Geçersiz sertifika", "invalidPrivateKey": "Geçersiz özel anahtar", "validatingData": "Veri doÄŸrulama", @@ -560,8 +560,8 @@ "validPrivateKey": "Geçerli özel anahtar", "expirationDate": "Son kullanma tarihi", "keysNotMatch": "Geçersiz bir sertifika veya anahtar: tls: özel anahtar genel anahtarla eÅŸleÅŸmiyor.", - "timeLogs": "Günlüklerdeki iÅŸlem süresi", - "timeLogsDescription": "Günlükler listesinde zaman yerine iÅŸlem süresini göster", + "timeLogs": "Günlüklerde iÅŸlem süresi göster", + "timeLogsDescription": "Günlükler listesinde zaman yerine iÅŸlem süresini göster.", "hostNames": "Ana bilgisayar adları", "keyType": "Anahtar türü", "updateAvailable": "Güncelleme mevcut", @@ -591,7 +591,7 @@ "updates": "Güncellemeler", "updatesDescription": "AdGuard Home sunucusunu güncelle", "updateNow": "Åžimdi güncelle", - "currentVersion": "Mevcut sürüm", + "currentVersion": "Yüklü sürüm", "requestStartUpdateFailed": "Güncellemeyi baÅŸlatma isteÄŸi baÅŸarısız oldu", "requestStartUpdateSuccessful": "Güncellemeyi baÅŸlatma isteÄŸi baÅŸarılı", "serverUpdated": "Sunucu güncellendi", @@ -618,15 +618,15 @@ "copiedClipboard": "Panoya kopyalandı", "seeDetails": "Detayları gör", "listNotAvailable": "Liste mevcut deÄŸil", - "copyListUrl": "Liste baÄŸlantısını kopyala", - "listUrlCopied": "Panoya kopyalanan baÄŸlantı adresini listeleyin", + "copyListUrl": "BaÄŸlantıyı kopyala", + "listUrlCopied": "Liste baÄŸlantısı panoya kopyalandı", "unsupportedVersion": "Desteklenmeyen sürüm", "unsupprtedVersionMessage": "Sunucu sürümünüz {version} için destek garantisi verilmiyor. Bu uygulamanın bu sunucu sürümüyle çalışmasında bazı sorunlar olabilir. AdGuard Home Yöneticisi, AdGuard Home sunucunun kararlı sürümleriyle çalışacak ÅŸekilde tasarlanmıştır. Alfa ve beta sürümleriyle çalışabilir, ancak uyumluluk garanti edilmez ve uygulama bu sürümlerle çalışırken bazı sorunlar yaÅŸayabilir.", "iUnderstand": "Anladım", "appUpdates": "Uygulama güncellemeleri", - "usingLatestVersion": "En son sürümü kullanıyorsunuz :)", - "ipLogs": "Günlüklerdeki IP", - "ipLogsDescription": "Günlükler listesinde istemci adı yerine IP adresini göster", + "usingLatestVersion": "En son sürümü kullanıyorsunuz", + "ipLogs": "Günlüklerde IP adresini göster", + "ipLogsDescription": "Günlükler listesinde istemci adı yerine IP adresini göster.", "application": "Uygulama", "combinedChart": "BirleÅŸtirilmiÅŸ grafik", "combinedChartDescription": "Tüm grafikleri bir araya getirir.", @@ -655,11 +655,11 @@ "queries": "Sorgular", "adultSites": "YetiÅŸkin içerikler", "quickFilters": "Hızlı filtreler", - "searchDomainInternet": "İnternette alan adı ara", + "searchDomainInternet": "Alan adını arat", "hideServerAddress": "Sunucu adresini gizle", "hideServerAddressDescription": "Ana ekranda sunucu adresini gizler.", "topItemsOrder": "Öne çıkan öğeler sıralaması", - "topItemsOrderDescription": "Ana ekrandaki öne çıkan öğe listelerini sırala", + "topItemsOrderDescription": "Ana ekrandaki öne çıkan öğe listelerini sıralayın.", "topItemsReorderInfo": "Yeniden sıralamak için bir öğeyi basılı tutun ve kaydırın.", "discardChanges": "DeÄŸiÅŸiklikleri iptal et", "discardChangesDescription": "DeÄŸiÅŸiklikleri iptal etmek istediÄŸinizden emin misiniz?", @@ -687,6 +687,92 @@ "unsupportedServerVersionMessage": "AdGuard Home sunucu sürümünüz çok eski ve AdGuard Home Manager tarafından desteklenmiyor. Bu uygulamayı kullanmak için AdGuard Home sunucunuzu daha yeni bir sürüme yükseltmeniz gerekecektir.", "yourVersion": "Yüklü sürüm: {version}", "minimumRequiredVersion": "Gerekli minimum sürüm: {version}", - "topUpstreams": "Öne çıkan üst kaynaklar", - "averageUpstreamResponseTime": "Üst kaynak ortalama yanıt süresi" -} + "topUpstreams": "Öne çıkan DNS sunucuları", + "averageUpstreamResponseTime": "DNS sunucusu ortalama iÅŸlem süresi" , + "dhcpNotAvailable": "DHCP sunucusu kullanılamıyor.", + "osServerInstalledIncompatible": "AdGuard Home, iÅŸletim sisteminizde DHCP sunucusu çalıştıramıyor.", + "resetSettings": "Ayarları sıfırla", + "resetEncryptionSettingsDescription": "Åžifreleme ayarlarını sıfırlamak istediÄŸinizden emin misiniz?", + "resettingConfig": "Yapılandırma sıfırlanıyor...", + "configurationResetSuccessfully": "Yapılandırma baÅŸarıyla sıfırlandı", + "configurationResetError": "Yapılandırma sıfırlanamadı", + "testUpstreamDnsServers": "DNS sunucusunu test et", + "errorTestUpstreamDns": "DNS sunucularını test ederken hata oluÅŸtu.", + "useCustomIpEdns": "EDNS için özel IP kullan", + "useCustomIpEdnsDescription": "EDNS için özel IP kullanımına izin ver", + "sortingOptions": "Sıralama seçenekleri", + "fromHighestToLowest": "Yüksekten düşüğe", + "fromLowestToHighest": "Düşükten yükseÄŸe", + "queryLogsAndStatistics": "Sorgu günlüğü ve istatistikler", + "ignoreClientQueryLog": "Sorgu günlüğünde bu istemciyi yoksay", + "ignoreClientStatistics": "İstatistiklerde bu istemciyi yoksay", + "savingChanges": "DeÄŸiÅŸiklikler kaydediliyor...", + "fallbackDnsServers": "Yedek DNS sunucuları", + "fallbackDnsServersDescription": "Yedek DNS sunucularını yapılandır", + "fallbackDnsServersInfo": "Üst DNS sunucuları yanıt vermediÄŸinde kullanılan yedek DNS sunucularının listesi. Sözdizimi, yukarıdaki ana üst kaynak alanıyla aynıdır.", + "noFallbackDnsAdded": "Yedek DNS sunucusu eklenmedi.", + "blockedResponseTtl": "Engellenen yanıtın kullanım süresi", + "blockedResponseTtlDescription": "İstemcilerin filtrelenmiÅŸ bir yanıtı kaç saniye süreyle önbelleÄŸe alması gerektiÄŸini belirtir", + "invalidValue": "Geçersiz deÄŸer", + "noDataChart": "Bu grafiÄŸi görüntüleyecek veri yok.", + "noData": "Veri yok", + "unblockClient": "İstemci engelini kaldır", + "blockingClient": "İstemci engelleniyor...", + "unblockingClient": "İstemci engeli kaldırılıyor...", + "upstreamDnsCacheConfiguration": "DNS önbellek yapılandırması", + "enableDnsCachingClient": "Bu istemci için DNS önbelleÄŸe almayı etkinleÅŸtir", + "dnsCacheSize": "DNS önbellek boyutu (bayt cinsinden)", + "nameInvalid": "Ad gereklidir", + "oneIdentifierRequired": "En az bir tanımlayıcı gereklidir", + "dnsCacheNumber": "DNS önbellek boyutu bir rakam içermelidir", + "errors": "Hatalar", + "redirectHttpsWarning": "AdGuard Home sunucunuzda \"Otomatik olarak HTTPS'e yönlendir\" seçeneÄŸini etkinleÅŸtirdiyseniz, bir HTTPS baÄŸlantısı seçmeli ve sunucunuzun HTTPS baÄŸlantı noktasını kullanmalısınız.", + "logsSettingsDescription": "Sorgu günlüklerini yapılandır", + "ignoredDomains": "Yok sayılan alan adları", + "noIgnoredDomainsAdded": "Yok sayılacak alan adı eklenmedi", + "pauseServiceBlocking": "Hizmet engellemeyi duraklat", + "newSchedule": "Yeni program", + "editSchedule": "Programı düzenle", + "timezone": "Zaman dilimi", + "monday": "Pazartesi", + "tuesday": "Salı", + "wednesday": "ÇarÅŸamba", + "thursday": "PerÅŸembe", + "friday": "Cuma", + "saturday": "Cumartesi", + "sunday": "Pazar", + "from": "BaÅŸlangıç: {from}", + "to": "BitiÅŸ: {to}", + "selectStartTime": "BaÅŸlangıç zamanını seç", + "selectEndTime": "BitiÅŸ zamanını seç", + "startTimeBeforeEndTime": "BaÅŸlangıç zamanı bitiÅŸ zamanından önce olmalıdır.", + "noBlockingScheduleThisDevice": "Bu cihaz için herhangi bir engelleme programı bulunmamaktadır.", + "selectTimezone": "Bir zaman dilimi seç", + "selectClientsFiltersInfo": "Görüntülemek istediÄŸiniz istemcileri seçin. Hiçbir istemci seçilmemiÅŸse, hepsi görüntülenecektir.", + "noDataThisSection": "Bu bölüm için veri yok.", + "statisticsSettings": "İstatistik ayarları", + "statisticsSettingsDescription": "İstatistikler için veri toplamayı yapılandır", + "loadingStatisticsSettings": "İstatistik ayarları yükleniyor...", + "statisticsSettingsLoadError": "İstatistik ayarları yüklenirken bir hata oluÅŸtu.", + "customTimeInHours": "Özel zaman (saat olarak)", + "invalidTime": "Geçersiz zaman", + "removeDomain": "Alan adını kaldır", + "addDomain": "Alan adı ekle", + "notLess1Hour": "Zaman 1 saatten az olamaz", + "rateLimit": "Hız sınırı", + "subnetPrefixLengthIpv4": "IPv4 için alt aÄŸ önek uzunluÄŸu", + "subnetPrefixLengthIpv6": "IPv6 için alt aÄŸ önek uzunluÄŸu", + "rateLimitAllowlist": "Hız sınırlama izin listesi", + "rateLimitAllowlistDescription": "Hız sınırlamasından hariç tutulan IP adresleri", + "dnsOptions": "DNS ayarları", + "editor": "Editör", + "editCustomRules": "Özel kuralları düzenle", + "savingCustomRules": "Özel kurallar kaydediliyor...", + "customRulesUpdatedSuccessfully": "Özel kurallar baÅŸarıyla güncellendi", + "customRulesNotUpdated": "Özel kurallar güncellenemedi", + "reorder": "Sırala", + "showHide": "Göster/gizle", + "noElementsReorderMessage": "Burada yeniden sıralamak için göster/gizle sekmesindeki bazı öğeleri etkinleÅŸtirin.", + "enablePlainDns": "Düz DNS'i etkinleÅŸtir", + "enablePlainDnsDescription": "Düz DNS varsayılan olarak etkindir. Tüm aygıtları ÅŸifrelenmiÅŸ DNS kullanmaya zorlamak için bunu devre dışı bırakabilirsiniz. Bunu yapmak için en az bir ÅŸifrelenmiÅŸ DNS protokolünü etkinleÅŸtirmeniz gerekir." +} \ No newline at end of file From dba9c8b9ac4be5a018c0ec2664c52505944b5b3e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 9 Feb 2024 01:29:11 +0100 Subject: [PATCH 551/676] Bug fixes --- lib/l10n/app_tr.arb | 4 ++-- lib/screens/filters/add_button.dart | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 12c8980..9e84991 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -741,8 +741,8 @@ "friday": "Cuma", "saturday": "Cumartesi", "sunday": "Pazar", - "from": "BaÅŸlangıç: {from}", - "to": "BitiÅŸ: {to}", + "from": "BaÅŸlangıç", + "to": "BitiÅŸ", "selectStartTime": "BaÅŸlangıç zamanını seç", "selectEndTime": "BitiÅŸ zamanını seç", "startTimeBeforeEndTime": "BaÅŸlangıç zamanı bitiÅŸ zamanından önce olmalıdır.", diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index bc5a22f..7f7663e 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -144,6 +144,7 @@ class AddFiltersButton extends StatelessWidget { processModal.close(); + if (!context.mounted) return; if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, From 34246d238bd21d0f46e8039f81d3b3596a043a1f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 9 Feb 2024 01:29:16 +0100 Subject: [PATCH 552/676] Updated libraries --- pubspec.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 0f65427..c1c90ca 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -141,10 +141,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "0042cb3b2a76413ea5f8a2b40cec2a33e01d0c937e91f0f7c211fde4f7739ba6" + sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110" url: "https://pub.dev" source: hosted - version: "9.1.1" + version: "9.1.2" device_info_plus_platform_interface: dependency: transitive description: @@ -386,10 +386,10 @@ packages: dependency: transitive description: name: image - sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d" + sha256: "49a0d4b0c12402853d3f227fe7c315601b238d126aa4caa5dbb2dcf99421aa4a" url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "4.1.6" intl: dependency: "direct main" description: @@ -594,18 +594,18 @@ packages: dependency: transitive description: name: sentry - sha256: "5686ed515bb620dc52b4ae99a6586fe720d443591183cf1f620ec5d1f0eec100" + sha256: a7946f4a90b0feb47214981d881b98149e05f6c576da9f2a2f33945bf561de25 url: "https://pub.dev" source: hosted - version: "7.15.0" + version: "7.16.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "505dec3b6810562785d2c34ae871c73ff2cba6cf436c32c188f0464df226ba8f" + sha256: "6db7fa1b076faf2f5dd77d8cc9ef206171f32a290cc638842d78e5d62b441a27" url: "https://pub.dev" source: hosted - version: "7.15.0" + version: "7.16.0" shared_preferences: dependency: "direct main" description: @@ -703,10 +703,10 @@ packages: dependency: "direct main" description: name: sqflite_common_ffi - sha256: d0e3f0d04fdf668e57db8db1df758f56c4193cb429092c708e7bfcc6ab04b27e + sha256: "754927d82de369a6b9e760fb60640aa81da650f35ffd468d5a992814d6022908" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.2+1" sqlite3: dependency: transitive description: @@ -719,10 +719,10 @@ packages: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: "90963b515721d6a71e96f438175cf43c979493ed14822860a300b69694c74eb6" + sha256: d6c31c8511c441d1f12f20b607343df1afe4eddf24a1cf85021677c8eea26060 url: "https://pub.dev" source: hosted - version: "0.5.19+1" + version: "0.5.20" stack_trace: dependency: transitive description: @@ -879,26 +879,26 @@ packages: dependency: transitive description: name: vector_graphics - sha256: "18f6690295af52d081f6808f2f7c69f0eed6d7e23a71539d75f4aeb8f0062172" + sha256: "4ac59808bbfca6da38c99f415ff2d3a5d7ca0a6b4809c71d9cf30fba5daf9752" url: "https://pub.dev" source: hosted - version: "1.1.9+2" + version: "1.1.10+1" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: "531d20465c10dfac7f5cd90b60bbe4dd9921f1ec4ca54c83ebb176dbacb7bb2d" + sha256: f3247e7ab0ec77dc759263e68394990edc608fb2b480b80db8aa86ed09279e33 url: "https://pub.dev" source: hosted - version: "1.1.9+2" + version: "1.1.10+1" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "03012b0a33775c5530576b70240308080e1d5050f0faf000118c20e6463bc0ad" + sha256: "18489bdd8850de3dd7ca8a34e0c446f719ec63e2bab2e7a8cc66a9028dd76c5a" url: "https://pub.dev" source: hosted - version: "1.1.9+2" + version: "1.1.10+1" vector_math: dependency: transitive description: From 6985efc4cb4c36fd5906f4eab2e99d199d136128 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 9 Feb 2024 01:44:31 +0100 Subject: [PATCH 553/676] Small improvement --- lib/screens/logs/logs_list_appbar.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index ee4dfd1..e4bf2ed 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -62,7 +62,7 @@ class LogsListAppBar extends StatelessWidget { "blocked_parental": AppLocalizations.of(context)!.blockedParentalRow, "safe_search": AppLocalizations.of(context)!.safeSearch, }; - +print(MediaQuery.of(context).viewPadding.top); return SliverAppBar.large( pinned: true, floating: true, @@ -80,6 +80,7 @@ class LogsListAppBar extends StatelessWidget { onPressed: () => showDialog( context: context, builder: (context) => _Search( + hasTopBar: MediaQuery.of(context).viewPadding.top > 0, onSearch: (v) { logsProvider.setAppliedFilters( AppliedFiters( @@ -234,9 +235,11 @@ class LogsListAppBar extends StatelessWidget { class _Search extends StatefulWidget { final void Function(String) onSearch; + final bool hasTopBar; const _Search({ - required this.onSearch + required this.onSearch, + required this.hasTopBar, }); @override @@ -270,7 +273,9 @@ class _SearchState extends State<_Search> { child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 500), child: Container( - margin: const EdgeInsets.all(16), + margin: widget.hasTopBar + ? const EdgeInsets.symmetric(horizontal: 16) + : const EdgeInsets.all(16), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16) From e2757d4b8f85a9db99d9ea86dabafc5fa1b3ff49 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 9 Feb 2024 01:45:02 +0100 Subject: [PATCH 554/676] Upgraded android gradle and macos podfile --- .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/settings.gradle | 2 +- macos/Podfile.lock | 32 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index cb24abd..3c472b9 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index eeb0d0e..b14b9f7 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.2.2" apply false + id "com.android.application" version '7.4.2' apply false id "org.jetbrains.kotlin.android" version "1.8.20" apply false } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index f5e5c0c..a257617 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -6,31 +6,31 @@ PODS: - FlutterMacOS (1.0.0) - package_info_plus (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.18.0): - - SentryPrivate (= 8.18.0) + - Sentry/HybridSDK (8.19.0): + - SentryPrivate (= 8.19.0) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.18.0) - - SentryPrivate (8.18.0) + - Sentry/HybridSDK (= 8.19.0) + - SentryPrivate (8.19.0) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - sqflite (0.0.3): - Flutter - FlutterMacOS - - sqlite3 (3.45.0): - - sqlite3/common (= 3.45.0) - - sqlite3/common (3.45.0) - - sqlite3/fts5 (3.45.0): + - sqlite3 (3.45.1): + - sqlite3/common (= 3.45.1) + - sqlite3/common (3.45.1) + - sqlite3/fts5 (3.45.1): - sqlite3/common - - sqlite3/perf-threadsafe (3.45.0): + - sqlite3/perf-threadsafe (3.45.1): - sqlite3/common - - sqlite3/rtree (3.45.0): + - sqlite3/rtree (3.45.1): - sqlite3/common - sqlite3_flutter_libs (0.0.1): - FlutterMacOS - - sqlite3 (~> 3.45.0) + - sqlite3 (~> 3.45.1) - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree @@ -84,13 +84,13 @@ SPEC CHECKSUMS: dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - Sentry: 8984a4ffb2b9bd2894d74fb36e6f5833865bc18e - sentry_flutter: c87a0556eeb6cbf7f9f924d30e878bdedf22d364 - SentryPrivate: 2f0c9ba4c3fc993f70eab6ca95673509561e0085 + Sentry: 1ebcaef678a27c8ac515f974cb5425dd1bbdec2f + sentry_flutter: ecdfbedee55337205561cfa782ee02d31ec83e1f + SentryPrivate: 765c9b4ebe9ac1a5fcdc067c5a1cfbf3f10e1677 shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec - sqlite3: f307b6291c4db7b5086c38d6237446b98a738581 - sqlite3_flutter_libs: 6b9913d8fbb718e5ebf23658aa6934a0fb509c0f + sqlite3: 73b7fc691fdc43277614250e04d183740cb15078 + sqlite3_flutter_libs: 06a05802529659a272beac4ee1350bfec294f386 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 From 9cd480aa9a094b133c9fb6c41c1fd728bab15a7e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 9 Feb 2024 01:48:32 +0100 Subject: [PATCH 555/676] Disable plain dns on general disabled --- lib/screens/settings/encryption/encryption.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 3c678b8..4e48f6c 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -383,6 +383,7 @@ class _EncryptionSettingsState extends State { onChanged: (v) => setState(() => _plainDns = v), title: AppLocalizations.of(context)!.enablePlainDns, subtitle: AppLocalizations.of(context)!.enablePlainDnsDescription, + disabled: enabled == false, ), ], SectionLabel( From eb703c6f5815a0d7acb24c1b826cd5c64e14bacd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 9 Feb 2024 01:48:56 +0100 Subject: [PATCH 556/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 5b76b9a..7a260b5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.16.0-beta.3+129 +version: 2.16.0+130 environment: sdk: '>=2.18.1 <3.0.0' From ca4fa5d7dfd221a9a33b0acc6a43e7d60b460f0a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 9 Feb 2024 03:00:42 +0100 Subject: [PATCH 557/676] Bug fixes --- lib/screens/clients/clients.dart | 2 +- lib/screens/filters/add_button.dart | 4 +-- .../filters/filters_triple_column.dart | 27 ++++++++++++++----- .../add_custom_rule.dart | 2 +- .../custom_rule_docs.dart | 0 .../edit_custom_rules.dart | 5 ++-- lib/screens/settings/settings.dart | 4 ++- 7 files changed, 29 insertions(+), 15 deletions(-) rename lib/screens/filters/modals/{add_custom_rule => custom_rules}/add_custom_rule.dart (99%) rename lib/screens/filters/modals/{add_custom_rule => custom_rules}/custom_rule_docs.dart (100%) rename lib/screens/filters/modals/{add_custom_rule => custom_rules}/edit_custom_rules.dart (95%) diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 3d494ae..1549bb6 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -23,7 +23,7 @@ class _ClientsState extends State with TickerProviderStateMixin { return Scaffold( body: LayoutBuilder( builder: (context, constraints) { - if (constraints.maxWidth > 1000) { + if (constraints.maxWidth > 900) { return SplitView.material( hideDivider: true, flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 7f7663e..be9f0f4 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -6,8 +6,8 @@ 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/filters/modals/add_custom_rule/edit_custom_rules.dart'; -import 'package:adguard_home_manager/screens/filters/modals/add_custom_rule/add_custom_rule.dart'; +import 'package:adguard_home_manager/screens/filters/modals/custom_rules/edit_custom_rules.dart'; +import 'package:adguard_home_manager/screens/filters/modals/custom_rules/add_custom_rule.dart'; import 'package:adguard_home_manager/screens/filters/details/add_list_modal.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 7d15639..686ee15 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -247,21 +247,34 @@ class FiltersTripleColumn extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - AppLocalizations.of(context)!.customRules, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500 + Flexible( + child: Text( + AppLocalizations.of(context)!.customRules, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500 + ), ), ), + const SizedBox(width: 16), AddFiltersButton( - type: '', + type: 'edit_custom_rule', + widget: (fn) => IconButton( + onPressed: fn, + icon: const Icon(Icons.edit_rounded), + tooltip: AppLocalizations.of(context)!.editCustomRules, + ) + ), + const SizedBox(width: 8), + AddFiltersButton( + type: 'add_custom_rule', widget: (fn) => IconButton( onPressed: fn, icon: const Icon(Icons.add_rounded), tooltip: AppLocalizations.of(context)!.addCustomRule, ) - ) + ), ], ), ), diff --git a/lib/screens/filters/modals/add_custom_rule/add_custom_rule.dart b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart similarity index 99% rename from lib/screens/filters/modals/add_custom_rule/add_custom_rule.dart rename to lib/screens/filters/modals/custom_rules/add_custom_rule.dart index ad43ebb..00fe303 100644 --- a/lib/screens/filters/modals/add_custom_rule/add_custom_rule.dart +++ b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:segmented_button_slide/segmented_button_slide.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/filters/modals/add_custom_rule/custom_rule_docs.dart'; +import 'package:adguard_home_manager/screens/filters/modals/custom_rules/custom_rule_docs.dart'; enum _BlockingPresets { block, unblock, custom } diff --git a/lib/screens/filters/modals/add_custom_rule/custom_rule_docs.dart b/lib/screens/filters/modals/custom_rules/custom_rule_docs.dart similarity index 100% rename from lib/screens/filters/modals/add_custom_rule/custom_rule_docs.dart rename to lib/screens/filters/modals/custom_rules/custom_rule_docs.dart diff --git a/lib/screens/filters/modals/add_custom_rule/edit_custom_rules.dart b/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart similarity index 95% rename from lib/screens/filters/modals/add_custom_rule/edit_custom_rules.dart rename to lib/screens/filters/modals/custom_rules/edit_custom_rules.dart index e1fc1d1..ba02ab0 100644 --- a/lib/screens/filters/modals/add_custom_rule/edit_custom_rules.dart +++ b/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart @@ -2,7 +2,7 @@ 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/filters/modals/add_custom_rule/custom_rule_docs.dart'; +import 'package:adguard_home_manager/screens/filters/modals/custom_rules/custom_rule_docs.dart'; import 'package:adguard_home_manager/providers/filtering_provider.dart'; @@ -26,7 +26,6 @@ class _EditCustomRulesState extends State { @override void initState() { final filteringProvider = Provider.of(context, listen: false); - print(filteringProvider.filtering!.userRules); if (filteringProvider.filtering != null) { _fieldController.text = filteringProvider.filtering!.userRules.join("\n"); } @@ -87,7 +86,7 @@ class _EditCustomRulesState extends State { ), const SizedBox(width: 8), Text( - AppLocalizations.of(context)!.addCustomRule, + AppLocalizations.of(context)!.editCustomRules, style: const TextStyle( fontSize: 22 ), diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index e16a84e..9ebe282 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -83,6 +83,8 @@ class _SettingsWidget extends StatefulWidget { } class _SettingsWidgetState extends State<_SettingsWidget> { + final scaffoldMessengerKey = GlobalKey(); + @override void initState() { Provider.of(context, listen: false).setSelectedSettingsScreen(screen: null); @@ -102,7 +104,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { } return ScaffoldMessenger( - key: widget.twoColumns ? GlobalKey() : null, + key: widget.twoColumns ? scaffoldMessengerKey : null, child: Scaffold( body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ From c60b62345b1f265554459e8f9962c622a9a5c783 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 9 Feb 2024 03:01:09 +0100 Subject: [PATCH 558/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 7a260b5..2c1f9b0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.16.0+130 +version: 2.16.1+131 environment: sdk: '>=2.18.1 <3.0.0' From 568b879054f5cf6f2db27458a675115597bfee18 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 18 Feb 2024 21:30:08 +0100 Subject: [PATCH 559/676] Added client name added clients desktop --- lib/screens/clients/client/added_client_tile.dart | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/screens/clients/client/added_client_tile.dart b/lib/screens/clients/client/added_client_tile.dart index 8c10fd7..5af9e46 100644 --- a/lib/screens/clients/client/added_client_tile.dart +++ b/lib/screens/clients/client/added_client_tile.dart @@ -81,7 +81,7 @@ class _AddedClientTileState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + widget.client.name, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, @@ -89,6 +89,15 @@ class _AddedClientTileState extends State { ), ), const SizedBox(height: 8), + Text( + widget.client.ids.toString().replaceAll(RegExp(r'^\[|\]$'), ''), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 8), Row( children: [ Icon( From 923fb97f031604e64ed8cdfaa40f83934652e766 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 18 Feb 2024 21:37:06 +0100 Subject: [PATCH 560/676] Added date log details --- lib/functions/check_app_updates.dart | 2 +- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/providers/filtering_provider.dart | 1 - .../logs/details/log_details_screen.dart | 333 ++++++++++-------- lib/screens/logs/logs_list_appbar.dart | 2 +- lib/services/api_client.dart | 1 - 7 files changed, 184 insertions(+), 161 deletions(-) diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart index e002556..dc08f29 100644 --- a/lib/functions/check_app_updates.dart +++ b/lib/functions/check_app_updates.dart @@ -30,7 +30,7 @@ Future checkAppUpdates({ gitHubRelease: gitHubRelease, isBeta: isBeta ); -print(update); + if (update == true) { setUpdateAvailable(gitHubRelease); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 1869104..9df4e41 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -774,5 +774,6 @@ "showHide": "Show/hide", "noElementsReorderMessage": "Enable some elements on the show/hide tab to reorder them here.", "enablePlainDns": "Enable plain DNS", - "enablePlainDnsDescription": "Plain DNS is enabled by default. You can disable it to force all devices to use encrypted DNS. To do this, you must enable at least one encrypted DNS protocol." + "enablePlainDnsDescription": "Plain DNS is enabled by default. You can disable it to force all devices to use encrypted DNS. To do this, you must enable at least one encrypted DNS protocol.", + "date": "Date" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 7070fea..eed494f 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -774,5 +774,6 @@ "showHide": "Mostrar/ocultar", "noElementsReorderMessage": "Activa algunos elementos en la pestaña de mostrar/ocultar para reordenarlos aquí.", "enablePlainDns": "Activar DNS simple (sin cifrado)", - "enablePlainDnsDescription": "El DNS simple (sin cifrado) está activado de forma predeterminada. Puedes desactivarlo para obligar a todos los dispositivos a utilizar DNS cifrado. Para ello, debes habilitar al menos un protocolo DNS cifrado." + "enablePlainDnsDescription": "El DNS simple (sin cifrado) está activado de forma predeterminada. Puedes desactivarlo para obligar a todos los dispositivos a utilizar DNS cifrado. Para ello, debes habilitar al menos un protocolo DNS cifrado.", + "date": "Fecha" } \ No newline at end of file diff --git a/lib/providers/filtering_provider.dart b/lib/providers/filtering_provider.dart index d43a1b5..9947233 100644 --- a/lib/providers/filtering_provider.dart +++ b/lib/providers/filtering_provider.dart @@ -133,7 +133,6 @@ class FilteringProvider with ChangeNotifier { if (result2.successful == true) { _filtering = result2.content as Filtering; notifyListeners(); - print(result.content); return { "success": true, "data": result.content diff --git a/lib/screens/logs/details/log_details_screen.dart b/lib/screens/logs/details/log_details_screen.dart index 42918dd..0c35f35 100644 --- a/lib/screens/logs/details/log_details_screen.dart +++ b/lib/screens/logs/details/log_details_screen.dart @@ -37,27 +37,6 @@ class LogDetailsScreen extends StatelessWidget { final width = MediaQuery.of(context).size.width; - Filter? getList(int id) { - try { - return statusProvider.filteringStatus!.filters.firstWhere((filter) => filter.id == id, orElse: () { - return statusProvider.filteringStatus!.whitelistFilters.firstWhere((filter) => filter.id == id); - }); - } catch (_) { - return null; - } - } - - Widget getResult() { - final filter = getFilteredStatus(context, appConfigProvider, log.reason, true); - return Text( - filter['label'], - style: TextStyle( - color: filter['color'], - fontWeight: FontWeight.w500 - ), - ); - } - void blockUnblock(String domain, String newStatus) async { final ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingUserFilters); @@ -85,8 +64,175 @@ class LogDetailsScreen extends StatelessWidget { } } - List content() { - return [ + if (dialog) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.clear_rounded) + ), + const SizedBox(width: 16), + Text( + AppLocalizations.of(context)!.logDetails, + style: const TextStyle( + fontSize: 22 + ), + ), + ], + ), + Row( + children: [ + IconButton( + onPressed: () => openUrl("${Urls.googleSearchUrl}?q=${log.question.name}"), + icon: const Icon(Icons.travel_explore_rounded), + tooltip: AppLocalizations.of(context)!.searchDomainInternet + ), + IconButton( + onPressed: log.question.name != null + ? () => blockUnblock( + log.question.name!, + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' + ) + : null, + icon: Icon( + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? Icons.check_circle_rounded + : Icons.block + ), + tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? AppLocalizations.of(context)!.unblockDomain + : AppLocalizations.of(context)!.blockDomain, + ), + ], + ) + ], + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: ListView( + children: [ + _Content(log: log) + ] + ) + ), + ) + ], + ), + ), + ); + } + else { + return Scaffold( + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + surfaceTintColor: isDesktop(width) ? Colors.transparent : null, + title: Text(AppLocalizations.of(context)!.logDetails), + actions: [ + IconButton( + onPressed: () => openUrl("${Urls.googleSearchUrl}?q=${log.question.name}"), + icon: const Icon(Icons.travel_explore_rounded), + tooltip: AppLocalizations.of(context)!.searchDomainInternet + ), + if (statusProvider.filteringStatus != null) IconButton( + onPressed: log.question.name != null + ? () => blockUnblock( + log.question.name!, + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' + ) + : null, + icon: Icon( + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? Icons.check_circle_rounded + : Icons.block + ), + tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true + ? AppLocalizations.of(context)!.unblockDomain + : AppLocalizations.of(context)!.blockDomain, + ), + const SizedBox(width: 10) + ], + ), + ) + ], + body: SafeArea( + top: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + _Content(log: log) + ] + ) + ], + ), + ) + ) + ), + ); + } + } +} + +class _Content extends StatelessWidget { + final Log log; + + const _Content({ + required this.log, + }); + + @override + Widget build(BuildContext context) { + final appConfigProvider = Provider.of(context); + final statusProvider = Provider.of(context); + + Widget getResult() { + final filter = getFilteredStatus(context, appConfigProvider, log.reason, true); + return Text( + filter['label'], + style: TextStyle( + color: filter['color'], + fontWeight: FontWeight.w500 + ), + ); + } + + Filter? getList(int id) { + try { + return statusProvider.filteringStatus!.filters.firstWhere((filter) => filter.id == id, orElse: () { + return statusProvider.filteringStatus!.whitelistFilters.firstWhere((filter) => filter.id == id); + }); + } catch (_) { + return null; + } + } + + return Column( + children: [ SectionLabel(label: AppLocalizations.of(context)!.status), LogListTile( icon: Icons.shield_rounded, @@ -118,6 +264,11 @@ class LogDetailsScreen extends StatelessWidget { title: AppLocalizations.of(context)!.blockingRule, subtitle: log.rule ), + LogListTile( + icon: Icons.calendar_month_rounded, + title: AppLocalizations.of(context)!.date, + subtitle: convertTimestampLocalTimezone(log.time, 'dd-MM-yyyy') + ), LogListTile( icon: Icons.schedule, title: AppLocalizations.of(context)!.time, @@ -180,7 +331,7 @@ class LogDetailsScreen extends StatelessWidget { else { return const SizedBox(); } - }).toList() + }) ], if (log.answer.isNotEmpty) ...[ SectionLabel(label: AppLocalizations.of(context)!.answers), @@ -206,137 +357,9 @@ class LogDetailsScreen extends StatelessWidget { ), ), ) - )).toList() + )) ] - ]; - } - - if (dialog) { - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.clear_rounded) - ), - const SizedBox(width: 16), - Text( - AppLocalizations.of(context)!.logDetails, - style: const TextStyle( - fontSize: 22 - ), - ), - ], - ), - Row( - children: [ - IconButton( - onPressed: () => openUrl("${Urls.googleSearchUrl}?q=${log.question.name}"), - icon: const Icon(Icons.travel_explore_rounded), - tooltip: AppLocalizations.of(context)!.searchDomainInternet - ), - IconButton( - onPressed: log.question.name != null - ? () => blockUnblock( - log.question.name!, - getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' - ) - : null, - icon: Icon( - getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? Icons.check_circle_rounded - : Icons.block - ), - tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? AppLocalizations.of(context)!.unblockDomain - : AppLocalizations.of(context)!.blockDomain, - ), - ], - ) - ], - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), - child: ListView( - children: content(), - ) - ), - ) - ], - ), - ), - ); - } - else { - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - surfaceTintColor: isDesktop(width) ? Colors.transparent : null, - title: Text(AppLocalizations.of(context)!.logDetails), - actions: [ - IconButton( - onPressed: () => openUrl("${Urls.googleSearchUrl}?q=${log.question.name}"), - icon: const Icon(Icons.travel_explore_rounded), - tooltip: AppLocalizations.of(context)!.searchDomainInternet - ), - if (statusProvider.filteringStatus != null) IconButton( - onPressed: log.question.name != null - ? () => blockUnblock( - log.question.name!, - getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' - ) - : null, - icon: Icon( - getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? Icons.check_circle_rounded - : Icons.block - ), - tooltip: getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true - ? AppLocalizations.of(context)!.unblockDomain - : AppLocalizations.of(context)!.blockDomain, - ), - const SizedBox(width: 10) - ], - ), - ) - ], - body: SafeArea( - top: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverList.list( - children: content() - ) - ], - ), - ) - ) - ), - ); - } + ], + ); } } \ No newline at end of file diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index e4bf2ed..9b5ab3b 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -62,7 +62,7 @@ class LogsListAppBar extends StatelessWidget { "blocked_parental": AppLocalizations.of(context)!.blockedParentalRow, "safe_search": AppLocalizations.of(context)!.safeSearch, }; -print(MediaQuery.of(context).viewPadding.top); + return SliverAppBar.large( pinned: true, floating: true, diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index 4f8ba90..9bc283e 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -913,7 +913,6 @@ class ApiClientV2 { server: server, body: body ); - print(result.body); return ApiResponse(successful: result.successful); } } \ No newline at end of file From e21e34668d051ca81059f2b508e49a432e8d6afc Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 18 Feb 2024 21:41:20 +0100 Subject: [PATCH 561/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 2c1f9b0..94c5042 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.16.1+131 +version: 2.16.2+132 environment: sdk: '>=2.18.1 <3.0.0' From dcad63fe5c0d7388274fd00ae632def0639179c0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 21 Feb 2024 02:34:36 +0100 Subject: [PATCH 562/676] New update server screen --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/screens/settings/settings.dart | 2 +- .../settings/update_server/update_screen.dart | 320 ++++++++++++++++++ 4 files changed, 325 insertions(+), 3 deletions(-) create mode 100644 lib/screens/settings/update_server/update_screen.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 9df4e41..439dac5 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -775,5 +775,6 @@ "noElementsReorderMessage": "Enable some elements on the show/hide tab to reorder them here.", "enablePlainDns": "Enable plain DNS", "enablePlainDnsDescription": "Plain DNS is enabled by default. You can disable it to force all devices to use encrypted DNS. To do this, you must enable at least one encrypted DNS protocol.", - "date": "Date" + "date": "Date", + "loadingChangelog": "Loading changelog..." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index eed494f..79aaa7d 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -775,5 +775,6 @@ "noElementsReorderMessage": "Activa algunos elementos en la pestaña de mostrar/ocultar para reordenarlos aquí.", "enablePlainDns": "Activar DNS simple (sin cifrado)", "enablePlainDnsDescription": "El DNS simple (sin cifrado) está activado de forma predeterminada. Puedes desactivarlo para obligar a todos los dispositivos a utilizar DNS cifrado. Para ello, debes habilitar al menos un protocolo DNS cifrado.", - "date": "Fecha" + "date": "Fecha", + "loadingChangelog": "Cargando registro de cambios..." } \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 9ebe282..718593e 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -14,7 +14,7 @@ import 'package:adguard_home_manager/screens/settings/customization/customizatio import 'package:adguard_home_manager/screens/settings/dhcp/dhcp.dart'; import 'package:adguard_home_manager/screens/settings/statistics_settings/statistics_settings.dart'; import 'package:adguard_home_manager/screens/settings/safe_search_settings.dart'; -import 'package:adguard_home_manager/screens/settings/update_server/update.dart'; +import 'package:adguard_home_manager/screens/settings/update_server/update_screen.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/servers/servers.dart'; diff --git a/lib/screens/settings/update_server/update_screen.dart b/lib/screens/settings/update_server/update_screen.dart new file mode 100644 index 0000000..4dd4b52 --- /dev/null +++ b/lib/screens/settings/update_server/update_screen.dart @@ -0,0 +1,320 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:html/parser.dart' as html; +import 'package:markdown/markdown.dart' as md; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/functions/open_url.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +const _minExent = 64.0; +const _maxExent = 240.0; + +const _iconMaxBottomPositionExent = 130.0; +const _iconMinBottomPositionExent = 34.0; + +const _textMaxBottomPositionExent = 70.0; +const _textMinBottomPositionExent = 16.0; + +const _versionTextMaxBottomPositionExent = 30.0; +const _versionTextMinBottomPositionExent = 0.0; + +const _textMaxFontSize = 24.0; +const _textMinFontSize = 22.0; + +const _iconSafetyMargin = 15.0; + +const _iconSize = 45.0; + +class UpdateScreen extends StatefulWidget { + const UpdateScreen({super.key}); + + @override + State createState() => _UpdateScreenState(); +} + +class _UpdateScreenState extends State { + final _scrollController = ScrollController(); + bool _isScrolled = false; + + String? _htmlChangelog; + + void processChangelog() async { + final serversProvider = Provider.of(context, listen: false); + final markdownResult = await compute(md.markdownToHtml, serversProvider.updateAvailable.data!.changelog!); + final htmlParsedResult = await compute(html.parse, markdownResult); + setState(() => _htmlChangelog = htmlParsedResult.outerHtml); + } + + @override + void initState() { + final serversProvider = Provider.of(context, listen: false); + _scrollController.addListener(() { + final newValue = _scrollController.offset > 20; + if (!( + serversProvider.updatingServer == false && + serversProvider.updateAvailable.data!.canAutoupdate != null && + serversProvider.updateAvailable.data!.canAutoupdate == true + )) return; + if (_isScrolled == newValue) return; + setState(() => _isScrolled = newValue); + }); + + processChangelog(); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void update() async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.requestingUpdate); + + final result = await serversProvider.apiClient2!.requestUpdateServer(); + + processModal.close(); + + if (!mounted) return; + if (result.successful == true) { + serversProvider.recheckPeriodServerUpdated(); + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.requestStartUpdateSuccessful, + color: Colors.green, + labelColor: Colors.white, + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.requestStartUpdateFailed, + color: Colors.red, + labelColor: Colors.white, + ); + } + } + + return Scaffold( + body: SafeArea( + top: false, + child: Stack( + children: [ + CustomScrollView( + controller: _scrollController, + slivers: [ + SliverPersistentHeader( + pinned: true, + delegate: _Header( + onRefresh: () => serversProvider.checkServerUpdatesAvailable( + server: serversProvider.selectedServer!, + ), + viewPaddingTop: MediaQuery.of(context).viewPadding.top + ) + ), + SliverList.list( + children: [ + const SizedBox(height: 16), + if (_htmlChangelog != null) Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + "Changelog ${serversProvider.updateAvailable.data!.canAutoupdate == true + ? serversProvider.updateAvailable.data!.newVersion + : serversProvider.updateAvailable.data!.currentVersion}", + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), + if (_htmlChangelog != null) Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Html( + data: _htmlChangelog, + onLinkTap: (url, context, attributes) => url != null ? openUrl(url) : null, + ) + ), + if (_htmlChangelog == null) Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 32), + child: Column( + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingChangelog, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ) + ], + ) + ), + ] + ) + ], + ), + if ( + serversProvider.updatingServer == false && + serversProvider.updateAvailable.data!.canAutoupdate != null && + serversProvider.updateAvailable.data!.canAutoupdate == true + ) AnimatedPositioned( + right: 20, + bottom: _isScrolled ? -70 : 20, + duration: const Duration(milliseconds: 200), + curve: Curves.ease, + child: FloatingActionButton( + onPressed: () => update(), + tooltip: AppLocalizations.of(context)!.updateNow, + child: const Icon(Icons.download_rounded), + ), + ) + ], + ), + ), + ); + } +} + +class _Header extends SliverPersistentHeaderDelegate { + final void Function() onRefresh; + final double viewPaddingTop; + + const _Header({ + required this.onRefresh, + required this.viewPaddingTop, + }); + + @override + Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { + final serversProvider = Provider.of(context); + + final iconMaxBottomPositionExent = _iconMaxBottomPositionExent + viewPaddingTop; + final iconMinBottomPositionExent = _iconMinBottomPositionExent + viewPaddingTop; + final textMaxBottomPositionExent = _textMaxBottomPositionExent + viewPaddingTop; + final textMinBottomPositionExent = _textMinBottomPositionExent + viewPaddingTop; + final versionTextMaxBottomPositionExent = _versionTextMaxBottomPositionExent + viewPaddingTop; + final versionTextMinBottomPositionExent = _versionTextMinBottomPositionExent + viewPaddingTop; + + final iconPercentage = shrinkOffset.clamp(0, _maxExent-_minExent-_iconSafetyMargin)/(_maxExent-_minExent-_iconSafetyMargin); + final textPercentage = shrinkOffset.clamp(0, _maxExent-_minExent)/(_maxExent-_minExent); + + final textFontSize = _textMinFontSize + (_textMaxFontSize-_textMinFontSize)*(1-textPercentage); + final mainText = _textMinBottomPositionExent + (textMaxBottomPositionExent-textMinBottomPositionExent)*(1-textPercentage); + final versionText = _versionTextMinBottomPositionExent + (versionTextMaxBottomPositionExent-versionTextMinBottomPositionExent)*(1-textPercentage); + + final iconBottom = _iconMinBottomPositionExent + (iconMaxBottomPositionExent-iconMinBottomPositionExent)*(1-iconPercentage); + + return LayoutBuilder( + builder: (context, constraints) => Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceVariant, + ), + child: Align( + alignment: Alignment.topLeft, + child: SafeArea( + bottom: false, + child: Stack( + fit: StackFit.expand, + alignment: Alignment.center, + children: [ + if (Navigator.of(context).canPop()) Positioned( + top: 8, + left: 0, + child: BackButton( + onPressed: () => Navigator.pop(context), + ), + ), + Positioned( + top: 8, + right: 0, + child: IconButton( + onPressed: onRefresh, + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ) + ), + Positioned( + bottom: iconBottom, + left: (constraints.maxWidth/2)-(_iconSize/2), + child: Opacity( + opacity: 1-iconPercentage, + child: Icon( + serversProvider.updateAvailable.data!.canAutoupdate == true + ? Icons.system_update_rounded + : Icons.system_security_update_good_rounded, + size: _iconSize, + color: Theme.of(context).colorScheme.primary, + ), + ), + ), + Positioned( + bottom: mainText, + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth-100 + ), + child: Text( + serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? AppLocalizations.of(context)!.checkingUpdates + : serversProvider.updateAvailable.data!.canAutoupdate == true + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.serverUpdated, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: textFontSize, + fontWeight: FontWeight.w400 + ), + ), + ) + ), + Positioned( + bottom: versionText, + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth-100 + ), + child: Opacity( + opacity: 1-iconPercentage, + child: Text( + serversProvider.updateAvailable.data!.canAutoupdate == true + ? "${AppLocalizations.of(context)!.newVersion}: ${serversProvider.updateAvailable.data!.newVersion ?? 'N/A'}" + : "${AppLocalizations.of(context)!.installedVersion}: ${serversProvider.updateAvailable.data!.currentVersion}", + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), + ) + ) + ], + ), + ), + ), + ), + ); + } + + @override + double get maxExtent => _maxExent + viewPaddingTop; + + @override + double get minExtent => _minExent + viewPaddingTop; + + @override + bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) => false; +} \ No newline at end of file From 7a89aea3a59540c9e7ad92ac93f650702698bc18 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 21 Feb 2024 10:50:02 +0100 Subject: [PATCH 563/676] Changed dns addresses modal --- .../server_info/dns_addresses_modal.dart | 93 +++++++++++-------- .../settings/server_info/server_info.dart | 27 ++++-- 2 files changed, 76 insertions(+), 44 deletions(-) diff --git a/lib/screens/settings/server_info/dns_addresses_modal.dart b/lib/screens/settings/server_info/dns_addresses_modal.dart index 2a6fa2f..e5fb87a 100644 --- a/lib/screens/settings/server_info/dns_addresses_modal.dart +++ b/lib/screens/settings/server_info/dns_addresses_modal.dart @@ -1,54 +1,71 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/widgets/list_bottom_sheet.dart'; + class DnsAddressesModal extends StatelessWidget { + final bool isDialog; final List dnsAddresses; const DnsAddressesModal({ - Key? key, + super.key, + required this.isDialog, required this.dnsAddresses, - }) : super(key: key); + }); @override Widget build(BuildContext context) { - return AlertDialog( - title: Column( - children: [ - Icon( - Icons.route_rounded, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.dnsAddresses, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface + if (isDialog == true) { + return AlertDialog( + title: Column( + children: [ + Icon( + Icons.route_rounded, + color: Theme.of(context).listTileTheme.iconColor ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.dnsAddresses, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 500), + child: SingleChildScrollView( + child: Wrap( + children: dnsAddresses.map((address) => ListTile( + title: Text( + address, + style: TextStyle( + fontWeight: FontWeight.normal, + color: Theme.of(context).listTileTheme.textColor + ), + ), + )).toList(), + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close) ) ], - ), - content: SizedBox( - height: dnsAddresses.length*56 < 500 - ? dnsAddresses.length*56 : 500, - width: double.minPositive, - child: ListView( - children: dnsAddresses.map((address) => ListTile( - title: Text( - address, - style: TextStyle( - fontWeight: FontWeight.normal, - color: Theme.of(context).listTileTheme.textColor - ), - ), - )).toList(), - ), - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close) - ) - ], - ); + ); + } + else { + return ListBottomSheet( + icon: Icons.route_rounded, + title: AppLocalizations.of(context)!.dnsAddresses, + children: dnsAddresses.map((address) => CustomListTile( + title: address, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + )).toList(), + ); + } } } \ No newline at end of file diff --git a/lib/screens/settings/server_info/server_info.dart b/lib/screens/settings/server_info/server_info.dart index b15d8e0..85de4f6 100644 --- a/lib/screens/settings/server_info/server_info.dart +++ b/lib/screens/settings/server_info/server_info.dart @@ -86,12 +86,27 @@ class _ServerInformationState extends State { title: AppLocalizations.of(context)!.dnsAddresses, subtitle: AppLocalizations.of(context)!.seeDnsAddresses, onTap: () { - showModal( - context: context, - builder: (context) => DnsAddressesModal( - dnsAddresses: serverInfo.data!.dnsAddresses - ) - ); + if (width > 700) { + showDialog( + context: context, + builder: (context) => DnsAddressesModal( + dnsAddresses: serverInfo.data!.dnsAddresses, + isDialog: true, + ) + ); + } + else { + showModalBottomSheet( + context: context, + builder: (context) => DnsAddressesModal( + dnsAddresses: serverInfo.data!.dnsAddresses, + isDialog: false, + ), + isScrollControlled: true, + backgroundColor: Colors.transparent, + useSafeArea: true + ); + } }, ), CustomListTile( From e603814d42834ebeda1d7e3015674536ac3c99eb Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 21 Feb 2024 10:50:33 +0100 Subject: [PATCH 564/676] Removed unused imports --- lib/screens/settings/server_info/server_info.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/screens/settings/server_info/server_info.dart b/lib/screens/settings/server_info/server_info.dart index 85de4f6..9757497 100644 --- a/lib/screens/settings/server_info/server_info.dart +++ b/lib/screens/settings/server_info/server_info.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; From 693e66e125f0556918a8dbfd0ac0a0593f2579c6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 21 Feb 2024 13:14:36 +0100 Subject: [PATCH 565/676] Added loading indicator --- .../settings/update_server/update_screen.dart | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/screens/settings/update_server/update_screen.dart b/lib/screens/settings/update_server/update_screen.dart index 4dd4b52..aa85e7c 100644 --- a/lib/screens/settings/update_server/update_screen.dart +++ b/lib/screens/settings/update_server/update_screen.dart @@ -250,13 +250,20 @@ class _Header extends SliverPersistentHeaderDelegate { left: (constraints.maxWidth/2)-(_iconSize/2), child: Opacity( opacity: 1-iconPercentage, - child: Icon( - serversProvider.updateAvailable.data!.canAutoupdate == true - ? Icons.system_update_rounded - : Icons.system_security_update_good_rounded, - size: _iconSize, - color: Theme.of(context).colorScheme.primary, - ), + child: serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? const Column( + children: [ + CircularProgressIndicator(), + SizedBox(height: 4) + ], + ) + : Icon( + serversProvider.updateAvailable.data!.canAutoupdate == true + ? Icons.system_update_rounded + : Icons.system_security_update_good_rounded, + size: _iconSize, + color: Theme.of(context).colorScheme.primary, + ), ), ), Positioned( From f624fdbc43b61f36f9d94e153a0d1be774ab6f56 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 21 Feb 2024 13:16:37 +0100 Subject: [PATCH 566/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 94c5042..3ef7c66 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.16.2+132 +version: 2.16.3+133 environment: sdk: '>=2.18.1 <3.0.0' From 19ae91905f7bcbb3f9a2e97ce816f9ef2a497be6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 14:43:25 +0100 Subject: [PATCH 567/676] Added project specific vscode settings --- .vscode/settings.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9ad1ad1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "editor.formatOnSave": false, + "editor.defaultFormatter": "Dart-Code.flutter", + "dart.lineLength": 120, + "[dart]": { + "editor.rulers": [ + 120 + ], + "editor.defaultFormatter": "Dart-Code.dart-code", + "editor.formatOnSave": false, + } +} \ No newline at end of file From 8859468a660418160b791371a8f7391536187d16 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 14:44:00 +0100 Subject: [PATCH 568/676] Updated libraries --- pubspec.lock | 120 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 76 insertions(+), 44 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index c1c90ca..38751b2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -189,10 +189,10 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" file: dependency: transitive description: @@ -213,10 +213,10 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: b5e2b0f13d93f8c532b5a2786bfb44580de1f50b927bf95813fa1af617e9caf8 + sha256: "00b74ae680df6b1135bdbea00a7d1fc072a9180b7c3f3702e4b19a9943f5ed7d" url: "https://pub.dev" source: hosted - version: "0.66.1" + version: "0.66.2" flutter: dependency: "direct main" description: flutter @@ -311,10 +311,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "30088ce826b5b9cfbf9e8bece34c716c8a59fa54461dcae1e4ac01a94639e762" + sha256: a64c5323ac83ed2b7940d2b6288d160aa1753ff271ba9d9b2a86770414aa3eab url: "https://pub.dev" source: hosted - version: "0.6.18+3" + version: "0.6.20+1" flutter_native_splash: dependency: "direct dev" description: @@ -344,10 +344,10 @@ packages: dependency: "direct main" description: name: flutter_svg - sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" url: "https://pub.dev" source: hosted - version: "2.0.9" + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -386,10 +386,10 @@ packages: dependency: transitive description: name: image - sha256: "49a0d4b0c12402853d3f227fe7c315601b238d126aa4caa5dbb2dcf99421aa4a" + sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" url: "https://pub.dev" source: hosted - version: "4.1.6" + version: "4.1.7" intl: dependency: "direct main" description: @@ -414,6 +414,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: @@ -442,26 +466,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" nested: dependency: transitive description: @@ -490,10 +514,10 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_parsing: dependency: transitive description: @@ -578,10 +602,10 @@ packages: dependency: "direct main" description: name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.2" segmented_button_slide: dependency: "direct main" description: @@ -594,18 +618,18 @@ packages: dependency: transitive description: name: sentry - sha256: a7946f4a90b0feb47214981d881b98149e05f6c576da9f2a2f33945bf561de25 + sha256: d2ee9c850d876d285f22e2e662f400ec2438df9939fe4acd5d780df9841794ce url: "https://pub.dev" source: hosted - version: "7.16.0" + version: "7.16.1" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "6db7fa1b076faf2f5dd77d8cc9ef206171f32a290cc638842d78e5d62b441a27" + sha256: "5b428c189c825f16fb14e9166529043f06b965d5b59bfc3a1415e39c082398c0" url: "https://pub.dev" source: hosted - version: "7.16.0" + version: "7.16.1" shared_preferences: dependency: "direct main" description: @@ -711,10 +735,10 @@ packages: dependency: transitive description: name: sqlite3 - sha256: c4a4c5a4b2a32e2d0f6837b33d7c91a67903891a5b7dbe706cf4b1f6b0c798c5 + sha256: "072128763f1547e3e9b4735ce846bfd226d68019ccda54db4cd427b12dfdedc9" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.0" sqlite3_flutter_libs: dependency: "direct main" description: @@ -807,26 +831,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c + sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" + sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_linux: dependency: transitive description: @@ -847,10 +871,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" url_launcher_web: dependency: transitive description: @@ -879,26 +903,26 @@ packages: dependency: transitive description: name: vector_graphics - sha256: "4ac59808bbfca6da38c99f415ff2d3a5d7ca0a6b4809c71d9cf30fba5daf9752" + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" url: "https://pub.dev" source: hosted - version: "1.1.10+1" + version: "1.1.11+1" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: f3247e7ab0ec77dc759263e68394990edc608fb2b480b80db8aa86ed09279e33 + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da url: "https://pub.dev" source: hosted - version: "1.1.10+1" + version: "1.1.11+1" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "18489bdd8850de3dd7ca8a34e0c446f719ec63e2bab2e7a8cc66a9028dd76c5a" + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" url: "https://pub.dev" source: hosted - version: "1.1.10+1" + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -907,14 +931,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" web: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.4.2" win32: dependency: transitive description: @@ -965,5 +997,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" From 0821fd4e0e442565ed13fd8b66e877976195e7a5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 14:44:10 +0100 Subject: [PATCH 569/676] Fix duplicated snackbars logs --- lib/screens/logs/logs_list.dart | 354 +++++++++++++++-------------- lib/screens/settings/settings.dart | 4 +- 2 files changed, 181 insertions(+), 177 deletions(-) diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart index ced94ca..6036f77 100644 --- a/lib/screens/logs/logs_list.dart +++ b/lib/screens/logs/logs_list.dart @@ -33,6 +33,7 @@ class LogsListWidget extends StatefulWidget { } class _LogsListWidgetState extends State { + final _scaffoldMessengerKey = GlobalKey(); bool showDivider = true; void fetchFilteringRules() async { @@ -93,194 +94,197 @@ class _LogsListWidgetState extends State { Widget build(BuildContext context) { final logsProvider = Provider.of(context); - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: LogsListAppBar( - innerBoxIsScrolled: innerBoxIsScrolled, - showDivider: showDivider, + return ScaffoldMessenger( + key: widget.twoColumns ? _scaffoldMessengerKey : null, + child: Scaffold( + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: LogsListAppBar( + innerBoxIsScrolled: innerBoxIsScrolled, + showDivider: showDivider, + ) ) - ) - ], - body: Builder( - builder: (context) { - switch (logsProvider.loadStatus) { - case LoadStatus.loading: - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverFillRemaining( - child: SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingLogs, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), + ], + body: Builder( + builder: (context) { + switch (logsProvider.loadStatus) { + case LoadStatus.loading: + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverFillRemaining( + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingLogs, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) ) - ) - ], - ), - ) - ); - - case LoadStatus.loaded: - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => RefreshIndicator( - onRefresh: () async { - await logsProvider.fetchLogs(inOffset: 0); - }, - displacement: 95, - child: NotificationListener( - onNotification: scrollListener, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (logsProvider.logsData!.data.isNotEmpty) SliverList.builder( - itemCount: logsProvider.isLoadingMore - ? logsProvider.logsData!.data.length + 1 - : logsProvider.logsData!.data.length, - itemBuilder: (context, index) { - if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { - return const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - else if (logsProvider.logsData!.data[index].question.name != null) { - return LogTile( - log: logsProvider.logsData!.data[index], - index: index, - length: logsProvider.logsData!.data.length, - isLogSelected: widget.selectedLog != null && widget.selectedLog == logsProvider.logsData!.data[index], - onLogTap: (log) { - if (!widget.twoColumns) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false, + ], + ), + ) + ); + + case LoadStatus.loaded: + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => RefreshIndicator( + onRefresh: () async { + await logsProvider.fetchLogs(inOffset: 0); + }, + displacement: 95, + child: NotificationListener( + onNotification: scrollListener, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (logsProvider.logsData!.data.isNotEmpty) SliverList.builder( + itemCount: logsProvider.isLoadingMore + ? logsProvider.logsData!.data.length + 1 + : logsProvider.logsData!.data.length, + itemBuilder: (context, index) { + if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else if (logsProvider.logsData!.data[index].question.name != null) { + return LogTile( + log: logsProvider.logsData!.data[index], + index: index, + length: logsProvider.logsData!.data.length, + isLogSelected: widget.selectedLog != null && widget.selectedLog == logsProvider.logsData!.data[index], + onLogTap: (log) { + if (!widget.twoColumns) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + ) ) - ) - ); - } - widget.onLogSelected(log); - }, - twoColumns: widget.twoColumns, - ); + ); + } + widget.onLogSelected(log); + }, + twoColumns: widget.twoColumns, + ); + } + else { + return null; + } } - else { - return null; - } - } - ), - if (logsProvider.logsData!.data.isEmpty) SliverFillRemaining( - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - AppLocalizations.of(context)!.noLogsDisplay, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - if (logsProvider.logsOlderThan != null) Padding( - padding: const EdgeInsets.only( - top: 30, - left: 20, - right: 20 - ), - child: Text( - AppLocalizations.of(context)!.noLogsThatOld, - textAlign: TextAlign.center, + ), + if (logsProvider.logsData!.data.isEmpty) SliverFillRemaining( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context)!.noLogsDisplay, style: TextStyle( - fontSize: 16, + fontSize: 24, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), - ), - ] + if (logsProvider.logsOlderThan != null) Padding( + padding: const EdgeInsets.only( + top: 30, + left: 20, + right: 20 + ), + child: Text( + AppLocalizations.of(context)!.noLogsThatOld, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ] + ), ), - ), - ) - ], + ) + ], + ), ), ), - ), - ) - ); - - case LoadStatus.error: - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverFillRemaining( - child: SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.logsNotLoaded, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, + ) + ); + + case LoadStatus.error: + return SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverFillRemaining( + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, ), - ) - ], - ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.logsNotLoaded, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) ) - ) - ], - ), - ) - ); - - default: - return const SizedBox(); - } - }, - ) + ], + ), + ) + ); + + default: + return const SizedBox(); + } + }, + ) + ), ), ); } diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 718593e..bce5e11 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -83,7 +83,7 @@ class _SettingsWidget extends StatefulWidget { } class _SettingsWidgetState extends State<_SettingsWidget> { - final scaffoldMessengerKey = GlobalKey(); + final _scaffoldMessengerKey = GlobalKey(); @override void initState() { @@ -104,7 +104,7 @@ class _SettingsWidgetState extends State<_SettingsWidget> { } return ScaffoldMessenger( - key: widget.twoColumns ? scaffoldMessengerKey : null, + key: widget.twoColumns ? _scaffoldMessengerKey : null, child: Scaffold( body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ From 9de9b0afecd7664d19baedb982bedc7c6e8092a9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 14:49:30 +0100 Subject: [PATCH 570/676] Fixed statistics config updated text --- lib/l10n/app_en.arb | 2 ++ lib/l10n/app_es.arb | 2 ++ .../settings/statistics_settings/statistics_settings.dart | 8 ++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 439dac5..dc938f5 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -754,6 +754,8 @@ "statisticsSettingsDescription": "Configure data collection for statistics", "loadingStatisticsSettings": "Loading statistics settings...", "statisticsSettingsLoadError": "An error occured when loading statistics settings.", + "statisticsConfigUpdated": "Statistics settings updated successfully", + "statisticsConfigNotUpdated": "Statistics settings couldn't be updated", "customTimeInHours": "Custom time (in hours)", "invalidTime": "Invalid time", "removeDomain": "Remove domain", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 79aaa7d..040beb1 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -754,6 +754,8 @@ "statisticsSettingsDescription": "Configura la recolección de datos para estadísticas", "loadingStatisticsSettings": "Cargando ajustes de estadísticas...", "statisticsSettingsLoadError": "Ocurrió un error al cargar los ajustes de estadísticas.", + "statisticsConfigNotUpdated": "La configuración de estadísticas no pudo ser actualizada.", + "statisticsConfigUpdated": "Configuración de estadísticas actualizada correctamente.", "customTimeInHours": "Tiempo personalizado (en horas)", "invalidTime": "Tiempo no válido", "removeDomain": "Eliminar dominio", diff --git a/lib/screens/settings/statistics_settings/statistics_settings.dart b/lib/screens/settings/statistics_settings/statistics_settings.dart index f514e78..27e4570 100644 --- a/lib/screens/settings/statistics_settings/statistics_settings.dart +++ b/lib/screens/settings/statistics_settings/statistics_settings.dart @@ -145,19 +145,19 @@ class _StatisticsSettingsState extends State { processModal.close(); - if (!mounted) return; + if (!context.mounted) return; if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsConfigUpdated, + label: AppLocalizations.of(context)!.statisticsConfigUpdated, color: Colors.green ); } else { showSnacbkar( appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.logsConfigNotUpdated, + label: AppLocalizations.of(context)!.statisticsConfigNotUpdated, color: Colors.red ); } @@ -209,7 +209,7 @@ class _StatisticsSettingsState extends State { if (value != null && value != "custom") { _customTimeError = null; _customTimeController.text = ""; - }; + } _retentionTime = value; }), decoration: InputDecoration( From ba2a27fef04e2f0daf819e869ea4430a39d3f867 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 14:55:40 +0100 Subject: [PATCH 571/676] Fixed fallback dns regex --- lib/l10n/app_en.arb | 3 ++- lib/l10n/app_es.arb | 3 ++- lib/screens/settings/dns/fallback_dns.dart | 5 +++-- lib/screens/settings/dns/upstream_dns.dart | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index dc938f5..89d1fb5 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -778,5 +778,6 @@ "enablePlainDns": "Enable plain DNS", "enablePlainDnsDescription": "Plain DNS is enabled by default. You can disable it to force all devices to use encrypted DNS. To do this, you must enable at least one encrypted DNS protocol.", "date": "Date", - "loadingChangelog": "Loading changelog..." + "loadingChangelog": "Loading changelog...", + "invalidIpOrUrl": "Invalid IP address or URL" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 040beb1..32fb2c6 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -778,5 +778,6 @@ "enablePlainDns": "Activar DNS simple (sin cifrado)", "enablePlainDnsDescription": "El DNS simple (sin cifrado) está activado de forma predeterminada. Puedes desactivarlo para obligar a todos los dispositivos a utilizar DNS cifrado. Para ello, debes habilitar al menos un protocolo DNS cifrado.", "date": "Fecha", - "loadingChangelog": "Cargando registro de cambios..." + "loadingChangelog": "Cargando registro de cambios...", + "invalidIpOrUrl": "Dirección IP o URL no válida" } \ No newline at end of file diff --git a/lib/screens/settings/dns/fallback_dns.dart b/lib/screens/settings/dns/fallback_dns.dart index dcae0a2..916aa90 100644 --- a/lib/screens/settings/dns/fallback_dns.dart +++ b/lib/screens/settings/dns/fallback_dns.dart @@ -24,11 +24,12 @@ class _FallbackDnsScreenState extends State { void validateIp(Map field, String value) { RegExp ipAddress = RegExp(r'(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$)'); - if (ipAddress.hasMatch(value) == true) { + RegExp url = RegExp(r'(https?|tls):\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'); + if (ipAddress.hasMatch(value) == true || url.hasMatch(value) == true) { setState(() => field['error'] = null); } else { - setState(() => field['error'] = AppLocalizations.of(context)!.invalidIp); + setState(() => field['error'] = AppLocalizations.of(context)!.invalidIpOrUrl); } checkValidValues(); } diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index e540053..7f83fd8 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -263,7 +263,7 @@ class _UpstreamDnsScreenState extends State { const SizedBox(width: 4), ], ), - )).toList(), + )), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, From dac07edd893d95ef060ba9827c6b232e1c578e59 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 15:16:50 +0100 Subject: [PATCH 572/676] Changes vscode rules --- .vscode/settings.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9ad1ad1..791c93f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,7 @@ { "editor.formatOnSave": false, + "editor.formatOnPaste": false, + "editor.formatOnType": false, "editor.defaultFormatter": "Dart-Code.flutter", "dart.lineLength": 120, "[dart]": { @@ -8,5 +10,7 @@ ], "editor.defaultFormatter": "Dart-Code.dart-code", "editor.formatOnSave": false, + "editor.formatOnPaste": false, + "editor.formatOnType": false } } \ No newline at end of file From 133d29aa91ebe2d40d79b727cc842d9b3a53a75f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 15:17:11 +0100 Subject: [PATCH 573/676] Bump compileSdkVersion and targetSdkVersion android --- android/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 8ab520c..29785d0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -29,7 +29,7 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 33 + compileSdkVersion 34 ndkVersion flutter.ndkVersion compileOptions { @@ -51,7 +51,7 @@ android { // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. minSdkVersion 26 - targetSdkVersion 33 + targetSdkVersion 34 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } From 7c0b592715f4a292140eb902442a7ea0225eb33b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 15:17:27 +0100 Subject: [PATCH 574/676] Changed handling of comments fallback dns --- lib/screens/settings/dns/fallback_dns.dart | 95 +++++++++++++++++++--- lib/screens/settings/dns/upstream_dns.dart | 2 +- 2 files changed, 84 insertions(+), 13 deletions(-) diff --git a/lib/screens/settings/dns/fallback_dns.dart b/lib/screens/settings/dns/fallback_dns.dart index 916aa90..8c45af8 100644 --- a/lib/screens/settings/dns/fallback_dns.dart +++ b/lib/screens/settings/dns/fallback_dns.dart @@ -1,5 +1,6 @@ -// ignore_for_file: use_build_context_synchronously +import 'dart:io'; +import 'package:adguard_home_manager/screens/settings/dns/comment_modal.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -48,12 +49,20 @@ class _FallbackDnsScreenState extends State { final dnsProvider = Provider.of(context, listen: false); for (var item in dnsProvider.dnsInfo!.fallbackDns!) { - final controller = TextEditingController(); - controller.text = item; - fallbackControllers.add({ - 'controller': controller, - 'error': null - }); + if (item.contains("#")) { + fallbackControllers.add({ + 'comment': item + }); + } + else { + final controller = TextEditingController(); + controller.text = item; + fallbackControllers.add({ + 'controller': controller, + 'error': null, + 'isComment': item.contains("#") + }); + } } validValues = true; super.initState(); @@ -71,11 +80,16 @@ class _FallbackDnsScreenState extends State { processModal.open(AppLocalizations.of(context)!.savingConfig); final result = await dnsProvider.saveFallbackDnsConfig({ - "fallback_dns": fallbackControllers.map((e) => e['controller'].text).toList(), + "fallback_dns": fallbackControllers.map( + (e) => e['controller'] != null + ? e['controller'].text + : e['comment'] + ).toList(), }); processModal.close(); + if (!context.mounted) return; if (result.successful == true) { showSnacbkar( appConfigProvider: appConfigProvider, @@ -99,6 +113,37 @@ class _FallbackDnsScreenState extends State { } } + void openEditCommentModal(Map item, int position) { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => CommentModal( + comment: item['comment'], + onConfirm: (value) { + setState(() => fallbackControllers[position] = { 'comment': value }); + }, + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + useRootNavigator: true, + builder: (context) => CommentModal( + comment: item['comment'], + onConfirm: (value) { + setState(() => fallbackControllers[position] = { 'comment': value }); + }, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + isDismissible: true + ); + } + } + return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.fallbackDnsServers), @@ -168,29 +213,55 @@ class _FallbackDnsScreenState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded( + if (c['controller'] != null) Expanded( child: TextFormField( controller: c['controller'], onChanged: (value) => validateIp(c, value), decoration: InputDecoration( - prefixIcon: const Icon(Icons.dns_rounded), + prefixIcon: Icon( + c['isComment'] == true + ? Icons.comment_rounded + : Icons.dns_rounded + ), border: const OutlineInputBorder( borderRadius: BorderRadius.all( Radius.circular(10) ) ), errorText: c['error'], - labelText: AppLocalizations.of(context)!.dnsServer, + labelText: c['isComment'] == true + ? AppLocalizations.of(context)!.comment + : AppLocalizations.of(context)!.dnsServer, ) ), ), const SizedBox(width: 8), + if (c['comment'] != null) Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + c['comment'], + style: TextStyle( + fontSize: 16, + color: Theme.of(context).listTileTheme.iconColor + ), + ), + IconButton( + onPressed: () => openEditCommentModal(c, fallbackControllers.indexOf(c)), + icon: const Icon(Icons.edit), + tooltip: AppLocalizations.of(context)!.edit, + ) + ], + ), + ), IconButton( onPressed: () { setState(() => fallbackControllers = fallbackControllers.where((con) => con != c).toList()); checkValidValues(); }, - icon: const Icon(Icons.remove_circle_outline) + icon: const Icon(Icons.remove_circle_outline), + tooltip: AppLocalizations.of(context)!.remove, ) ], ), diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 7f83fd8..c99c9bc 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -47,7 +47,7 @@ class _UpstreamDnsScreenState extends State { final dnsProvider = Provider.of(context, listen: false); for (var item in dnsProvider.dnsInfo!.upstreamDns) { - if (item == '#') { + if (item.contains("#")) { dnsServers.add({ 'comment': item }); From 019367ca933513f8a643340456350341af6ed849 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 15:29:56 +0100 Subject: [PATCH 575/676] Fix hour mismatch home charts --- lib/screens/home/chart.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/home/chart.dart b/lib/screens/home/chart.dart index 0093ae8..ac1fce5 100644 --- a/lib/screens/home/chart.dart +++ b/lib/screens/home/chart.dart @@ -43,7 +43,7 @@ class _HomeChartState extends State { if (!(appConfigProvider.hideZeroValues == true && isEmpty == true)) { List dateTimes = []; - DateTime currentDate = DateTime.now().subtract(Duration(hours: widget.hoursInterval*widget.data.length+1)); + DateTime currentDate = DateTime.now().subtract(Duration(hours: widget.hoursInterval*widget.data.length)); for (var i = 0; i < widget.data.length; i++) { currentDate = currentDate.add(Duration(hours: widget.hoursInterval)); dateTimes.add(currentDate); From 654284b46ac4fc5acfaa1ef66637364f76b2ef96 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 15:33:26 +0100 Subject: [PATCH 576/676] Added add comment fallback dns --- lib/screens/settings/dns/fallback_dns.dart | 47 +++++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/screens/settings/dns/fallback_dns.dart b/lib/screens/settings/dns/fallback_dns.dart index 8c45af8..849eb4d 100644 --- a/lib/screens/settings/dns/fallback_dns.dart +++ b/lib/screens/settings/dns/fallback_dns.dart @@ -113,6 +113,44 @@ class _FallbackDnsScreenState extends State { } } + void openAddCommentModal() { + if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { + showDialog( + context: context, + builder: (context) => CommentModal( + onConfirm: (value) { + setState(() { + fallbackControllers.add({ + 'comment': value + }); + }); + }, + dialog: true, + ), + ); + } + else { + showModalBottomSheet( + context: context, + useRootNavigator: true, + builder: (context) => CommentModal( + onConfirm: (value) { + setState(() { + fallbackControllers.add({ + 'comment': value + }); + }); + }, + dialog: false, + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + isDismissible: true + ); + } + } + + void openEditCommentModal(Map item, int position) { if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { showDialog( @@ -267,9 +305,14 @@ class _FallbackDnsScreenState extends State { ), )), Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.min, children: [ + ElevatedButton.icon( + onPressed: openAddCommentModal, + icon: const Icon(Icons.add), + label: Text(AppLocalizations.of(context)!.comment) + ), ElevatedButton.icon( onPressed: () { setState(() => fallbackControllers.add({ @@ -279,7 +322,7 @@ class _FallbackDnsScreenState extends State { checkValidValues(); }, icon: const Icon(Icons.add), - label: Text(AppLocalizations.of(context)!.addItem) + label: Text(AppLocalizations.of(context)!.address) ), ], ), From 59a7a31a4f5339bd39c27e39e4103cf8dd0eec0b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 15:34:11 +0100 Subject: [PATCH 577/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 3ef7c66..70e1dff 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.16.3+133 +version: 2.16.4+134 environment: sdk: '>=2.18.1 <3.0.0' From a58b97a1bd1e1a8b3138f161270c1ea607263b43 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Feb 2024 15:44:49 +0100 Subject: [PATCH 578/676] Updated macos stuff --- macos/Podfile.lock | 16 ++++++++-------- macos/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index a257617..33a5a97 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -6,13 +6,13 @@ PODS: - FlutterMacOS (1.0.0) - package_info_plus (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.19.0): - - SentryPrivate (= 8.19.0) + - Sentry/HybridSDK (8.20.0): + - SentryPrivate (= 8.20.0) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.19.0) - - SentryPrivate (8.19.0) + - Sentry/HybridSDK (= 8.20.0) + - SentryPrivate (8.20.0) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS @@ -84,9 +84,9 @@ SPEC CHECKSUMS: dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - Sentry: 1ebcaef678a27c8ac515f974cb5425dd1bbdec2f - sentry_flutter: ecdfbedee55337205561cfa782ee02d31ec83e1f - SentryPrivate: 765c9b4ebe9ac1a5fcdc067c5a1cfbf3f10e1677 + Sentry: a8d7b373b9f9868442b02a0c425192f693103cbf + sentry_flutter: 03e7660857a8cdb236e71456a7e8447b65c8a788 + SentryPrivate: 006b24af16828441f70e2ab6adf241bd0a8ad130 shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: 73b7fc691fdc43277614250e04d183740cb15078 @@ -96,4 +96,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 -COCOAPODS: 1.14.3 +COCOAPODS: 1.15.2 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index cb14ee0..f7a463a 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -202,7 +202,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index b1bc689..6982a10 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Date: Thu, 29 Feb 2024 18:47:20 +0300 Subject: [PATCH 579/676] Update app_tr.arb --- lib/l10n/app_tr.arb | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 9e84991..42c0f33 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -75,7 +75,7 @@ "userNotEmpty": "Kullanıcı adı boÅŸ bırakılamaz", "passwordNotEmpty": "Åžifre boÅŸ bırakılamaz", "examplePath": "Örnek: /adguard", - "helperPath": "Ters proxy kullanıyorsanız", + "helperPath": "EÄŸer ters proxy kullanıyorsanız", "aboutApp": "Uygulama hakkında", "appVersion": "Uygulama sürümü", "createdBy": "GeliÅŸtirici", @@ -103,7 +103,7 @@ "logsCopiedClipboard": "Günlükler panoya kopyalandı", "advancedSettings": "GeliÅŸmiÅŸ ayarlar", "dontCheckCertificate": "SSL sertifikasını kontrol etme", - "dontCheckCertificateDescription": "Sunucunun SSL sertifikası doÄŸrulamasını geçersiz kılar", + "dontCheckCertificateDescription": "Sunucunun SSL sertifikası doÄŸrulamasını geçersiz kılar.", "advancedSetupDescription": "GeliÅŸmiÅŸ seçenekleri yönet", "settingsUpdatedSuccessfully": "Ayarlar baÅŸarıyla güncellendi.", "cannotUpdateSettings": "Ayarlar güncellenemiyor.", @@ -131,11 +131,11 @@ "rewrite": "Yeniden Yaz", "status": "Durum", "result": "Sonuç", - "time": "Zaman", + "time": "Saat", "blocklist": "Engelleme Listesi", "request": "İstek", "domain": "Alan adı", - "type": "Tip", + "type": "Tür", "clas": "Sınıf", "response": "Yanıt", "dnsServer": "DNS sunucusu", @@ -204,7 +204,7 @@ "noUpstreamServers": "Üst sunucu yok.", "willBeUsedGeneralServers": "Genel üst sunucular kullanılacak.", "added": "Eklenenler", - "clientUpdatedSuccessfully": "İstemci baÅŸarıyla güncellendi", + "clientUpdatedSuccessfully": "İstemci ayarları baÅŸarıyla güncellendi", "clientNotUpdated": "İstemci güncellenemedi", "clientDeletedSuccessfully": "İstemci baÅŸarıyla kaldırıldı", "clientNotDeleted": "İstemci silinemedi", @@ -308,8 +308,8 @@ "addImportant": "Başına $important ekle", "howCreateRules": "Özel kurallar nasıl oluÅŸturulur?", "examples": "Örnekler", - "example1": "example.org (ornek.org) ve tüm alt alan adlarına eriÅŸimi engeller.", - "example2": "example.org (ornek.org) ve tüm alt alan adlarına eriÅŸimi engellemeyi kaldırır.", + "example1": "example.org ve tüm alt alan adlarına eriÅŸimi engeller.", + "example2": "example.org ve tüm alt alan adlarına eriÅŸimi engellemeyi kaldırır.", "example3": "Yorum ekler.", "example4": "Belirtilen düzenli ifadeye uyan alan adlarına eriÅŸimi engeller.", "moreInformation": "Daha fazla bilgi", @@ -418,7 +418,7 @@ "logSettingsNotLoaded": "Günlük ayarları yüklenemedi.", "updatingSettings": "Ayarlar güncelleniyor...", "logsConfigUpdated": "Günlük ayarları baÅŸarıyla güncellendi", - "logsConfigNotUpdated": "Günlük ayarları baÅŸarıyla güncellendi", + "logsConfigNotUpdated": "Günlük ayarları güncellenemedi", "deletingLogs": "Günlükler temizleniyor...", "logsCleared": "Günlükler baÅŸarıyla temizlendi", "logsNotCleared": "Günlükler temizlenemedi", @@ -436,7 +436,7 @@ "parallelRequests": "Paralel istekler", "fastestIpAddress": "En hızlı IP adresi", "loadBalancingDescription": "Her seferinde bir üst sunucuya sorgu yapar. AdGuard Home, sunucuyu seçmek için ağırlıklı rastgele algoritmasını kullanır, böylece en hızlı sunucu daha sık kullanılır.", - "parallelRequestsDescription": "Tüm üst sunucuları aynı anda sorgulayarak çözümlemeyi hızlandırmak için paralel sorgular kullanır.", + "parallelRequestsDescription": "Tüm üst sunucuları aynı anda sorgulayarak çözümlemeyi hızlandırmak için paralel sorgular kullanılır.", "fastestIpAddressDescription": "Tüm DNS sunucularına sorgu yapın ve tüm yanıtlar arasında en hızlı IP adresini döndürür. Bu, AdGuard Home'un tüm DNS sunucularından yanıtları beklemesi gerektiÄŸi için DNS sorgularını yavaÅŸlatır, ancak genel baÄŸlantıyı iyileÅŸtirir.", "noBootstrapDns": "Önyükleme DNS sunucuları eklenmedi.", "bootstrapDnsServersInfo": "Önyükleme ​​DNS sunucuları, üst kaynaklarda belirttiÄŸiniz DoH/DoT çözümleyicilerinin IP adreslerini çözmek için kullanılır.", @@ -469,7 +469,7 @@ "customIpDescription": "Manuel olarak ayarlanmış bir IP adresi ile yanıt verir.", "dnsCacheConfig": "DNS önbellek yapılandırması", "cacheSize": "Önbellek boyutu", - "inBytes": "Alınacak önbelleÄŸin boyutunu ayarla (bayt olarak)", + "inBytes": "Alınacak önbelleÄŸin boyutunu ayarla (Bayt olarak)", "overrideMinimumTtl": "Minimum kullanım süresini geçersiz kıl", "overrideMinimumTtlDescription": "DNS yanıtlarını önbelleÄŸe alırken üst sunucudan alınan minimum kullanım süresi deÄŸerini (TTL) saniye olarak ayarlayın.", "overrideMaximumTtl": "Maksimum kullanım süresini geçersiz kıl", @@ -494,7 +494,7 @@ "dnsCacheConfigDescription": "Sunucunun DNS önbelleÄŸini nasıl yöneteceÄŸini yapılandır", "comment": "Yorum", "address": "Adres", - "commentsDescription": "Yorumlar her zaman # iÅŸareti ile baÅŸlar. Onu eklemenize gerek yok, otomatik olarak eklenir.", + "commentsDescription": "Yorumlar her zaman # iÅŸareti ile baÅŸlar. Eklemenize gerek yok, otomatik olarak eklenecektir.", "encryptionSettings": "Åžifreleme ayarları", "encryptionSettingsDescription": "Åžifreleme (HTTPS/QUIC/TLS) desteÄŸi", "loadingEncryptionSettings": "Åžifreleme ayarları yükleniyor...", @@ -560,8 +560,8 @@ "validPrivateKey": "Geçerli özel anahtar", "expirationDate": "Son kullanma tarihi", "keysNotMatch": "Geçersiz bir sertifika veya anahtar: tls: özel anahtar genel anahtarla eÅŸleÅŸmiyor.", - "timeLogs": "Günlüklerde iÅŸlem süresi göster", - "timeLogsDescription": "Günlükler listesinde zaman yerine iÅŸlem süresini göster.", + "timeLogs": "Günlüklerde iÅŸlem süresini göster", + "timeLogsDescription": "Günlükler listesinde zaman yerine iÅŸlem süresini gösterir.", "hostNames": "Ana bilgisayar adları", "keyType": "Anahtar türü", "updateAvailable": "Güncelleme mevcut", @@ -626,7 +626,7 @@ "appUpdates": "Uygulama güncellemeleri", "usingLatestVersion": "En son sürümü kullanıyorsunuz", "ipLogs": "Günlüklerde IP adresini göster", - "ipLogsDescription": "Günlükler listesinde istemci adı yerine IP adresini göster.", + "ipLogsDescription": "Günlükler listesinde istemci adı yerine IP adresini gösterir.", "application": "Uygulama", "combinedChart": "BirleÅŸtirilmiÅŸ grafik", "combinedChartDescription": "Tüm grafikleri bir araya getirir.", @@ -688,7 +688,7 @@ "yourVersion": "Yüklü sürüm: {version}", "minimumRequiredVersion": "Gerekli minimum sürüm: {version}", "topUpstreams": "Öne çıkan DNS sunucuları", - "averageUpstreamResponseTime": "DNS sunucusu ortalama iÅŸlem süresi" , + "averageUpstreamResponseTime": "DNS sunucuları iÅŸlem süresi" , "dhcpNotAvailable": "DHCP sunucusu kullanılamıyor.", "osServerInstalledIncompatible": "AdGuard Home, iÅŸletim sisteminizde DHCP sunucusu çalıştıramıyor.", "resetSettings": "Ayarları sıfırla", @@ -721,7 +721,7 @@ "unblockingClient": "İstemci engeli kaldırılıyor...", "upstreamDnsCacheConfiguration": "DNS önbellek yapılandırması", "enableDnsCachingClient": "Bu istemci için DNS önbelleÄŸe almayı etkinleÅŸtir", - "dnsCacheSize": "DNS önbellek boyutu (bayt cinsinden)", + "dnsCacheSize": "DNS önbellek boyutu (Bayt cinsinden)", "nameInvalid": "Ad gereklidir", "oneIdentifierRequired": "En az bir tanımlayıcı gereklidir", "dnsCacheNumber": "DNS önbellek boyutu bir rakam içermelidir", @@ -754,7 +754,9 @@ "statisticsSettingsDescription": "İstatistikler için veri toplamayı yapılandır", "loadingStatisticsSettings": "İstatistik ayarları yükleniyor...", "statisticsSettingsLoadError": "İstatistik ayarları yüklenirken bir hata oluÅŸtu.", - "customTimeInHours": "Özel zaman (saat olarak)", + "statisticsConfigUpdated": "İstatistik ayarları baÅŸarıyla güncellendi", + "statisticsConfigNotUpdated": "İstatistik ayarları güncellenemedi", + "customTimeInHours": "Özel zaman (Saat olarak)", "invalidTime": "Geçersiz zaman", "removeDomain": "Alan adını kaldır", "addDomain": "Alan adı ekle", @@ -774,5 +776,8 @@ "showHide": "Göster/gizle", "noElementsReorderMessage": "Burada yeniden sıralamak için göster/gizle sekmesindeki bazı öğeleri etkinleÅŸtirin.", "enablePlainDns": "Düz DNS'i etkinleÅŸtir", - "enablePlainDnsDescription": "Düz DNS varsayılan olarak etkindir. Tüm aygıtları ÅŸifrelenmiÅŸ DNS kullanmaya zorlamak için bunu devre dışı bırakabilirsiniz. Bunu yapmak için en az bir ÅŸifrelenmiÅŸ DNS protokolünü etkinleÅŸtirmeniz gerekir." + "enablePlainDnsDescription": "Düz DNS varsayılan olarak etkindir. Tüm aygıtları ÅŸifrelenmiÅŸ DNS kullanmaya zorlamak için bunu devre dışı bırakabilirsiniz. Bunu yapmak için en az bir ÅŸifrelenmiÅŸ DNS protokolünü etkinleÅŸtirmeniz gerekir.", + "date": "Tarih", + "loadingChangelog": "DeÄŸiÅŸiklikler yükleniyor...", + "invalidIpOrUrl": "Geçersiz IP adresi veya URL" } \ No newline at end of file From ad6cb92d4bebc0b193b0a5161a2a6aa940f7e4c5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 13:44:07 +0100 Subject: [PATCH 580/676] Add persistent client logs --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/screens/clients/client/client_screen.dart | 21 +++++++- .../client/client_screen_functions.dart | 2 + lib/screens/clients/fab.dart | 2 +- lib/screens/logs/log_tile.dart | 48 +++++++++++++++++++ 6 files changed, 75 insertions(+), 4 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 89d1fb5..17b3cc7 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -779,5 +779,6 @@ "enablePlainDnsDescription": "Plain DNS is enabled by default. You can disable it to force all devices to use encrypted DNS. To do this, you must enable at least one encrypted DNS protocol.", "date": "Date", "loadingChangelog": "Loading changelog...", - "invalidIpOrUrl": "Invalid IP address or URL" + "invalidIpOrUrl": "Invalid IP address or URL", + "addPersistentClient": "Add as a persistent client" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 32fb2c6..cd63b77 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -779,5 +779,6 @@ "enablePlainDnsDescription": "El DNS simple (sin cifrado) está activado de forma predeterminada. Puedes desactivarlo para obligar a todos los dispositivos a utilizar DNS cifrado. Para ello, debes habilitar al menos un protocolo DNS cifrado.", "date": "Fecha", "loadingChangelog": "Cargando registro de cambios...", - "invalidIpOrUrl": "Dirección IP o URL no válida" + "invalidIpOrUrl": "Dirección IP o URL no válida", + "addPersistentClient": "Añadir como cliente persistente" } \ 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 225b5eb..64bde26 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -10,6 +10,16 @@ import 'package:adguard_home_manager/models/safe_search.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; +class ClientInitialData { + final String name; + final String ip; + + const ClientInitialData({ + required this.name, + required this.ip, + }); +} + class ControllerListItem { final String id; final TextEditingController controller; @@ -25,13 +35,15 @@ class ClientScreen extends StatefulWidget { final void Function(Client) onConfirm; final void Function(Client)? onDelete; final bool fullScreen; + final ClientInitialData? initialData; const ClientScreen({ super.key, this.client, required this.onConfirm, this.onDelete, - required this.fullScreen + required this.fullScreen, + this.initialData, }); @override @@ -146,6 +158,13 @@ class _ClientScreenState extends State { _blockedServicesSchedule = widget.client!.blockedServicesSchedule!; } } + if (widget.initialData != null) { + nameController.text = widget.initialData!.name; + identifiersControllers[0] = ControllerListItem( + id: uuid.v4(), + controller: TextEditingController(text: widget.initialData!.ip) + ); + } super.initState(); } diff --git a/lib/screens/clients/client/client_screen_functions.dart b/lib/screens/clients/client/client_screen_functions.dart index f0338a1..2c176c4 100644 --- a/lib/screens/clients/client/client_screen_functions.dart +++ b/lib/screens/clients/client/client_screen_functions.dart @@ -80,6 +80,7 @@ void openClientFormModal({ Client? client, required void Function(Client) onConfirm, void Function(Client)? onDelete, + ClientInitialData? initialData, }) { showGeneralDialog( context: context, @@ -105,6 +106,7 @@ void openClientFormModal({ client: client, onConfirm: onConfirm, onDelete: onDelete, + initialData: initialData, ), ); } diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 64fd098..a46b89a 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -14,7 +14,7 @@ import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class ClientsFab extends StatelessWidget { - const ClientsFab({Key? key}) : super(key: key); + const ClientsFab({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index f5db5ee..5f3a834 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -4,12 +4,16 @@ 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/client_screen_functions.dart'; +import 'package:adguard_home_manager/screens/clients/client/client_screen.dart'; import 'package:adguard_home_manager/widgets/options_menu.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; +import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; @@ -40,6 +44,7 @@ class LogTile extends StatelessWidget { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); final statusProvider = Provider.of(context); + final clientsProvider = Provider.of(context); Widget logStatusWidget({ required IconData icon, @@ -118,6 +123,39 @@ class LogTile extends StatelessWidget { } } + void confirmAddClient(Client client) async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.addingClient); + + final result = await clientsProvider.addClient(client); + + processModal.close(); + + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientAddedSuccessfully, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientNotAdded, + color: Colors.red + ); + } + } + + void openAddClient() { + openClientFormModal( + context: context, + width: MediaQuery.of(context).size.width, + onConfirm: confirmAddClient, + initialData: ClientInitialData(name: "Client ${log.client}", ip: log.client) + ); + } + final domainBlocked = isDomainBlocked(log.reason); if (twoColumns && !(useAlwaysNormalTile == true)) { @@ -141,6 +179,11 @@ class LogTile extends StatelessWidget { newStatus: domainBlocked == true ? 'unblock' : 'block' ) ), + if (log.clientInfo?.name == "") MenuOption( + title: AppLocalizations.of(context)!.addPersistentClient, + icon: Icons.add_rounded, + action: openAddClient + ), if (log.question.name != null) MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, @@ -319,6 +362,11 @@ class LogTile extends StatelessWidget { newStatus: domainBlocked == true ? 'unblock' : 'block' ) ), + if (log.clientInfo?.name == "") MenuOption( + title: AppLocalizations.of(context)!.addPersistentClient, + icon: Icons.add_rounded, + action: openAddClient + ), if (log.question.name != null) MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, From ce8d38958ec58d619e90298a29c32f4ceb149f48 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 13:57:15 +0100 Subject: [PATCH 581/676] Fix desktop and sliver app bar add client --- lib/screens/clients/client/client_screen.dart | 147 ++++++++++-------- lib/screens/logs/log_tile.dart | 13 +- 2 files changed, 91 insertions(+), 69 deletions(-) diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index 64bde26..05d53a0 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -235,71 +235,90 @@ class _ClientScreenState extends State { if (widget.fullScreen == true) { - return Dialog.fullscreen( - child: Scaffold( - appBar: AppBar( - leading: IconButton( - onPressed: () => Navigator.pop(context), - icon: const Icon(Icons.close) - ), - title: Text( - widget.client != null - ? AppLocalizations.of(context)!.client - : AppLocalizations.of(context)!.addClient - ), - actions: actions(), - ), + return Material( + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + leading: IconButton( + onPressed: () => Navigator.pop(context), + icon: const Icon(Icons.close) + ), + title: Text( + widget.client != null + ? AppLocalizations.of(context)!.client + : AppLocalizations.of(context)!.addClient + ), + actions: actions(), + ) + ) + ], body: SafeArea( - child: ListView( - controller: _scrollController, - children: [ - if (!_nameValid || !_identifiersValid || !_dnsCacheValid) _Errors( - nameValid: _nameValid, - identifiersValid: _identifiersValid, - dnsCacheValid: _dnsCacheValid - ), - ClientForm( - isFullScreen: true, - client: widget.client, - nameController: nameController, - 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), - ignoreClientQueryLog: _ignoreClientQueryLog, - ignoreClientStatistics: _ignoreClientStatistics, - updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v), - updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v), - enableDnsCache: _enableDnsCache, - updateEnableDnsCache: (v) => setState(() => _enableDnsCache = v), - dnsCacheField: _dnsCacheField, - dnsCacheError: _dnsCacheError, - updateDnsCacheError: (v) => setState(() => _dnsCacheError = v), - blockedServicesSchedule: _blockedServicesSchedule, - setBlockedServicesSchedule: (v) => setState(() => _blockedServicesSchedule = v), - ), - ], - ), - ), + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + if (!_nameValid || !_identifiersValid || !_dnsCacheValid) _Errors( + nameValid: _nameValid, + identifiersValid: _identifiersValid, + dnsCacheValid: _dnsCacheValid + ), + ClientForm( + isFullScreen: true, + client: widget.client, + nameController: nameController, + 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), + ignoreClientQueryLog: _ignoreClientQueryLog, + ignoreClientStatistics: _ignoreClientStatistics, + updateIgnoreClientQueryLog: (v) => setState(() => _ignoreClientQueryLog = v), + updateIgnoreClientStatistics: (v) => setState(() => _ignoreClientStatistics = v), + enableDnsCache: _enableDnsCache, + updateEnableDnsCache: (v) => setState(() => _enableDnsCache = v), + dnsCacheField: _dnsCacheField, + dnsCacheError: _dnsCacheError, + updateDnsCacheError: (v) => setState(() => _dnsCacheError = v), + blockedServicesSchedule: _blockedServicesSchedule, + setBlockedServicesSchedule: (v) => setState(() => _blockedServicesSchedule = v), + ), + ], + ) + ], + ), + ) + ) ), ); } diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 5f3a834..c59aa64 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -148,11 +148,14 @@ class LogTile extends StatelessWidget { } void openAddClient() { - openClientFormModal( - context: context, - width: MediaQuery.of(context).size.width, - onConfirm: confirmAddClient, - initialData: ClientInitialData(name: "Client ${log.client}", ip: log.client) + Future.delayed( + const Duration(milliseconds: 0), + () => openClientFormModal( + context: context, + width: MediaQuery.of(context).size.width, + onConfirm: confirmAddClient, + initialData: ClientInitialData(name: "Client ${log.client}", ip: log.client) + ) ); } From d65ea6520c9e2d1707833dc936df595a02eb9137 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 14:14:49 +0100 Subject: [PATCH 582/676] Added sliver app bar client logs --- lib/screens/clients/client/client_screen.dart | 2 +- .../clients/client/logs_list_client.dart | 283 ++++++++++-------- 2 files changed, 157 insertions(+), 128 deletions(-) diff --git a/lib/screens/clients/client/client_screen.dart b/lib/screens/clients/client/client_screen.dart index 05d53a0..573e6cf 100644 --- a/lib/screens/clients/client/client_screen.dart +++ b/lib/screens/clients/client/client_screen.dart @@ -260,7 +260,7 @@ class _ClientScreenState extends State { ], body: SafeArea( top: false, - bottom: true, + bottom: false, child: Builder( builder: (context) => CustomScrollView( slivers: [ diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index 3267128..2d76396 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -131,146 +131,175 @@ class _LogsListClientState extends State { setState(() => previousIp = widget.ip); } - return Scaffold( - appBar: AppBar( - title: Text(widget.name != null && widget.name != '' ? widget.name! : widget.ip), - centerTitle: true, - surfaceTintColor: isDesktop(MediaQuery.of(context).size.width) - ? Colors.transparent - : null, - actions: [ - if (!(Platform.isAndroid || Platform.isIOS)) ...[ - IconButton( - onPressed: fetchLogs, - icon: const Icon(Icons.refresh_rounded), - tooltip: AppLocalizations.of(context)!.refresh, - ), - const SizedBox(width: 8) - ] - ], - ), - body: SafeArea( - child: Builder( - builder: (context) { - switch (loadStatus) { - case 0: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingLogs, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], + return Material( + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + title: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.client, + style: const TextStyle( + fontSize: 24 + ), + ), + const SizedBox(height: 4), + Text( + widget.name != null && widget.name != '' ? widget.name! : widget.ip, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.secondary + ), + ) + ], + ), + ), + surfaceTintColor: isDesktop(MediaQuery.of(context).size.width) + ? Colors.transparent + : null, + actions: [ + if (!(Platform.isAndroid || Platform.isIOS)) ...[ + IconButton( + onPressed: fetchLogs, + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, ), - ); - - case 1: - if (logsData!.data.isNotEmpty) { - return RefreshIndicator( - onRefresh: fetchLogs, - child: ListView.builder( - controller: scrollController, - padding: const EdgeInsets.only(top: 0), - itemCount: isLoadingMore == true - ? logsData!.data.length+1 - : logsData!.data.length, - itemBuilder: (context, index) { - if (isLoadingMore == true && index == logsData!.data.length) { - return const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: Center( - child: CircularProgressIndicator(), + const SizedBox(width: 8) + ] + ], + ) + ) + ], + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => RefreshIndicator( + onRefresh: fetchLogs, + displacement: 95, + child: CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (loadStatus == 0) SliverFillRemaining( + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingLogs, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ); - } - else { - return LogTile( - log: logsData!.data[index], - index: index, - length: logsData!.data.length, - useAlwaysNormalTile: true, - onLogTap: (log) => { - if (width > 700) { - showDialog( - context: context, + ) + ], + ), + ) + ), + if (loadStatus == 1 && logsData!.data.isNotEmpty) SliverList.builder( + itemCount: isLoadingMore == true + ? logsData!.data.length+1 + : logsData!.data.length, + itemBuilder: (context, index) { + if (isLoadingMore == true && index == logsData!.data.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + else { + return LogTile( + log: logsData!.data[index], + index: index, + length: logsData!.data.length, + useAlwaysNormalTile: true, + onLogTap: (log) => { + if (width > 700) { + showDialog( + context: context, + builder: (context) => LogDetailsScreen( + log: log, + dialog: true + ) + ) + } + else { + Navigator.of(context).push( + MaterialPageRoute( builder: (context) => LogDetailsScreen( log: log, - dialog: true + dialog: false ) ) - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false - ) - ) - ) - } - }, - twoColumns: widget.splitView, - ); - } + ) + } + }, + twoColumns: widget.splitView, + ); } - ), - ); - } - else { - return Center( - child: Text( - AppLocalizations.of(context)!.noLogsDisplay, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ); - } - - case 2: - return SizedBox( - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.logsNotLoaded, + } + ), + if (loadStatus == 1 && logsData!.data.isEmpty) SliverFillRemaining( + child: Center( + child: Text( + AppLocalizations.of(context)!.noLogsDisplay, textAlign: TextAlign.center, style: TextStyle( fontSize: 22, color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ) - ], + ), + ), ), - ); - - default: - return const SizedBox(); - } - }, - ), - ) + if (loadStatus == 2) SliverFillRemaining( + child: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.logsNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + ) + ], + ), + ), + ) + ) + ), ); } } \ No newline at end of file From 31ad3fcf6aab5c83384b60c710675c12f88b1b34 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 14:40:02 +0100 Subject: [PATCH 583/676] Fixed logs search bar --- lib/screens/logs/logs_list_appbar.dart | 157 ++++++++++++++----------- 1 file changed, 86 insertions(+), 71 deletions(-) diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 9b5ab3b..341593a 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -8,11 +8,14 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/filters/logs_filters_modal.dart'; +import 'package:adguard_home_manager/config/globals.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; +final GlobalKey _searchButtonKey = GlobalKey(); + class LogsListAppBar extends StatelessWidget { final bool innerBoxIsScrolled; final bool showDivider; @@ -52,6 +55,25 @@ class LogsListAppBar extends StatelessWidget { } } + void showSearchDialog() { + showDialog( + context: context, + builder: (context) => _Search( + searchButtonRenderBox: _searchButtonKey.currentContext!.findRenderObject() as RenderBox, + onSearch: (v) { + logsProvider.setAppliedFilters( + AppliedFiters( + selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, + searchText: v != "" ? v : null, + clients: logsProvider.appliedFilters.clients + ) + ); + logsProvider.filterLogs(); + }, + ), + ); + } + final Map translatedString = { "all": AppLocalizations.of(context)!.all, "filtered": AppLocalizations.of(context)!.filtered, @@ -77,22 +99,8 @@ class LogsListAppBar extends StatelessWidget { tooltip: AppLocalizations.of(context)!.refresh, ), if (logsProvider.loadStatus == LoadStatus.loaded) IconButton( - onPressed: () => showDialog( - context: context, - builder: (context) => _Search( - hasTopBar: MediaQuery.of(context).viewPadding.top > 0, - onSearch: (v) { - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: v != "" ? v : null, - clients: logsProvider.appliedFilters.clients - ) - ); - logsProvider.filterLogs(); - }, - ), - ), + key: _searchButtonKey, + onPressed: showSearchDialog, icon: const Icon(Icons.search_rounded), tooltip: AppLocalizations.of(context)!.search, ), @@ -235,11 +243,11 @@ class LogsListAppBar extends StatelessWidget { class _Search extends StatefulWidget { final void Function(String) onSearch; - final bool hasTopBar; + final RenderBox searchButtonRenderBox; const _Search({ required this.onSearch, - required this.hasTopBar, + required this.searchButtonRenderBox, }); @override @@ -261,67 +269,74 @@ class _SearchState extends State<_Search> { Widget build(BuildContext context) { final logsProvider = Provider.of(context); + final Offset position = widget.searchButtonRenderBox.localToGlobal(Offset.zero); + return GestureDetector( onTap: () => Navigator.pop(context), child: Material( color: Colors.transparent, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - GestureDetector( - onTap: () => {}, - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 500), - child: Container( - margin: widget.hasTopBar - ? const EdgeInsets.symmetric(horizontal: 16) - : const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(16) - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - child: TextFormField( - controller: _searchController, - onChanged: (v) { - if (v == "") { - logsProvider.setSearchText(null); - return; - } - logsProvider.setSearchText(v); - }, - onFieldSubmitted: (v) { - widget.onSearch(v); - Navigator.pop(context); - }, - autofocus: true, - decoration: InputDecoration( - hintText: AppLocalizations.of(context)!.search, - prefixIcon: const Icon(Icons.search_rounded), - border: InputBorder.none, - filled: true, - fillColor: Colors.grey.withOpacity(0.2), - suffixIcon: _searchController.text != "" - ? IconButton( - onPressed: () { - _searchController.text = ""; + child: LayoutBuilder( + builder: (context, constraints) { + final double width = constraints.maxWidth - 32 > 500 ? 500 : constraints.maxWidth - 32; + return Stack( + alignment: Alignment.topCenter, + children: [ + Positioned( + top: position.dy - MediaQuery.of(globalNavigatorKey.currentContext!).viewPadding.top, + child: SizedBox( + width: width, + child: GestureDetector( + onTap: () => {}, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(16) + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: TextFormField( + controller: _searchController, + onChanged: (v) { + if (v == "") { logsProvider.setSearchText(null); - }, - icon: const Icon( - Icons.close_rounded, - size: 20, - ), - tooltip: AppLocalizations.of(context)!.clearSearch, - ) - : null + return; + } + logsProvider.setSearchText(v); + }, + onFieldSubmitted: (v) { + widget.onSearch(v); + Navigator.pop(context); + }, + autofocus: true, + decoration: InputDecoration( + hintText: AppLocalizations.of(context)!.search, + prefixIcon: const Icon(Icons.search_rounded), + border: InputBorder.none, + filled: true, + fillColor: Colors.grey.withOpacity(0.2), + suffixIcon: _searchController.text != "" + ? IconButton( + onPressed: () { + _searchController.text = ""; + logsProvider.setSearchText(null); + }, + icon: const Icon( + Icons.close_rounded, + size: 20, + ), + tooltip: AppLocalizations.of(context)!.clearSearch, + ) + : null + ), + ), + ), ), ), ), - ), - ), - ) - ], + ) + ], + ); + } ), ), ); From 806e74ca9fa29a8731ce5bbdebbfbd94c95ce170 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 20:07:24 +0100 Subject: [PATCH 584/676] Added block unblock domain for a client --- lib/l10n/app_en.arb | 6 +++- lib/l10n/app_es.arb | 6 +++- lib/screens/logs/log_tile.dart | 51 ++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 17b3cc7..cd626ac 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -780,5 +780,9 @@ "date": "Date", "loadingChangelog": "Loading changelog...", "invalidIpOrUrl": "Invalid IP address or URL", - "addPersistentClient": "Add as a persistent client" + "addPersistentClient": "Add as a persistent client", + "blockThisClientOnly": "Block for this client only", + "unblockThisClientOnly": "Unblock for this client only", + "domainBlockedThisClient": "{domain} blocked for this client", + "domainUnblockedThisClient": "{domain} unblocked for this client" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index cd63b77..1faf2c7 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -780,5 +780,9 @@ "date": "Fecha", "loadingChangelog": "Cargando registro de cambios...", "invalidIpOrUrl": "Dirección IP o URL no válida", - "addPersistentClient": "Añadir como cliente persistente" + "addPersistentClient": "Añadir como cliente persistente", + "blockThisClientOnly": "Bloquear sólo para este cliente", + "unblockThisClientOnly": "Desbloquear sólo para este cliente", + "domainBlockedThisClient": "{domain} bloqueado para este cliente", + "domainUnblockedThisClient": "{domain} desbloqueado para este cliente" } \ No newline at end of file diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index c59aa64..bd44f95 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -9,6 +9,7 @@ import 'package:adguard_home_manager/screens/clients/client/client_screen.dart'; import 'package:adguard_home_manager/widgets/options_menu.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; @@ -45,6 +46,7 @@ class LogTile extends StatelessWidget { final appConfigProvider = Provider.of(context); final statusProvider = Provider.of(context); final clientsProvider = Provider.of(context); + final filteringProvider = Provider.of(context); Widget logStatusWidget({ required IconData icon, @@ -147,6 +149,37 @@ class LogTile extends StatelessWidget { } } + void blockUnblockRuleClient() async { + ProcessModal processModal = ProcessModal(); + processModal.open(AppLocalizations.of(context)!.addingRule); + + final rule = isDomainBlocked(log.reason) == true + ? "@@||${log.question.name}^\$client='${log.client}'" + : "||${log.question.name}^\$client='${log.client}'"; + + final result = await filteringProvider.addCustomRule(rule); + + processModal.close(); + + if (!context.mounted) return; + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: isDomainBlocked(log.reason) == true + ? AppLocalizations.of(context)!.domainUnblockedThisClient(log.question.name!) + : AppLocalizations.of(context)!.domainBlockedThisClient(log.question.name!), + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.ruleNotAdded, + color: Colors.red + ); + } + } + void openAddClient() { Future.delayed( const Duration(milliseconds: 0), @@ -182,6 +215,15 @@ class LogTile extends StatelessWidget { newStatus: domainBlocked == true ? 'unblock' : 'block' ) ), + MenuOption( + title: domainBlocked == true + ? AppLocalizations.of(context)!.unblockThisClientOnly + : AppLocalizations.of(context)!.blockThisClientOnly, + icon: domainBlocked == true + ? Icons.check_rounded + : Icons.block_rounded, + action: blockUnblockRuleClient + ), if (log.clientInfo?.name == "") MenuOption( title: AppLocalizations.of(context)!.addPersistentClient, icon: Icons.add_rounded, @@ -365,6 +407,15 @@ class LogTile extends StatelessWidget { newStatus: domainBlocked == true ? 'unblock' : 'block' ) ), + MenuOption( + title: domainBlocked == true + ? AppLocalizations.of(context)!.unblockThisClientOnly + : AppLocalizations.of(context)!.blockThisClientOnly, + icon: domainBlocked == true + ? Icons.check_rounded + : Icons.block_rounded, + action: blockUnblockRuleClient + ), if (log.clientInfo?.name == "") MenuOption( title: AppLocalizations.of(context)!.addPersistentClient, icon: Icons.add_rounded, From 5fdeaa80b7bba075bc2b77c168e2208bdea1ea88 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 20:33:14 +0100 Subject: [PATCH 585/676] Added option to allow and disallow client --- lib/l10n/app_en.arb | 9 +++++- lib/l10n/app_es.arb | 9 +++++- lib/screens/logs/log_tile.dart | 59 ++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index cd626ac..93b08af 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -784,5 +784,12 @@ "blockThisClientOnly": "Block for this client only", "unblockThisClientOnly": "Unblock for this client only", "domainBlockedThisClient": "{domain} blocked for this client", - "domainUnblockedThisClient": "{domain} unblocked for this client" + "domainUnblockedThisClient": "{domain} unblocked for this client", + "disallowThisClient": "Disallow this client", + "allowThisClient": "Allow this client", + "clientAllowedSuccessfully": "Client allowed successfully", + "clientDisallowedSuccessfully": "Client disallowed successfully", + "changesNotSaved": "Changes could not be saved", + "allowingClient": "Allowing client...", + "disallowingClient": "Disallowing client..." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 1faf2c7..e777f48 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -784,5 +784,12 @@ "blockThisClientOnly": "Bloquear sólo para este cliente", "unblockThisClientOnly": "Desbloquear sólo para este cliente", "domainBlockedThisClient": "{domain} bloqueado para este cliente", - "domainUnblockedThisClient": "{domain} desbloqueado para este cliente" + "domainUnblockedThisClient": "{domain} desbloqueado para este cliente", + "disallowThisClient": "No permitir este cliente", + "allowThisClient": "Permitir este cliente", + "clientAllowedSuccessfully": "Cliente permitido correctamente", + "clientDisallowedSuccessfully": "Cliente no permitido correctamente", + "changesNotSaved": "Los cambios no han podido ser guardados", + "allowingClient": "Permitiendo cliente...", + "disallowingClient": "No permitiendo cliente..." } \ No newline at end of file diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index bd44f95..f077c31 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -180,6 +180,47 @@ class LogTile extends StatelessWidget { } } + void allowDisallowClient() async { + ProcessModal processModal = ProcessModal(); + processModal.open( + log.clientInfo!.disallowed == true + ? AppLocalizations.of(context)!.allowingClient + : AppLocalizations.of(context)!.disallowingClient + ); + + final result = await clientsProvider.addClientList( + log.client, + log.clientInfo!.disallowed == true + ? AccessSettingsList.allowed + : AccessSettingsList.disallowed + ); + + processModal.close(); + + if (!context.mounted) return; + if (result.successful == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientAddedSuccessfully, + color: Colors.green + ); + } + else if (result.successful == false && result.content == 'client_another_list') { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientAnotherList, + color: Colors.red + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.changesNotSaved, + color: Colors.red + ); + } + } + void openAddClient() { Future.delayed( const Duration(milliseconds: 0), @@ -229,6 +270,15 @@ class LogTile extends StatelessWidget { icon: Icons.add_rounded, action: openAddClient ), + MenuOption( + title: log.clientInfo!.disallowed == true + ? AppLocalizations.of(context)!.allowThisClient + : AppLocalizations.of(context)!.disallowThisClient, + icon: log.clientInfo!.disallowed == true + ? Icons.check_rounded + : Icons.block_rounded, + action: allowDisallowClient + ), if (log.question.name != null) MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, @@ -421,6 +471,15 @@ class LogTile extends StatelessWidget { icon: Icons.add_rounded, action: openAddClient ), + MenuOption( + title: log.clientInfo!.disallowed == true + ? AppLocalizations.of(context)!.allowThisClient + : AppLocalizations.of(context)!.disallowThisClient, + icon: log.clientInfo!.disallowed == true + ? Icons.check_rounded + : Icons.block_rounded, + action: allowDisallowClient + ), if (log.question.name != null) MenuOption( title: AppLocalizations.of(context)!.copyClipboard, icon: Icons.copy_rounded, From a8d0bd95a6a6d84fb50e8e97bd2cb96b9183d01a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 20:41:49 +0100 Subject: [PATCH 586/676] Changed options menu --- lib/widgets/options_menu.dart | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/widgets/options_menu.dart b/lib/widgets/options_menu.dart index ad91b33..8daeb00 100644 --- a/lib/widgets/options_menu.dart +++ b/lib/widgets/options_menu.dart @@ -76,6 +76,7 @@ class _OptionsModal extends StatelessWidget { Widget build(BuildContext context) { return AlertDialog( contentPadding: const EdgeInsets.symmetric(vertical: 16), + scrollable: true, title: Column( children: [ Icon( @@ -94,19 +95,17 @@ class _OptionsModal extends StatelessWidget { ), content: ConstrainedBox( constraints: const BoxConstraints( - maxWidth: 400 + maxWidth: 500 ), - child: SingleChildScrollView( - child: Wrap( - children: options(value).map((opt) => CustomListTileDialog( - title: opt.title, - icon: opt.icon, - onTap: () { - Navigator.pop(context); - opt.action(); - }, - )).toList() - ), + child: Column( + children: options(value).map((opt) => CustomListTileDialog( + title: opt.title, + icon: opt.icon, + onTap: () { + Navigator.pop(context); + opt.action(); + }, + )).toList() ), ), actions: [ From 4b3129656ba71617963b8d4d41a99702ca2868a2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 20:43:03 +0100 Subject: [PATCH 587/676] Updated libraries --- pubspec.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 38751b2..f59e518 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -157,10 +157,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: a866f1f8947bfdaf674d7928e769eac7230388a2e7a2542824fad4bb5b87be3b + sha256: eae98052fa6e2826bdac3dd2e921c6ce2903be15c6b7f8b6d8a5d49b5086298d url: "https://pub.dev" source: hosted - version: "1.6.9" + version: "1.7.0" equatable: dependency: transitive description: @@ -311,10 +311,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: a64c5323ac83ed2b7940d2b6288d160aa1753ff271ba9d9b2a86770414aa3eab + sha256: cb44f7831b23a6bdd0f501718b0d2e8045cbc625a15f668af37ddb80314821db url: "https://pub.dev" source: hosted - version: "0.6.20+1" + version: "0.6.21" flutter_native_splash: dependency: "direct dev" description: @@ -458,10 +458,10 @@ packages: dependency: "direct main" description: name: markdown - sha256: "1b134d9f8ff2da15cb298efe6cd8b7d2a78958c1b00384ebcbdf13fe340a6c90" + sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051 url: "https://pub.dev" source: hosted - version: "7.2.1" + version: "7.2.2" matcher: dependency: transitive description: @@ -618,18 +618,18 @@ packages: dependency: transitive description: name: sentry - sha256: d2ee9c850d876d285f22e2e662f400ec2438df9939fe4acd5d780df9841794ce + sha256: a524a87d096799b775530176c8c082afe7aa1f10cc31ba078fecdd74e9afc923 url: "https://pub.dev" source: hosted - version: "7.16.1" + version: "7.17.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "5b428c189c825f16fb14e9166529043f06b965d5b59bfc3a1415e39c082398c0" + sha256: e0f8367f8f7c74dba9f7521f71700bce6c6ee065cf342f065d4fce411b84fc7b url: "https://pub.dev" source: hosted - version: "7.16.1" + version: "7.17.0" shared_preferences: dependency: "direct main" description: @@ -951,10 +951,10 @@ packages: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.3.0" win32_registry: dependency: transitive description: From ac5be8b5001fa1c0ac94095773b92084e76d1c71 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 20:43:28 +0100 Subject: [PATCH 588/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 70e1dff..20d81bb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.16.4+134 +version: 2.17.0+135 environment: sdk: '>=2.18.1 <3.0.0' From e88b61eb906bec7498bd8d3b86024a45740b31d1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 9 Mar 2024 20:43:28 +0100 Subject: [PATCH 589/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 70e1dff..66651ef 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.16.4+134 +version: 2.17.0-beta.1+135 environment: sdk: '>=2.18.1 <3.0.0' From b270ca2b8c75abe989328e0e688416a906d01597 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 10 Mar 2024 14:51:35 +0100 Subject: [PATCH 590/676] Added sliverappbar to more screens --- .../modals/blocked_services_screen.dart | 367 +++++++++++------- .../modals/custom_rules/add_custom_rule.dart | 94 +++-- .../custom_rules/edit_custom_rules.dart | 66 ++-- macos/Podfile.lock | 14 +- 4 files changed, 331 insertions(+), 210 deletions(-) diff --git a/lib/screens/filters/modals/blocked_services_screen.dart b/lib/screens/filters/modals/blocked_services_screen.dart index b95dd4f..f3f52ec 100644 --- a/lib/screens/filters/modals/blocked_services_screen.dart +++ b/lib/screens/filters/modals/blocked_services_screen.dart @@ -85,38 +85,130 @@ class _BlockedServicesScreenStateWidget extends State { if (widget.fullScreen == true) { return Dialog.fullscreen( - child: Scaffold( - appBar: AppBar( - leading: CloseButton(onPressed: () => Navigator.pop(context)), - title: Text(AppLocalizations.of(context)!.blockedServices), - actions: [ - IconButton( - onPressed: updateBlockedServices, - icon: const Icon( - Icons.save_rounded - ), - tooltip: AppLocalizations.of(context)!.save, - ), - const SizedBox(width: 10) - ], - ), - body: SafeArea( - child: RefreshIndicator( - onRefresh: () async { - final result = await filteringProvider.loadBlockedServices(); - if (result == false) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.blockedServicesListNotLoaded, - color: Colors.red - ); - } - }, - child: _Content( - values: values, - updateValues: updateValues, + child: Material( + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.blockedServices), + actions: [ + IconButton( + onPressed: updateBlockedServices, + icon: const Icon( + Icons.save_rounded + ), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 10) + ], + ) ) - ), + ], + body: SafeArea( + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (filteringProvider.blockedServicesLoadStatus == LoadStatus.loading) Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingBlockedServicesList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ), + if (filteringProvider.blockedServicesLoadStatus == LoadStatus.loaded) SliverList.builder( + itemCount: filteringProvider.blockedServices!.services.length, + itemBuilder: (context, index) => Material( + color: Colors.transparent, + child: InkWell( + onTap: () => updateValues( + values.contains(filteringProvider.blockedServices!.services[index].id), + filteringProvider.blockedServices!.services[index] + ), + child: Padding( + padding: const EdgeInsets.only( + top: 6, + bottom: 6, + right: 12, + left: 24 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + filteringProvider.blockedServices!.services[index].name, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Checkbox( + value: values.contains(filteringProvider.blockedServices!.services[index].id), + onChanged: (value) => updateValues( + value!, + filteringProvider.blockedServices!.services[index] + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + ) + ], + ), + ), + ), + ) + ), + if (filteringProvider.blockedServicesLoadStatus == LoadStatus.error) Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.blockedServicesListNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ) + ], + ), + ) + ) ), ), ); @@ -162,9 +254,105 @@ class _BlockedServicesScreenStateWidget extends State { ), ), Expanded( - child: _Content( - values: values, - updateValues: updateValues, + child: Builder( + builder: (ctx) { + switch (filteringProvider.blockedServicesLoadStatus) { + case LoadStatus.loading: + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingBlockedServicesList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + case LoadStatus.loaded: + return ListView.builder( + itemCount: filteringProvider.blockedServices!.services.length, + itemBuilder: (context, index) => Material( + color: Colors.transparent, + child: InkWell( + onTap: () => updateValues( + values.contains(filteringProvider.blockedServices!.services[index].id), + filteringProvider.blockedServices!.services[index] + ), + child: Padding( + padding: const EdgeInsets.only( + top: 6, + bottom: 6, + right: 12, + left: 24 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + filteringProvider.blockedServices!.services[index].name, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurface + ), + ), + Checkbox( + value: values.contains(filteringProvider.blockedServices!.services[index].id), + onChanged: (value) => updateValues( + value!, + filteringProvider.blockedServices!.services[index] + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5) + ), + ) + ], + ), + ), + ), + ) + ); + + case LoadStatus.error: + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.blockedServicesListNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + }, ) ), ], @@ -175,117 +363,6 @@ class _BlockedServicesScreenStateWidget extends State { } } -class _Content extends StatelessWidget { - final List values; - final void Function(bool value, BlockedService item) updateValues; - - const _Content({ - required this.values, - required this.updateValues, - }); - - @override - Widget build(BuildContext context) { - final filteringProvider = Provider.of(context); - - switch (filteringProvider.blockedServicesLoadStatus) { - case LoadStatus.loading: - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingBlockedServicesList, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - case LoadStatus.loaded: - return ListView.builder( - itemCount: filteringProvider.blockedServices!.services.length, - itemBuilder: (context, index) => Material( - color: Colors.transparent, - child: InkWell( - onTap: () => updateValues( - values.contains(filteringProvider.blockedServices!.services[index].id), - filteringProvider.blockedServices!.services[index] - ), - child: Padding( - padding: const EdgeInsets.only( - top: 6, - bottom: 6, - right: 12, - left: 24 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - filteringProvider.blockedServices!.services[index].name, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurface - ), - ), - Checkbox( - value: values.contains(filteringProvider.blockedServices!.services[index].id), - onChanged: (value) => updateValues( - value!, - filteringProvider.blockedServices!.services[index] - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5) - ), - ) - ], - ), - ), - ), - ) - ); - - case LoadStatus.error: - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.blockedServicesListNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], - ), - ); - - default: - return const SizedBox(); - } - } -} void openBlockedServicesModal({ required BuildContext context, diff --git a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart index 00fe303..7e6e604 100644 --- a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart +++ b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart @@ -55,44 +55,66 @@ class _AddCustomRuleState extends State { Widget build(BuildContext context) { if (widget.fullScreen == true) { return Dialog.fullscreen( - child: Scaffold( - appBar: AppBar( - leading: CloseButton(onPressed: () => Navigator.pop(context)), - title: Text(AppLocalizations.of(context)!.addCustomRule), - actions: [ - IconButton( - onPressed: _checkValidValues() == true - ? () { - Navigator.pop(context); - widget.onConfirm( - _buildRule( - domainController: _domainController, - important: _addImportant, - preset: _preset - ) - ); - } - : null, - icon: const Icon(Icons.check) - ), - const SizedBox(width: 10) - ], - ), - body: SafeArea( - child: ListView( - children: [ - _CustomRuleEditor( - domainController: _domainController, - domainError: _domainError, - important: _addImportant, - preset: _preset, - setImportant: (v) => setState(() => _addImportant = v), - setPreset: (v) => setState(() => _preset = v), - validateDomain: validateDomain + child: Material( + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.addCustomRule), + actions: [ + IconButton( + onPressed: _checkValidValues() == true + ? () { + Navigator.pop(context); + widget.onConfirm( + _buildRule( + domainController: _domainController, + important: _addImportant, + preset: _preset + ) + ); + } + : null, + icon: const Icon(Icons.check) + ), + const SizedBox(width: 10) + ], + ) ) - ] + ], + body: SafeArea( + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + _CustomRuleEditor( + domainController: _domainController, + domainError: _domainError, + important: _addImportant, + preset: _preset, + setImportant: (v) => setState(() => _addImportant = v), + setPreset: (v) => setState(() => _preset = v), + validateDomain: validateDomain + ) + ] + ) + ], + ), + ) + ) ), - ) ), ); } diff --git a/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart b/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart index ba02ab0..b063411 100644 --- a/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart +++ b/lib/screens/filters/modals/custom_rules/edit_custom_rules.dart @@ -37,29 +37,51 @@ class _EditCustomRulesState extends State { Widget build(BuildContext context) { if (widget.fullScreen == true) { return Dialog.fullscreen( - child: Scaffold( - appBar: AppBar( - leading: CloseButton(onPressed: () => Navigator.pop(context)), - title: Text(AppLocalizations.of(context)!.editCustomRules), - actions: [ - IconButton( - onPressed: () { - Navigator.pop(context); - widget.onConfirm(_fieldController.text.split("\n")); - }, - icon: const Icon(Icons.save_rounded), - tooltip: AppLocalizations.of(context)!.save, - ), - const SizedBox(width: 10) - ], + child: Material( + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + leading: CloseButton(onPressed: () => Navigator.pop(context)), + title: Text(AppLocalizations.of(context)!.editCustomRules), + actions: [ + IconButton( + onPressed: () { + Navigator.pop(context); + widget.onConfirm(_fieldController.text.split("\n")); + }, + icon: const Icon(Icons.save_rounded), + tooltip: AppLocalizations.of(context)!.save, + ), + const SizedBox(width: 10) + ], + ) + ) + ], + body: SafeArea( + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: [ + _CustomRulesRawEditor(fieldController: _fieldController) + ] + ) + ], + ), + ) + ) ), - body: SafeArea( - child: ListView( - children: [ - _CustomRulesRawEditor(fieldController: _fieldController) - ] - ), - ) ), ); } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 33a5a97..a7aa080 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -6,13 +6,13 @@ PODS: - FlutterMacOS (1.0.0) - package_info_plus (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.20.0): - - SentryPrivate (= 8.20.0) + - Sentry/HybridSDK (8.21.0): + - SentryPrivate (= 8.21.0) - sentry_flutter (0.0.1): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.20.0) - - SentryPrivate (8.20.0) + - Sentry/HybridSDK (= 8.21.0) + - SentryPrivate (8.21.0) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS @@ -84,9 +84,9 @@ SPEC CHECKSUMS: dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - Sentry: a8d7b373b9f9868442b02a0c425192f693103cbf - sentry_flutter: 03e7660857a8cdb236e71456a7e8447b65c8a788 - SentryPrivate: 006b24af16828441f70e2ab6adf241bd0a8ad130 + Sentry: ebc12276bd17613a114ab359074096b6b3725203 + sentry_flutter: dff1df05dc39c83d04f9330b36360fc374574c5e + SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: 73b7fc691fdc43277614250e04d183740cb15078 From e013b1496e618eec44f03dedeb40c69534b3446f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 10 Mar 2024 20:30:25 +0100 Subject: [PATCH 591/676] Bug fixes --- lib/screens/logs/log_tile.dart | 4 ++-- lib/screens/logs/logs.dart | 10 +++++++++- lib/screens/logs/logs_list_appbar.dart | 9 +++++---- lib/screens/settings/dns/dns_server_settings.dart | 2 +- lib/screens/settings/update_server/update_screen.dart | 3 ++- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index f077c31..9dfea35 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -256,7 +256,7 @@ class LogTile extends StatelessWidget { newStatus: domainBlocked == true ? 'unblock' : 'block' ) ), - MenuOption( + if (filteringProvider.filtering != null) MenuOption( title: domainBlocked == true ? AppLocalizations.of(context)!.unblockThisClientOnly : AppLocalizations.of(context)!.blockThisClientOnly, @@ -457,7 +457,7 @@ class LogTile extends StatelessWidget { newStatus: domainBlocked == true ? 'unblock' : 'block' ) ), - MenuOption( + if (filteringProvider.filtering != null) MenuOption( title: domainBlocked == true ? AppLocalizations.of(context)!.unblockThisClientOnly : AppLocalizations.of(context)!.blockThisClientOnly, diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index 560db9c..e99317d 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -1,14 +1,16 @@ // ignore_for_file: use_build_context_synchronously import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:adguard_home_manager/screens/logs/logs_list.dart'; import 'package:adguard_home_manager/screens/logs/details/log_details_screen.dart'; import 'package:adguard_home_manager/models/logs.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; class Logs extends StatefulWidget { - const Logs({Key? key}) : super(key: key); + const Logs({super.key}); @override State createState() => _LogsState(); @@ -17,6 +19,12 @@ class Logs extends StatefulWidget { class _LogsState extends State { Log? _selectedLog; + @override + void initState() { + Provider.of(context, listen: false).fetchFilters(); + super.initState(); + } + @override Widget build(BuildContext context) { return LayoutBuilder( diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 341593a..5014806 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -59,7 +59,7 @@ class LogsListAppBar extends StatelessWidget { showDialog( context: context, builder: (context) => _Search( - searchButtonRenderBox: _searchButtonKey.currentContext!.findRenderObject() as RenderBox, + searchButtonRenderBox: _searchButtonKey.currentContext?.findRenderObject() as RenderBox?, onSearch: (v) { logsProvider.setAppliedFilters( AppliedFiters( @@ -243,7 +243,7 @@ class LogsListAppBar extends StatelessWidget { class _Search extends StatefulWidget { final void Function(String) onSearch; - final RenderBox searchButtonRenderBox; + final RenderBox? searchButtonRenderBox; const _Search({ required this.onSearch, @@ -269,7 +269,8 @@ class _SearchState extends State<_Search> { Widget build(BuildContext context) { final logsProvider = Provider.of(context); - final Offset position = widget.searchButtonRenderBox.localToGlobal(Offset.zero); + final position = widget.searchButtonRenderBox?.localToGlobal(Offset.zero); + final topPadding = MediaQuery.of(globalNavigatorKey.currentContext!).viewPadding.top; return GestureDetector( onTap: () => Navigator.pop(context), @@ -282,7 +283,7 @@ class _SearchState extends State<_Search> { alignment: Alignment.topCenter, children: [ Positioned( - top: position.dy - MediaQuery.of(globalNavigatorKey.currentContext!).viewPadding.top, + top: position != null ? position.dy - topPadding : topPadding, child: SizedBox( width: width, child: GestureDetector( diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index ddae1e3..a4b7369 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -165,7 +165,7 @@ class _DnsServerSettingsScreenState extends State { processModal.open(AppLocalizations.of(context)!.savingConfig); final result = await dnsProvider.saveDnsServerConfig({ - "ratelimit": int.parse(_limitRequestsController.text), + "ratelimit": int.tryParse(_limitRequestsController.text), "edns_cs_enabled": _enableEdns, "edns_cs_use_custom": _useCustomIpEdns, "edns_cs_custom_ip": _customIpEdnsController.text, diff --git a/lib/screens/settings/update_server/update_screen.dart b/lib/screens/settings/update_server/update_screen.dart index aa85e7c..5386ad8 100644 --- a/lib/screens/settings/update_server/update_screen.dart +++ b/lib/screens/settings/update_server/update_screen.dart @@ -47,6 +47,7 @@ class _UpdateScreenState extends State { void processChangelog() async { final serversProvider = Provider.of(context, listen: false); + if (serversProvider.updateAvailable.data?.changelog == null) return; final markdownResult = await compute(md.markdownToHtml, serversProvider.updateAvailable.data!.changelog!); final htmlParsedResult = await compute(html.parse, markdownResult); setState(() => _htmlChangelog = htmlParsedResult.outerHtml); @@ -84,7 +85,7 @@ class _UpdateScreenState extends State { processModal.close(); - if (!mounted) return; + if (!context.mounted) return; if (result.successful == true) { serversProvider.recheckPeriodServerUpdated(); showSnacbkar( From fd25088791d841fb20bface406aab39d1094da51 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 10 Mar 2024 20:31:16 +0100 Subject: [PATCH 592/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 66651ef..232e855 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.17.0-beta.1+135 +version: 2.17.0+136 environment: sdk: '>=2.18.1 <3.0.0' From 5be5377110f94407e949fee770d927747df2e117 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 10 Mar 2024 21:15:24 +0100 Subject: [PATCH 593/676] Removed splitview package --- lib/screens/clients/added_list.dart | 4 +- lib/screens/clients/clients.dart | 37 +++++++--------- lib/screens/clients/clients_lists.dart | 18 ++++++-- lib/screens/settings/dhcp/dhcp.dart | 14 +++--- lib/screens/settings/dns/dns.dart | 4 +- .../general_settings/general_settings.dart | 6 ++- lib/screens/settings/settings.dart | 44 ++++++++++--------- pubspec.lock | 9 ---- pubspec.yaml | 4 -- 9 files changed, 71 insertions(+), 69 deletions(-) diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index aa86785..0bb668b 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -3,10 +3,10 @@ import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:flutter/rendering.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/clients/clients.dart'; import 'package:adguard_home_manager/screens/clients/client/client_screen_functions.dart'; import 'package:adguard_home_manager/screens/clients/client/added_client_tile.dart'; import 'package:adguard_home_manager/screens/clients/client/remove_client_modal.dart'; @@ -107,7 +107,7 @@ class _AddedListState extends State { if (result == true) { if (widget.splitView == true) { - SplitView.of(context).popUntil(0); + Navigator.of(clientsNavigatorKey.currentContext!).popUntil((route) => false); } showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 1549bb6..2ca57f1 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/clients_lists.dart'; import 'package:adguard_home_manager/models/clients.dart'; +final clientsNavigatorKey = GlobalKey(); + class Clients extends StatefulWidget { const Clients({super.key}); @@ -24,26 +24,23 @@ class _ClientsState extends State with TickerProviderStateMixin { body: LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 900) { - return SplitView.material( - hideDivider: true, - flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), - placeholder: Center( - child: Padding( - padding: const EdgeInsets.all(24), - child: Text( - AppLocalizations.of(context)!.selectClientLeftColumn, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ), + return Row( + children: [ + const Expanded( + flex: 1, + child: ClientsLists( + splitView: true, + ) ), - child: const ClientsLists( - splitView: true, + Expanded( + flex: 2, + child: Navigator( + key: clientsNavigatorKey, + onGenerateRoute: (settings) => MaterialPageRoute(builder: (ctx) => const SizedBox()), + ), ) - ); + ], + ); } else { return const ClientsLists( diff --git a/lib/screens/clients/clients_lists.dart b/lib/screens/clients/clients_lists.dart index bdc56b8..a2cfa19 100644 --- a/lib/screens/clients/clients_lists.dart +++ b/lib/screens/clients/clients_lists.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/clients/clients.dart'; import 'package:adguard_home_manager/screens/clients/added_list.dart'; import 'package:adguard_home_manager/screens/clients/client/logs_list_client.dart'; import 'package:adguard_home_manager/screens/clients/clients_list.dart'; @@ -68,7 +68,13 @@ class _ClientsListsState extends State with TickerProviderStateMix splitView: widget.splitView, ); if (widget.splitView) { - SplitView.of(context).push(w); + Navigator.of(clientsNavigatorKey.currentContext!).pushReplacement( + PageRouteBuilder( + pageBuilder: (context, animation1, animation2) => w, + transitionDuration: Duration.zero, + reverseTransitionDuration: Duration.zero, + ) + ); } else { Navigator.of(context).push( @@ -88,7 +94,13 @@ class _ClientsListsState extends State with TickerProviderStateMix splitView: widget.splitView, ); if (widget.splitView) { - SplitView.of(context).push(w); + Navigator.of(clientsNavigatorKey.currentContext!).pushReplacement( + PageRouteBuilder( + pageBuilder: (context, animation1, animation2) => w, + transitionDuration: Duration.zero, + reverseTransitionDuration: Duration.zero, + ) + ); } else { Navigator.of(context).push( diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index a17d620..f7facd6 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -3,10 +3,10 @@ import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/settings/settings.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_not_available.dart'; import 'package:adguard_home_manager/widgets/confirm_action_modal.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_main_button.dart'; @@ -610,11 +610,11 @@ class _DhcpScreenState extends State { ElevatedButton( onPressed: () { if (!(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push( - DhcpLeases( + Navigator.of(settingsNavigatorKey.currentContext!).push( + MaterialPageRoute(builder: (ctx) => DhcpLeases( items: dhcpProvider.dhcp!.dhcpStatus!.leases, staticLeases: false, - ) + )) ); } else { @@ -639,11 +639,11 @@ class _DhcpScreenState extends State { ElevatedButton( onPressed: () { if (!(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push( - DhcpLeases( + Navigator.of(settingsNavigatorKey.currentContext!).push( + MaterialPageRoute(builder: (ctx) => DhcpLeases( items: dhcpProvider.dhcp!.dhcpStatus!.staticLeases, staticLeases: true, - ) + )) ); } else { diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index 4a7c78a..baba9fa 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -1,10 +1,10 @@ // ignore_for_file: use_build_context_synchronously import 'package:flutter/material.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/settings/settings.dart'; import 'package:adguard_home_manager/screens/settings/dns/fallback_dns.dart'; import 'package:adguard_home_manager/screens/settings/dns/test_upstream_dns_modal.dart'; import 'package:adguard_home_manager/screens/settings/dns/clear_dns_cache_dialog.dart'; @@ -52,7 +52,7 @@ class _DnsSettingsState extends State { void navigate(Widget w) { if (widget.splitView) { - SplitView.of(context).push(w); + Navigator.of(settingsNavigatorKey.currentContext!).push(MaterialPageRoute(builder: (ctx) => w)); } else { Navigator.of(context).push( diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index 7439353..7c396da 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -3,11 +3,11 @@ import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:store_checker/store_checker.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/screens/settings/settings.dart'; import 'package:adguard_home_manager/screens/settings/general_settings/top_items_list/top_items_list_settings.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; @@ -199,7 +199,9 @@ class _GeneralSettingsState extends State { title: AppLocalizations.of(context)!.topItemsOrder, subtitle: AppLocalizations.of(context)!.topItemsOrderDescription, onTap: () => widget.splitView == true - ? SplitView.of(context).push(const TopItemsListSettings()) + ? Navigator.of(settingsNavigatorKey.currentContext!).push( + MaterialPageRoute(builder: (ctx) => const TopItemsListSettings()) + ) : Navigator.of(context).push( MaterialPageRoute( builder: (context) => const TopItemsListSettings() diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index bce5e11..0f55b89 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/server_info/server_info.dart'; @@ -33,6 +32,8 @@ import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +final settingsNavigatorKey = GlobalKey(); + class Settings extends StatelessWidget { const Settings({super.key}); @@ -41,25 +42,22 @@ class Settings extends StatelessWidget { return LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 900) { - return SplitView.material( - hideDivider: true, - flexWidth: const FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2), - placeholder: Center( - child: Padding( - padding: const EdgeInsets.all(24), - child: Text( - AppLocalizations.of(context)!.selectOptionLeftColumn, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), + return Row( + children: [ + const Expanded( + flex: 1, + child: _SettingsWidget( + twoColumns: true, + ) ), - ), - child: const _SettingsWidget( - twoColumns: true, - ), + Expanded( + flex: 2, + child: Navigator( + key: settingsNavigatorKey, + onGenerateRoute: (settings) => MaterialPageRoute(builder: (ctx) => const SizedBox()), + ), + ) + ], ); } else { @@ -351,7 +349,13 @@ class _SettingsTile extends StatelessWidget { selectedItem: appConfigProvider.selectedSettingsScreen, onTap: () { appConfigProvider.setSelectedSettingsScreen(screen: thisItem, notify: true); - SplitView.of(context).setSecondary(screenToNavigate); + Navigator.of(settingsNavigatorKey.currentContext!).pushReplacement( + PageRouteBuilder( + pageBuilder: (context, animation1, animation2) => screenToNavigate, + transitionDuration: Duration.zero, + reverseTransitionDuration: Duration.zero, + ), + ); }, ); } diff --git a/pubspec.lock b/pubspec.lock index f59e518..a1ae53b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -331,15 +331,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" - flutter_split_view: - dependency: "direct main" - description: - path: "." - ref: master-alt - resolved-ref: a6aa2419243cc0abccf9474ce340790d6c0ded6f - url: "https://github.com/JGeek00/flutter_split_view" - source: git - version: "0.1.2" flutter_svg: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 232e855..8aa5909 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,10 +62,6 @@ dependencies: git: url: https://github.com/google/flutter-desktop-embedding path: plugins/window_size - flutter_split_view: - git: - url: https://github.com/JGeek00/flutter_split_view - ref: master-alt contextmenu: ^3.0.0 async: ^2.11.0 sentry_flutter: ^7.13.2 From 999da666b46eecc34f1b8492a7d47da4f8e75908 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 10 Mar 2024 21:24:17 +0100 Subject: [PATCH 594/676] Replaced window size with window manager --- lib/main.dart | 5 +++-- linux/flutter/generated_plugin_registrant.cc | 12 +++++++---- linux/flutter/generated_plugins.cmake | 3 ++- macos/Flutter/GeneratedPluginRegistrant.swift | 6 ++++-- macos/Podfile.lock | 16 +++++++++----- pubspec.lock | 21 ++++++++++++------- pubspec.yaml | 5 +---- .../flutter/generated_plugin_registrant.cc | 9 +++++--- windows/flutter/generated_plugins.cmake | 3 ++- 9 files changed, 51 insertions(+), 29 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 98669e6..db378ae 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -13,7 +13,7 @@ import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:store_checker/store_checker.dart'; -import 'package:window_size/window_size.dart'; +import 'package:window_manager/window_manager.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -40,7 +40,8 @@ void main() async { SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { - setWindowMinSize(const Size(500, 500)); + await windowManager.ensureInitialized(); + WindowManager.instance.setMinimumSize(const Size(1280, 720)); } if (Platform.isWindows || Platform.isLinux) { diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 1786709..fd3f3f5 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,15 +7,19 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include -#include +#include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) dynamic_color_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); + g_autoptr(FlPluginRegistrar) screen_retriever_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin"); + screen_retriever_plugin_register_with_registrar(screen_retriever_registrar); g_autoptr(FlPluginRegistrar) sentry_flutter_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin"); sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar); @@ -25,7 +29,7 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); - g_autoptr(FlPluginRegistrar) window_size_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin"); - window_size_plugin_register_with_registrar(window_size_registrar); + g_autoptr(FlPluginRegistrar) window_manager_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin"); + window_manager_plugin_register_with_registrar(window_manager_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 59ac090..307410d 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,10 +4,11 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color + screen_retriever sentry_flutter sqlite3_flutter_libs url_launcher_linux - window_size + window_manager ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 045b44f..28ea475 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,21 +8,23 @@ import Foundation import device_info_plus import dynamic_color import package_info_plus +import screen_retriever import sentry_flutter import shared_preferences_foundation import sqflite import sqlite3_flutter_libs import url_launcher_macos -import window_size +import window_manager func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) + ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) - WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin")) + WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index a7aa080..5357874 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -6,6 +6,8 @@ PODS: - FlutterMacOS (1.0.0) - package_info_plus (0.0.1): - FlutterMacOS + - screen_retriever (0.0.1): + - FlutterMacOS - Sentry/HybridSDK (8.21.0): - SentryPrivate (= 8.21.0) - sentry_flutter (0.0.1): @@ -36,7 +38,7 @@ PODS: - sqlite3/rtree - url_launcher_macos (0.0.1): - FlutterMacOS - - window_size (0.0.2): + - window_manager (0.2.0): - FlutterMacOS DEPENDENCIES: @@ -44,12 +46,13 @@ DEPENDENCIES: - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) + - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) - sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - - window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`) + - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) SPEC REPOS: trunk: @@ -66,6 +69,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral package_info_plus: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos + screen_retriever: + :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos sentry_flutter: :path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos shared_preferences_foundation: @@ -76,14 +81,15 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos - window_size: - :path: Flutter/ephemeral/.symlinks/plugins/window_size/macos + window_manager: + :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce + screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 Sentry: ebc12276bd17613a114ab359074096b6b3725203 sentry_flutter: dff1df05dc39c83d04f9330b36360fc374574c5e SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe @@ -92,7 +98,7 @@ SPEC CHECKSUMS: sqlite3: 73b7fc691fdc43277614250e04d183740cb15078 sqlite3_flutter_libs: 06a05802529659a272beac4ee1350bfec294f386 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 - window_size: 339dafa0b27a95a62a843042038fa6c3c48de195 + window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 diff --git a/pubspec.lock b/pubspec.lock index a1ae53b..7b50c80 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -597,6 +597,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.2" + screen_retriever: + dependency: transitive + description: + name: screen_retriever + sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90" + url: "https://pub.dev" + source: hosted + version: "0.1.9" segmented_button_slide: dependency: "direct main" description: @@ -954,15 +962,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" - window_size: + window_manager: dependency: "direct main" description: - path: "plugins/window_size" - ref: HEAD - resolved-ref: "6c66ad23ee79749f30a8eece542cf54eaf157ed8" - url: "https://github.com/google/flutter-desktop-embedding" - source: git - version: "0.1.0" + name: window_manager + sha256: b3c895bdf936c77b83c5254bec2e6b3f066710c1f89c38b20b8acc382b525494 + url: "https://pub.dev" + source: hosted + version: "0.3.8" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8aa5909..daf62b3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,10 +58,6 @@ dependencies: flutter_html: ^3.0.0-beta.2 sqlite3_flutter_libs: ^0.5.18 sqflite_common_ffi: ^2.3.1 - window_size: - git: - url: https://github.com/google/flutter-desktop-embedding - path: plugins/window_size contextmenu: ^3.0.0 async: ^2.11.0 sentry_flutter: ^7.13.2 @@ -74,6 +70,7 @@ dependencies: flutter_custom_tabs: ^2.0.0+1 url_launcher: ^6.2.4 shared_preferences: ^2.2.2 + window_manager: ^0.3.8 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 50bb1c8..683e616 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,20 +7,23 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include -#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { DynamicColorPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); + ScreenRetrieverPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); SentryFlutterPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("SentryFlutterPlugin")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); - WindowSizePluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("WindowSizePlugin")); + WindowManagerPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("WindowManagerPlugin")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 71f5fcf..b2ba396 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,10 +4,11 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color + screen_retriever sentry_flutter sqlite3_flutter_libs url_launcher_windows - window_size + window_manager ) list(APPEND FLUTTER_FFI_PLUGIN_LIST From 7e13285b7eb479d83a2b79d25b874a6214c3f799 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 10 Mar 2024 21:30:25 +0100 Subject: [PATCH 595/676] Changed size --- lib/main.dart | 2 +- windows/runner/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index db378ae..dce3456 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -41,7 +41,7 @@ void main() async { if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { await windowManager.ensureInitialized(); - WindowManager.instance.setMinimumSize(const Size(1280, 720)); + WindowManager.instance.setMinimumSize(const Size(500, 700)); } if (Platform.isWindows || Platform.isLinux) { diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp index 1c992e7..618eef7 100644 --- a/windows/runner/main.cpp +++ b/windows/runner/main.cpp @@ -26,7 +26,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); + Win32Window::Size size(500,700); if (!window.Create(L"AdGuard Home Manager", origin, size)) { return EXIT_FAILURE; } From d48687bfa073fec2d93a74d5bff85cc0ddb48ceb Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 10 Mar 2024 21:53:06 +0100 Subject: [PATCH 596/676] Fixed innosetup --- windows/innosetup_installer_builder.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 92a4b72..53b8fc7 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -44,7 +44,7 @@ Source: "..\build\windows\x64\runner\Release\sentry_flutter_plugin.dll"; DestDir Source: "..\build\windows\x64\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\x64\runner\Release\window_size_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\window_manager_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files From d3b6833e1542a692b7d78e1c3f1807dad8eb7007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B7=EF=BC=A9=EF=BC=AE=EF=BC=BA=EF=BC=AF=EF=BC=B2?= =?UTF-8?q?=EF=BC=B4?= <75412448+mikropsoft@users.noreply.github.com> Date: Fri, 15 Mar 2024 19:43:51 +0300 Subject: [PATCH 597/676] Update app_tr.arb --- lib/l10n/app_tr.arb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 42c0f33..423dfa3 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -779,5 +779,17 @@ "enablePlainDnsDescription": "Düz DNS varsayılan olarak etkindir. Tüm aygıtları ÅŸifrelenmiÅŸ DNS kullanmaya zorlamak için bunu devre dışı bırakabilirsiniz. Bunu yapmak için en az bir ÅŸifrelenmiÅŸ DNS protokolünü etkinleÅŸtirmeniz gerekir.", "date": "Tarih", "loadingChangelog": "DeÄŸiÅŸiklikler yükleniyor...", - "invalidIpOrUrl": "Geçersiz IP adresi veya URL" + "invalidIpOrUrl": "Geçersiz IP adresi veya URL", + "addPersistentClient": "Kalıcı istemci olarak ekle", + "blockThisClientOnly": "Yalnızca bu istemci için engelle", + "unblockThisClientOnly": "Yalnızca bu istemci için engeli kaldır", + "domainBlockedThisClient": "Bu istemci için {domain} engellendi", + "domainUnblockedThisClient": "Bu istemci için {domain} engeli kaldırıldı", + "disallowThisClient": "Bu istemciye izin verme", + "allowThisClient": "Bu istemciye izin ver", + "clientAllowedSuccessfully": "İstemciye baÅŸarıyla izin verildi", + "clientDisallowedSuccessfully": "İstemci baÅŸarıyla reddedildi", + "changesNotSaved": "DeÄŸiÅŸiklikler kaydedilemedi", + "allowingClient": "İstemciye izin veriliyor...", + "disallowingClient": "İstemci reddediliyor..." } \ No newline at end of file From 18ee68d6840c1eebc73bd336c0f73bfd6fb24747 Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:06:09 +0000 Subject: [PATCH 598/676] Update app_zh.arb --- lib/l10n/app_zh.arb | 177 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 153 insertions(+), 24 deletions(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 8d246eb..7599fc5 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -23,7 +23,7 @@ "invalidUsernamePassword": "ç”¨æˆ·åæˆ–密ç é”™è¯¯", "tooManyAttempts": "å°è¯•次数过多,请ç¨åŽå†è¯•", "cantReachServer": "无法连接æœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥è¿žæŽ¥ä¿¡æ¯æ˜¯å¦æ­£ç¡®", - "sslError": "SSL 错误。转到 设置 > 高级设置 å¹¶å¯ç”¨ 䏿£€æŸ¥ SSL è¯ä¹¦", + "sslError": "SSL 错误 转到 设置 > 高级设置 å¹¶å¯ç”¨ 䏿£€æŸ¥ SSL è¯ä¹¦", "unknownError": "未知错误", "connectionNotCreated": "连接无法创建", "connecting": "正在连接...", @@ -158,7 +158,7 @@ "notSelected": "未选择", "resetFilters": "é‡ç½®è¿‡æ»¤å™¨", "noLogsDisplay": "æ— æ—¥å¿—å¯æ˜¾ç¤º", - "noLogsThatOld": "选择的时间段å¯èƒ½æ²¡æœ‰æ—¥å¿—。å°è¯•选择近期时间。", + "noLogsThatOld": "选择的时间段å¯èƒ½æ²¡æœ‰æ—¥å¿— 请å°è¯•选择近期时间 ", "apply": "应用", "selectAll": "全选", "unselectAll": "å–æ¶ˆå…¨é€‰", @@ -235,7 +235,7 @@ "urlNotValid": "URL 无效", "urlAbsolutePath": "URL 或ç»å¯¹è·¯å¾„", "addingList": "正在添加订阅规则...", - "listAdded": "订阅规则添加æˆåŠŸ 。已添加项目:", + "listAdded": "订阅规则添加æˆåŠŸ 已添加项目:", "listAlreadyAdded": "订阅规则已被添加", "listUrlInvalid": "订阅规则 URL 无效", "listNotAdded": "无法添加订阅规则", @@ -282,7 +282,7 @@ "clientsNotLoaded": "无法加载客户端", "noAllowedClients": "没有已å…许的客户端", "allowedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†ä»…æŽ¥å—æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求", - "blockedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†æ‹’ç»æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求。如果已å…许客户端中有æ¡ç›®ï¼Œåˆ™ä¼šå¿½ç•¥æ­¤å­—段", + "blockedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†æ‹’ç»æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求 如果已å…许客户端中有æ¡ç›®ï¼Œåˆ™ä¼šå¿½ç•¥æ­¤å­—段", "disallowedDomainsDescription": "AdGuard Home 会丢弃与这些域å匹é…çš„ DNS 查询,这些查询甚至ä¸ä¼šå‡ºçŽ°åœ¨æŸ¥è¯¢æ—¥å¿—ä¸­", "addClientFieldDescription": "CIDRã€IP åœ°å€æˆ–客户端 ID", "clientIdentifier": "客户端标识符", @@ -358,7 +358,7 @@ "seconds": "{time} ç§’", "leaseTimeNotValid": "租期无效", "restoreConfiguration": "é‡ç½®é…ç½®", - "restoreConfigurationMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰é…置。此æ“作无法撤消", + "restoreConfigurationMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰é…ç½® æ­¤æ“作无法撤消", "changeInterface": "更改接å£", "savingSettings": "正在ä¿å­˜è®¾ç½®...", "settingsSaved": "设置ä¿å­˜æˆåŠŸ", @@ -372,7 +372,7 @@ "staticLeaseDeleted": "DHCP 陿€ç§Ÿç”¨åˆ é™¤æˆåŠŸ", "staticLeaseNotDeleted": "无法删除 DHCP 陿€ç§Ÿç”¨", "deleteStaticLease": "åˆ é™¤é™æ€ç§Ÿç”¨", - "deleteStaticLeaseDescription": "DHCP 陿€ç§Ÿç”¨å°†è¢«åˆ é™¤ã€‚æ­¤æ“作无法撤消", + "deleteStaticLeaseDescription": "DHCP 陿€ç§Ÿç”¨å°†è¢«åˆ é™¤ æ­¤æ“作无法撤消", "addStaticLease": "æ·»åŠ é™æ€ç§Ÿç”¨", "macAddress": "MAC 地å€", "macAddressNotValid": "MAC åœ°å€æ— æ•ˆ", @@ -384,7 +384,7 @@ "staticLeaseExists": "DHCP 陿€ç§Ÿç”¨å·²å­˜åœ¨", "serverNotConfigured": "未é…ç½®æœåС噍", "restoreLeases": "é‡ç½®ç§Ÿç”¨", - "restoreLeasesMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰çŽ°æœ‰ç§Ÿç”¨ã€‚æ­¤æ“作无法撤消", + "restoreLeasesMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰çŽ°æœ‰ç§Ÿç”¨ æ­¤æ“作无法撤消", "restoringLeases": "正在é‡ç½®ç§Ÿç”¨...", "leasesRestored": "租用é‡ç½®æˆåŠŸ", "leasesNotRestored": "无法é‡ç½®ç§Ÿç”¨", @@ -427,24 +427,24 @@ "dnsSettingsDescription": "é…置与 DNS æœåŠ¡å™¨çš„è¿žæŽ¥", "upstreamDns": "上游 DNS æœåС噍", "bootstrapDns": "引导 DNS æœåС噍", - "noUpstreamDns": "未添加上游 DNS æœåŠ¡å™¨ã€‚", + "noUpstreamDns": "未添加上游 DNS æœåС噍 ", "dnsMode": "DNS 模å¼", "noDnsMode": "未选择 DNS 模å¼", "loadBalancing": "è´Ÿè½½å‡è¡¡", "parallelRequests": "并行请求", "fastestIpAddress": "最快的 IP 地å€", - "loadBalancingDescription": "æ¯æ¬¡æŸ¥è¯¢ä¸€ä¸ªä¸Šæ¸¸æœåŠ¡å™¨ã€‚AdGuard Home 使用其加æƒéšæœºç®—æ³•é€‰æ‹©æœåŠ¡å™¨ï¼Œä»¥ä¾¿æ›´é¢‘ç¹åœ°ä½¿ç”¨æœ€å¿«çš„æœåŠ¡å™¨", + "loadBalancingDescription": "æ¯æ¬¡æŸ¥è¯¢ä¸€ä¸ªä¸Šæ¸¸æœåС噍 AdGuard Home 使用其加æƒéšæœºç®—æ³•é€‰æ‹©æœåŠ¡å™¨ï¼Œä»¥ä¾¿æ›´é¢‘ç¹åœ°ä½¿ç”¨æœ€å¿«çš„æœåŠ¡å™¨", "parallelRequestsDescription": "ä½¿ç”¨å¹¶è¡ŒæŸ¥è¯¢åŒæ—¶åŠ é€Ÿè§£æžï¼ŒåŒæ—¶æŸ¥è¯¢æ‰€æœ‰ä¸Šæ¸¸æœåС噍", - "fastestIpAddressDescription": "查询所有 DNS æœåŠ¡å™¨å¹¶è¿”å›žæ‰€æœ‰å“应中最快的 IP 地å€ã€‚è¿™ä¼šå‡æ…¢ DNS 查询,因为 AdGuard Home 必须等待所有 DNS æœåŠ¡å™¨çš„å“应,但å¯ä»¥æ”¹å–„整体连接性", - "noBootstrapDns": "未添加引导 DNS æœåŠ¡å™¨ã€‚", - "bootstrapDnsServersInfo": "引导 DNS æœåŠ¡å™¨ç”¨äºŽè§£æžæ‚¨æŒ‡å®šçš„上游 DoH/DoT è§£æžå™¨çš„ IP 地å€ã€‚", + "fastestIpAddressDescription": "查询所有 DNS æœåŠ¡å™¨å¹¶è¿”å›žæ‰€æœ‰å“应中最快的 IP åœ°å€ è¿™ä¼šå‡æ…¢ DNS 查询,因为 AdGuard Home 必须等待所有 DNS æœåŠ¡å™¨çš„å“应,但å¯ä»¥æ”¹å–„整体连接性", + "noBootstrapDns": "未添加引导 DNS æœåС噍 ", + "bootstrapDnsServersInfo": "引导 DNS æœåŠ¡å™¨ç”¨äºŽè§£æžæ‚¨æŒ‡å®šçš„上游 DoH/DoT è§£æžå™¨çš„ IP åœ°å€ ", "privateReverseDnsServers": "ç§æœ‰åå‘ DNS æœåС噍", - "privateReverseDnsServersDescription": "AdGuard Home 用于本地 PTR 查询的 DNS æœåŠ¡å™¨ã€‚è¿™äº›æœåŠ¡å™¨ç”¨äºŽè§£æžç§æœ‰ IP 范围内的地å€çš„ PTR 请求,例如 \"192.168.12.34\"。如果未设置,AdGuard Home 将使用æ“作系统的默认 DNS è§£æžå™¨åœ°å€ï¼Œä½†ä¸åŒ…括 AdGuard Home 本身的地å€ã€‚", + "privateReverseDnsServersDescription": "AdGuard Home 用于本地 PTR 查询的 DNS æœåС噍 这些æœåŠ¡å™¨ç”¨äºŽè§£æžç§æœ‰ IP 范围内的地å€çš„ PTR 请求,例如 \"192.168.12.34\" 如果未设置,AdGuard Home 将使用æ“作系统的默认 DNS è§£æžå™¨åœ°å€ï¼Œä½†ä¸åŒ…括 AdGuard Home æœ¬èº«çš„åœ°å€ ", "reverseDnsDefault": "默认情况下,AdGuard Home 使用以下默认åå‘ DNS è§£æžå™¨", "addItem": "添加项目", "noServerAddressesAdded": "未添加æœåŠ¡å™¨åœ°å€", "usePrivateReverseDnsResolvers": "ä½¿ç”¨ç§æœ‰åå‘ DNS è§£æžå™¨", - "usePrivateReverseDnsResolversDescription": "使用这些上游æœåŠ¡å™¨æ‰§è¡Œæœ¬åœ°æä¾›çš„地å€çš„åå‘ DNS 查询。如果ç¦ç”¨ï¼ŒAdGuard Home 会对所有此类 PTR 请求(除了æ¥è‡ª DHCPã€/etc/hosts 等已知客户端)å“应 NXDOMAIN", + "usePrivateReverseDnsResolversDescription": "使用这些上游æœåŠ¡å™¨æ‰§è¡Œæœ¬åœ°æä¾›çš„地å€çš„åå‘ DNS 查询 如果ç¦ç”¨ï¼ŒAdGuard Home 会对所有此类 PTR 请求(除了æ¥è‡ª DHCPã€/etc/hosts 等已知客户端)å“应 NXDOMAIN", "enableReverseResolving": "å¯ç”¨å®¢æˆ·ç«¯ IP 地å€çš„åå‘è§£æž", "enableReverseResolvingDescription": "通过å‘相应的解æžå™¨å‘é€ PTR 查询,将客户端 IP 地å€è¿›è¡Œåå‘è§£æžä¸ºä¸»æœºåï¼ˆå¯¹äºŽæœ¬åœ°å®¢æˆ·ç«¯ä½¿ç”¨ç§æœ‰ DNS æœåŠ¡å™¨ï¼Œå¯¹äºŽå…·æœ‰å…¬å…± IP 地å€çš„客户端使用上游æœåŠ¡å™¨ï¼‰", "dnsServerSettings": "AdGuard Home DNS æœåŠ¡å™¨è®¾ç½®", @@ -492,7 +492,7 @@ "dnsCacheConfigDescription": "é…ç½®æœåŠ¡å™¨å¦‚ä½•ç®¡ç† DNS 缓存", "comment": "注释", "address": "地å€", - "commentsDescription": "注释始终以 # 开头。您无需添加它,系统将自动添加", + "commentsDescription": "注释始终以 # 开头 您无需添加它,系统将自动添加", "encryptionSettings": "加密设置", "encryptionSettingsDescription": "加密(HTTPS/QUIC/TLS)支æŒ", "loadingEncryptionSettings": "正在加载加密设置...", @@ -502,13 +502,13 @@ "enableEncryptionDescription": "如果å¯ç”¨åŠ å¯†ï¼ŒAdGuard Home 管ç†ç•Œé¢å°†é€šè¿‡ HTTPS è¿è¡Œï¼Œå¹¶ä¸” DNS æœåŠ¡å™¨å°†ç›‘å¬ DNS-over-HTTPS å’Œ DNS-over-TLS 请求", "serverConfiguration": "æœåС噍é…ç½®", "domainName": "域å", - "domainNameDescription": "如果设置,AdGuard Home 将检测 ClientIDã€å“应 DDR 查询并执行其他连接验è¯ã€‚如果未设置,这些功能将被ç¦ç”¨ã€‚必须与è¯ä¹¦ä¸­çš„ DNS å称之一匹é…", + "domainNameDescription": "如果设置,AdGuard Home 将检测 ClientIDã€å“应 DDR æŸ¥è¯¢å¹¶æ‰§è¡Œå…¶ä»–è¿žæŽ¥éªŒè¯ å¦‚æžœæœªè®¾ç½®ï¼Œè¿™äº›åŠŸèƒ½å°†è¢«ç¦ç”¨ 必须与è¯ä¹¦ä¸­çš„ DNS å称之一匹é…", "redirectHttps": "自动é‡å®šå‘到 HTTPS", "httpsPort": "HTTPS 端å£", "tlsPort": "DNS-over-TLS 端å£", "dnsOverQuicPort": "DNS-over-QUIC 端å£", "certificates": "è¯ä¹¦", - "certificatesDescription": "为了使用加密,您需è¦ä¸ºæ‚¨çš„域æä¾›æœ‰æ•ˆçš„ SSL è¯ä¹¦é“¾ã€‚您å¯ä»¥åœ¨ letsencrypt.org 上获得å…è´¹è¯ä¹¦ï¼Œä¹Ÿå¯ä»¥ä»Žå—信任的è¯ä¹¦é¢å‘机构购买", + "certificatesDescription": "为了使用加密,您需è¦ä¸ºæ‚¨çš„域æä¾›æœ‰æ•ˆçš„ SSL è¯ä¹¦é“¾ 您å¯ä»¥åœ¨ letsencrypt.org 上获得å…è´¹è¯ä¹¦ï¼Œä¹Ÿå¯ä»¥ä»Žå—信任的è¯ä¹¦é¢å‘机构购买", "certificateFilePath": "设置è¯ä¹¦æ–‡ä»¶è·¯å¾„", "pasteCertificateContent": "粘贴è¯ä¹¦å†…容", "certificatePath": "è¯ä¹¦è·¯å¾„", @@ -526,13 +526,13 @@ "encryptionConfigSaved": "加密é…置已æˆåŠŸä¿å­˜", "encryptionConfigNotSaved": "无法ä¿å­˜åР坆é…ç½®", "configError": "é…置错误", - "enterOnlyCertificate": "åªè¾“å…¥è¯ä¹¦ã€‚ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", - "enterOnlyPrivateKey": "åªè¾“入密钥。ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", + "enterOnlyCertificate": "åªè¾“å…¥è¯ä¹¦ ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行 ", + "enterOnlyPrivateKey": "åªè¾“入密钥 ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行 ", "noItemsSearch": "没有匹é…的项目", "clearSearch": "清除æœç´¢", "exitSearch": "退出æœç´¢", "searchClients": "æœç´¢å®¢æˆ·ç«¯", - "noClientsSearch": "没有匹é…的客户端。", + "noClientsSearch": "没有匹é…的客户端 ", "customization": "定制", "customizationDescription": "自定义此应用程åº", "color": "颜色", @@ -598,7 +598,7 @@ "checkUpdates": "检查更新", "requestingUpdate": "正在请求更新...", "autoupdateUnavailable": "自动更新ä¸å¯ç”¨", - "autoupdateUnavailableDescription": "æ­¤æœåС噍䏿”¯æŒè‡ªåŠ¨æ›´æ–°æœåŠ¡ã€‚è¿™å¯èƒ½æ˜¯å› ä¸ºæœåŠ¡å™¨æ­£åœ¨ Docker 容器中è¿è¡Œã€‚æ‚¨éœ€è¦æ‰‹åŠ¨æ›´æ–°æœåС噍", + "autoupdateUnavailableDescription": "æ­¤æœåС噍䏿”¯æŒè‡ªåŠ¨æ›´æ–°æœåŠ¡ è¿™å¯èƒ½æ˜¯å› ä¸ºæœåŠ¡å™¨æ­£åœ¨ Docker 容器中è¿è¡Œ æ‚¨éœ€è¦æ‰‹åŠ¨æ›´æ–°æœåС噍", "minute": "{time} 分钟", "minutes": "{time} 分钟", "hour": "{time} å°æ—¶", @@ -606,7 +606,7 @@ "remainingTime": "剩余时间", "safeSearchSettings": "安全æœç´¢è®¾ç½®", "loadingSafeSearchSettings": "正在加载安全æœç´¢è®¾ç½®...", - "safeSearchSettingsNotLoaded": "加载安全æœç´¢è®¾ç½®æ—¶å‡ºé”™ã€‚", + "safeSearchSettingsNotLoaded": "加载安全æœç´¢è®¾ç½®æ—¶å‡ºé”™ ", "loadingLogsSettings": "正在加载日志设置...", "selectOptionLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªé€‰é¡¹", "selectClientLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªå®¢æˆ·ç«¯", @@ -619,7 +619,7 @@ "copyListUrl": "å¤åˆ¶è®¢é˜…规则 URL", "listUrlCopied": "订阅规则 URL å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", "unsupportedVersion": "䏿”¯æŒçš„版本", - "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\n\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ã€‚alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", + "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\n\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", "iUnderstand": "我了解", "appUpdates": "åº”ç”¨ç¨‹åºæ›´æ–°", "usingLatestVersion": "您正在使用最新版本", @@ -658,7 +658,136 @@ "hideServerAddressDescription": "在主页上éšè—æœåŠ¡å™¨åœ°å€", "topItemsOrder": "顶部项目顺åº", "topItemsOrderDescription": "排列主页顶部项目列表", - "topItemsReorderInfo": "按ä½å¹¶æ»‘åŠ¨ä¸€ä¸ªé¡¹ç›®ä»¥é‡æ–°æŽ’åºã€‚", + "topItemsReorderInfo": "按ä½å¹¶æ»‘åŠ¨ä¸€ä¸ªé¡¹ç›®ä»¥é‡æ–°æŽ’åº ", "discardChanges": "放弃更改", "discardChangesDescription": "æ‚¨ç¡®å®šè¦æ”¾å¼ƒæ›´æ”¹å—?" + "others": "å…¶ä»–", + "showChart": "显示图表", + "hideChart": "éšè—图表", + "showTopItemsChart": "显示顶部项目图表", + "showTopItemsChartDescription": "默认情况下在移动视图中显示顶部项目部分的环形图 ", + "openMenu": "打开èœå•", + "closeMenu": "关闭èœå•", + "openListUrl": "打开列表URL", + "selectionMode": "选择模å¼", + "enableDisableSelected": "å¯ç”¨æˆ–ç¦ç”¨é€‰å®šé¡¹ç›®", + "deleteSelected": "删除选定项目", + "deleteSelectedLists": "删除选定列表", + "allSelectedListsDeletedSuccessfully": "所有选定列表已æˆåŠŸåˆ é™¤ ", + "deletionResult": "删除结果", + "deletingLists": "正在删除列表...", + "failedElements": "失败元素", + "processingLists": "正在处ç†åˆ—表...", + "enableDisableResult": "å¯ç”¨æˆ–ç¦ç”¨ç»“æžœ", + "selectedListsEnabledDisabledSuccessfully": "所有选定列表已æˆåŠŸå¯ç”¨æˆ–ç¦ç”¨" + "sslWarning": "如果您正在使用带有自签åè¯ä¹¦çš„ HTTPS 连接,请确ä¿åœ¨è®¾ç½® > 高级设置中å¯ç”¨ '䏿£€æŸ¥ SSL è¯ä¹¦' ", + "unsupportedServerVersion": "䏿”¯æŒçš„æœåŠ¡å™¨ç‰ˆæœ¬", + "unsupportedServerVersionMessage": "您的 AdGuard Home æœåŠ¡å™¨ç‰ˆæœ¬è¿‡æ—§ï¼Œä¸å— AdGuard Home Manager æ”¯æŒ æ‚¨éœ€è¦å°† AdGuard Home æœåС噍å‡çº§åˆ°æ›´æ–°çš„版本æ‰èƒ½ä½¿ç”¨æ­¤åº”ç”¨ç¨‹åº ", + "yourVersion": "您的版本:{version}", + "minimumRequiredVersion": "æœ€ä½Žè¦æ±‚版本:{version}", + "topUpstreams": "主è¦ä¸Šæ¸¸", + "averageUpstreamResponseTime": "å¹³å‡ä¸Šæ¸¸å“应时间", + "dhcpNotAvailable": "DHCP æœåС噍ä¸å¯ç”¨ ", + "osServerInstalledIncompatible": "æœåŠ¡å™¨å®‰è£…çš„æ“作系统与此功能ä¸å…¼å®¹ ", + "resetSettings": "é‡ç½®è®¾ç½®", + "resetEncryptionSettingsDescription": "您确定è¦å°†åŠ å¯†è®¾ç½®é‡ç½®ä¸ºé»˜è®¤å€¼å—?", + "resettingConfig": "正在é‡ç½®é…ç½®...", + "configurationResetSuccessfully": "é…置已æˆåŠŸé‡ç½®", + "configurationResetError": "é…置无法é‡ç½®", + "testUpstreamDnsServers": "测试上游 DNS æœåС噍", + "errorTestUpstreamDns": "测试上游 DNS æœåŠ¡å™¨æ—¶å‡ºé”™ ", + "useCustomIpEdns": "使用 EDNS 的自定义 IP", + "useCustomIpEdnsDescription": "å…许使用 EDNS 的自定义 IP", + "sortingOptions": "排åºé€‰é¡¹", + "fromHighestToLowest": "从高到低", + "fromLowestToHighest": "从低到高", + "queryLogsAndStatistics": "查询日志和统计", + "ignoreClientQueryLog": "在查询日志中忽略此客户端", + "ignoreClientStatistics": "在统计中忽略此客户端", + "savingChanges": "正在ä¿å­˜æ›´æ”¹...", + "fallbackDnsServers": "备用 DNS æœåС噍", + "fallbackDnsServersDescription": "é…置备用 DNS æœåС噍", + "fallbackDnsServersInfo": "当上游 DNS æœåŠ¡å™¨æ— å“应时使用的备用 DNS æœåŠ¡å™¨åˆ—è¡¨ 语法与上é¢çš„ä¸»ä¸Šæ¸¸å­—æ®µç›¸åŒ ", + "noFallbackDnsAdded": "未添加备用 DNS æœåС噍 ", + "blockedResponseTtl": "被阻止的å“应 TTL", + "blockedResponseTtlDescription": "指定客户端应缓存过滤å“应的秒数", + "invalidValue": "无效值", + "noDataChart": "æ²¡æœ‰æ•°æ®æ˜¾ç¤ºæ­¤å›¾è¡¨ ", + "noData": "æ— æ•°æ®", + "unblockClient": "解除客户端å°é”", + "blockingClient": "正在å°é”客户端...", + "unblockingClient": "正在解除客户端å°é”...", + "upstreamDnsCacheConfiguration": "DNS 上游缓存é…ç½®", + "enableDnsCachingClient": "为此客户端å¯ç”¨ DNS 缓存", + "dnsCacheSize": "DNS 缓存大å°", + "nameInvalid": "å称是必需的", + "oneIdentifierRequired": "至少需è¦ä¸€ä¸ªæ ‡è¯†ç¬¦", + "dnsCacheNumber": "DNS 缓存大å°å¿…须是一个数字", + "errors": "错误", + "redirectHttpsWarning": "如果您在 AdGuard Home æœåŠ¡å™¨ä¸Šå¯ç”¨äº† '自动é‡å®šå‘到 HTTPS',则必须选择 HTTPS 连接并使用æœåŠ¡å™¨çš„ HTTPS ç«¯å£ ", + "logsSettingsDescription": "é…置查询日志", + "ignoredDomains": "忽略的域å", + "noIgnoredDomainsAdded": "未添加忽略的域å", + "pauseServiceBlocking": "æš‚åœæœåŠ¡é˜»æ­¢", + "newSchedule": "新计划", + "editSchedule": "编辑计划", + "timezone": "时区", + "monday": "星期一", + "tuesday": "星期二", + "wednesday": "星期三", + "thursday": "星期四", + "friday": "星期五", + "saturday": "星期六", + "sunday": "星期日", + "from": "从", + "to": "到", + "selectStartTime": "选择开始时间", + "selectEndTime": "é€‰æ‹©ç»“æŸæ—¶é—´", + "startTimeBeforeEndTime": "å¼€å§‹æ—¶é—´å¿…é¡»åœ¨ç»“æŸæ—¶é—´ä¹‹å‰ ", + "noBlockingScheduleThisDevice": "此设备没有阻止计划 ", + "selectTimezone": "选择时区", + "selectClientsFiltersInfo": "é€‰æ‹©æ‚¨æƒ³è¦æ˜¾ç¤ºçš„客户端 如果没有选择任何客户端,将显示所有客户端 ", + "noDataThisSection": "æœ¬èŠ‚æ²¡æœ‰æ•°æ® ", + "statisticsSettings": "统计设置", + "statisticsSettingsDescription": "é…ç½®ç»Ÿè®¡æ•°æ®æ”¶é›†", + "loadingStatisticsSettings": "正在加载统计设置...", + "statisticsSettingsLoadError": "加载统计设置时å‘生错误 ", + "statisticsConfigUpdated": "统计设置æˆåŠŸæ›´æ–°", + "statisticsConfigNotUpdated": "统计设置无法更新", + "customTimeInHours": "è‡ªå®šä¹‰æ—¶é—´ï¼ˆä»¥å°æ—¶ä¸ºå•ä½ï¼‰", + "invalidTime": "无效时间", + "removeDomain": "移除域å", + "addDomain": "添加域å", + "notLess1Hour": "æ—¶é—´ä¸èƒ½å°‘于 1 å°æ—¶", + "rateLimit": "速率é™åˆ¶", + "subnetPrefixLengthIpv4": "IPv4 çš„å­ç½‘å‰ç¼€é•¿åº¦", + "subnetPrefixLengthIpv6": "IPv6 çš„å­ç½‘å‰ç¼€é•¿åº¦", + "rateLimitAllowlist": "速率é™åˆ¶ç™½åå•", + "rateLimitAllowlistDescription": "从速率é™åˆ¶ä¸­æŽ’除的 IP 地å€", + "dnsOptions": "DNS 选项", + "editor": "编辑器", + "editCustomRules": "编辑自定义规则", + "savingCustomRules": "正在ä¿å­˜è‡ªå®šä¹‰è§„则...", + "customRulesUpdatedSuccessfully": "自定义规则æˆåŠŸæ›´æ–°", + "customRulesNotUpdated": "自定义规则无法更新", + "reorder": "釿–°æŽ’åº", + "showHide": "显示/éšè—", + "noElementsReorderMessage": "在显示/éšè—标签页上å¯ç”¨ä¸€äº›å…ƒç´ ï¼Œç„¶åŽåœ¨è¿™é‡Œé‡æ–°æŽ’åº ", + "enablePlainDns": "å¯ç”¨æ™®é€š DNS", + "enablePlainDnsDescription": "默认å¯ç”¨æ™®é€š DNS 您å¯ä»¥ç¦ç”¨å®ƒï¼Œå¼ºåˆ¶æ‰€æœ‰è®¾å¤‡ä½¿ç”¨åР坆 DNS è¦åšåˆ°è¿™ä¸€ç‚¹ï¼Œæ‚¨å¿…须至少å¯ç”¨ä¸€ä¸ªåР坆 DNS åè®® ", + "date": "日期", + "loadingChangelog": "正在加载更新日志...", + "invalidIpOrUrl": "无效的 IP åœ°å€æˆ– URL", + "addPersistentClient": "添加为æŒä¹…客户端", + "blockThisClientOnly": "仅为此客户端å°é”", + "unblockThisClientOnly": "仅为此客户端解å°", + "domainBlockedThisClient": "{domain} 已为此客户端å°é”", + "domainUnblockedThisClient": "{domain} 已为此客户端解å°", + "disallowThisClient": "ç¦æ­¢æ­¤å®¢æˆ·ç«¯", + "allowThisClient": "å…许此客户端", + "clientAllowedSuccessfully": "客户端æˆåŠŸå…许", + "clientDisallowedSuccessfully": "客户端æˆåŠŸç¦æ­¢", + "changesNotSaved": "更改无法ä¿å­˜", + "allowingClient": "正在å…许客户端...", + "disallowingClient": "æ­£åœ¨ç¦æ­¢å®¢æˆ·ç«¯..." } From f838302720877db3bc4209804b1748e4c5aae9bd Mon Sep 17 00:00:00 2001 From: Zutzo <126886178+zutzo@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:07:15 +0000 Subject: [PATCH 599/676] Update app_zh_CN.arb --- lib/l10n/app_zh_CN.arb | 177 +++++++++++++++++++++++++++++++++++------ 1 file changed, 153 insertions(+), 24 deletions(-) diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb index 8d246eb..7599fc5 100644 --- a/lib/l10n/app_zh_CN.arb +++ b/lib/l10n/app_zh_CN.arb @@ -23,7 +23,7 @@ "invalidUsernamePassword": "ç”¨æˆ·åæˆ–密ç é”™è¯¯", "tooManyAttempts": "å°è¯•次数过多,请ç¨åŽå†è¯•", "cantReachServer": "无法连接æœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥è¿žæŽ¥ä¿¡æ¯æ˜¯å¦æ­£ç¡®", - "sslError": "SSL 错误。转到 设置 > 高级设置 å¹¶å¯ç”¨ 䏿£€æŸ¥ SSL è¯ä¹¦", + "sslError": "SSL 错误 转到 设置 > 高级设置 å¹¶å¯ç”¨ 䏿£€æŸ¥ SSL è¯ä¹¦", "unknownError": "未知错误", "connectionNotCreated": "连接无法创建", "connecting": "正在连接...", @@ -158,7 +158,7 @@ "notSelected": "未选择", "resetFilters": "é‡ç½®è¿‡æ»¤å™¨", "noLogsDisplay": "æ— æ—¥å¿—å¯æ˜¾ç¤º", - "noLogsThatOld": "选择的时间段å¯èƒ½æ²¡æœ‰æ—¥å¿—。å°è¯•选择近期时间。", + "noLogsThatOld": "选择的时间段å¯èƒ½æ²¡æœ‰æ—¥å¿— 请å°è¯•选择近期时间 ", "apply": "应用", "selectAll": "全选", "unselectAll": "å–æ¶ˆå…¨é€‰", @@ -235,7 +235,7 @@ "urlNotValid": "URL 无效", "urlAbsolutePath": "URL 或ç»å¯¹è·¯å¾„", "addingList": "正在添加订阅规则...", - "listAdded": "订阅规则添加æˆåŠŸ 。已添加项目:", + "listAdded": "订阅规则添加æˆåŠŸ 已添加项目:", "listAlreadyAdded": "订阅规则已被添加", "listUrlInvalid": "订阅规则 URL 无效", "listNotAdded": "无法添加订阅规则", @@ -282,7 +282,7 @@ "clientsNotLoaded": "无法加载客户端", "noAllowedClients": "没有已å…许的客户端", "allowedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†ä»…æŽ¥å—æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求", - "blockedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†æ‹’ç»æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求。如果已å…许客户端中有æ¡ç›®ï¼Œåˆ™ä¼šå¿½ç•¥æ­¤å­—段", + "blockedClientsDescription": "如果此列表中有æ¡ç›®ï¼ŒAdGuard Home å°†æ‹’ç»æ¥è‡ªè¿™äº›å®¢æˆ·ç«¯çš„请求 如果已å…许客户端中有æ¡ç›®ï¼Œåˆ™ä¼šå¿½ç•¥æ­¤å­—段", "disallowedDomainsDescription": "AdGuard Home 会丢弃与这些域å匹é…çš„ DNS 查询,这些查询甚至ä¸ä¼šå‡ºçŽ°åœ¨æŸ¥è¯¢æ—¥å¿—ä¸­", "addClientFieldDescription": "CIDRã€IP åœ°å€æˆ–客户端 ID", "clientIdentifier": "客户端标识符", @@ -358,7 +358,7 @@ "seconds": "{time} ç§’", "leaseTimeNotValid": "租期无效", "restoreConfiguration": "é‡ç½®é…ç½®", - "restoreConfigurationMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰é…置。此æ“作无法撤消", + "restoreConfigurationMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰é…ç½® æ­¤æ“作无法撤消", "changeInterface": "更改接å£", "savingSettings": "正在ä¿å­˜è®¾ç½®...", "settingsSaved": "设置ä¿å­˜æˆåŠŸ", @@ -372,7 +372,7 @@ "staticLeaseDeleted": "DHCP 陿€ç§Ÿç”¨åˆ é™¤æˆåŠŸ", "staticLeaseNotDeleted": "无法删除 DHCP 陿€ç§Ÿç”¨", "deleteStaticLease": "åˆ é™¤é™æ€ç§Ÿç”¨", - "deleteStaticLeaseDescription": "DHCP 陿€ç§Ÿç”¨å°†è¢«åˆ é™¤ã€‚æ­¤æ“作无法撤消", + "deleteStaticLeaseDescription": "DHCP 陿€ç§Ÿç”¨å°†è¢«åˆ é™¤ æ­¤æ“作无法撤消", "addStaticLease": "æ·»åŠ é™æ€ç§Ÿç”¨", "macAddress": "MAC 地å€", "macAddressNotValid": "MAC åœ°å€æ— æ•ˆ", @@ -384,7 +384,7 @@ "staticLeaseExists": "DHCP 陿€ç§Ÿç”¨å·²å­˜åœ¨", "serverNotConfigured": "未é…ç½®æœåС噍", "restoreLeases": "é‡ç½®ç§Ÿç”¨", - "restoreLeasesMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰çŽ°æœ‰ç§Ÿç”¨ã€‚æ­¤æ“作无法撤消", + "restoreLeasesMessage": "您确定è¦ç»§ç»­å—?这将é‡ç½®æ‰€æœ‰çŽ°æœ‰ç§Ÿç”¨ æ­¤æ“作无法撤消", "restoringLeases": "正在é‡ç½®ç§Ÿç”¨...", "leasesRestored": "租用é‡ç½®æˆåŠŸ", "leasesNotRestored": "无法é‡ç½®ç§Ÿç”¨", @@ -427,24 +427,24 @@ "dnsSettingsDescription": "é…置与 DNS æœåŠ¡å™¨çš„è¿žæŽ¥", "upstreamDns": "上游 DNS æœåС噍", "bootstrapDns": "引导 DNS æœåС噍", - "noUpstreamDns": "未添加上游 DNS æœåŠ¡å™¨ã€‚", + "noUpstreamDns": "未添加上游 DNS æœåС噍 ", "dnsMode": "DNS 模å¼", "noDnsMode": "未选择 DNS 模å¼", "loadBalancing": "è´Ÿè½½å‡è¡¡", "parallelRequests": "并行请求", "fastestIpAddress": "最快的 IP 地å€", - "loadBalancingDescription": "æ¯æ¬¡æŸ¥è¯¢ä¸€ä¸ªä¸Šæ¸¸æœåŠ¡å™¨ã€‚AdGuard Home 使用其加æƒéšæœºç®—æ³•é€‰æ‹©æœåŠ¡å™¨ï¼Œä»¥ä¾¿æ›´é¢‘ç¹åœ°ä½¿ç”¨æœ€å¿«çš„æœåŠ¡å™¨", + "loadBalancingDescription": "æ¯æ¬¡æŸ¥è¯¢ä¸€ä¸ªä¸Šæ¸¸æœåС噍 AdGuard Home 使用其加æƒéšæœºç®—æ³•é€‰æ‹©æœåŠ¡å™¨ï¼Œä»¥ä¾¿æ›´é¢‘ç¹åœ°ä½¿ç”¨æœ€å¿«çš„æœåŠ¡å™¨", "parallelRequestsDescription": "ä½¿ç”¨å¹¶è¡ŒæŸ¥è¯¢åŒæ—¶åŠ é€Ÿè§£æžï¼ŒåŒæ—¶æŸ¥è¯¢æ‰€æœ‰ä¸Šæ¸¸æœåС噍", - "fastestIpAddressDescription": "查询所有 DNS æœåŠ¡å™¨å¹¶è¿”å›žæ‰€æœ‰å“应中最快的 IP 地å€ã€‚è¿™ä¼šå‡æ…¢ DNS 查询,因为 AdGuard Home 必须等待所有 DNS æœåŠ¡å™¨çš„å“应,但å¯ä»¥æ”¹å–„整体连接性", - "noBootstrapDns": "未添加引导 DNS æœåŠ¡å™¨ã€‚", - "bootstrapDnsServersInfo": "引导 DNS æœåŠ¡å™¨ç”¨äºŽè§£æžæ‚¨æŒ‡å®šçš„上游 DoH/DoT è§£æžå™¨çš„ IP 地å€ã€‚", + "fastestIpAddressDescription": "查询所有 DNS æœåŠ¡å™¨å¹¶è¿”å›žæ‰€æœ‰å“应中最快的 IP åœ°å€ è¿™ä¼šå‡æ…¢ DNS 查询,因为 AdGuard Home 必须等待所有 DNS æœåŠ¡å™¨çš„å“应,但å¯ä»¥æ”¹å–„整体连接性", + "noBootstrapDns": "未添加引导 DNS æœåС噍 ", + "bootstrapDnsServersInfo": "引导 DNS æœåŠ¡å™¨ç”¨äºŽè§£æžæ‚¨æŒ‡å®šçš„上游 DoH/DoT è§£æžå™¨çš„ IP åœ°å€ ", "privateReverseDnsServers": "ç§æœ‰åå‘ DNS æœåС噍", - "privateReverseDnsServersDescription": "AdGuard Home 用于本地 PTR 查询的 DNS æœåŠ¡å™¨ã€‚è¿™äº›æœåŠ¡å™¨ç”¨äºŽè§£æžç§æœ‰ IP 范围内的地å€çš„ PTR 请求,例如 \"192.168.12.34\"。如果未设置,AdGuard Home 将使用æ“作系统的默认 DNS è§£æžå™¨åœ°å€ï¼Œä½†ä¸åŒ…括 AdGuard Home 本身的地å€ã€‚", + "privateReverseDnsServersDescription": "AdGuard Home 用于本地 PTR 查询的 DNS æœåС噍 这些æœåŠ¡å™¨ç”¨äºŽè§£æžç§æœ‰ IP 范围内的地å€çš„ PTR 请求,例如 \"192.168.12.34\" 如果未设置,AdGuard Home 将使用æ“作系统的默认 DNS è§£æžå™¨åœ°å€ï¼Œä½†ä¸åŒ…括 AdGuard Home æœ¬èº«çš„åœ°å€ ", "reverseDnsDefault": "默认情况下,AdGuard Home 使用以下默认åå‘ DNS è§£æžå™¨", "addItem": "添加项目", "noServerAddressesAdded": "未添加æœåŠ¡å™¨åœ°å€", "usePrivateReverseDnsResolvers": "ä½¿ç”¨ç§æœ‰åå‘ DNS è§£æžå™¨", - "usePrivateReverseDnsResolversDescription": "使用这些上游æœåŠ¡å™¨æ‰§è¡Œæœ¬åœ°æä¾›çš„地å€çš„åå‘ DNS 查询。如果ç¦ç”¨ï¼ŒAdGuard Home 会对所有此类 PTR 请求(除了æ¥è‡ª DHCPã€/etc/hosts 等已知客户端)å“应 NXDOMAIN", + "usePrivateReverseDnsResolversDescription": "使用这些上游æœåŠ¡å™¨æ‰§è¡Œæœ¬åœ°æä¾›çš„地å€çš„åå‘ DNS 查询 如果ç¦ç”¨ï¼ŒAdGuard Home 会对所有此类 PTR 请求(除了æ¥è‡ª DHCPã€/etc/hosts 等已知客户端)å“应 NXDOMAIN", "enableReverseResolving": "å¯ç”¨å®¢æˆ·ç«¯ IP 地å€çš„åå‘è§£æž", "enableReverseResolvingDescription": "通过å‘相应的解æžå™¨å‘é€ PTR 查询,将客户端 IP 地å€è¿›è¡Œåå‘è§£æžä¸ºä¸»æœºåï¼ˆå¯¹äºŽæœ¬åœ°å®¢æˆ·ç«¯ä½¿ç”¨ç§æœ‰ DNS æœåŠ¡å™¨ï¼Œå¯¹äºŽå…·æœ‰å…¬å…± IP 地å€çš„客户端使用上游æœåŠ¡å™¨ï¼‰", "dnsServerSettings": "AdGuard Home DNS æœåŠ¡å™¨è®¾ç½®", @@ -492,7 +492,7 @@ "dnsCacheConfigDescription": "é…ç½®æœåŠ¡å™¨å¦‚ä½•ç®¡ç† DNS 缓存", "comment": "注释", "address": "地å€", - "commentsDescription": "注释始终以 # 开头。您无需添加它,系统将自动添加", + "commentsDescription": "注释始终以 # 开头 您无需添加它,系统将自动添加", "encryptionSettings": "加密设置", "encryptionSettingsDescription": "加密(HTTPS/QUIC/TLS)支æŒ", "loadingEncryptionSettings": "正在加载加密设置...", @@ -502,13 +502,13 @@ "enableEncryptionDescription": "如果å¯ç”¨åŠ å¯†ï¼ŒAdGuard Home 管ç†ç•Œé¢å°†é€šè¿‡ HTTPS è¿è¡Œï¼Œå¹¶ä¸” DNS æœåŠ¡å™¨å°†ç›‘å¬ DNS-over-HTTPS å’Œ DNS-over-TLS 请求", "serverConfiguration": "æœåС噍é…ç½®", "domainName": "域å", - "domainNameDescription": "如果设置,AdGuard Home 将检测 ClientIDã€å“应 DDR 查询并执行其他连接验è¯ã€‚如果未设置,这些功能将被ç¦ç”¨ã€‚必须与è¯ä¹¦ä¸­çš„ DNS å称之一匹é…", + "domainNameDescription": "如果设置,AdGuard Home 将检测 ClientIDã€å“应 DDR æŸ¥è¯¢å¹¶æ‰§è¡Œå…¶ä»–è¿žæŽ¥éªŒè¯ å¦‚æžœæœªè®¾ç½®ï¼Œè¿™äº›åŠŸèƒ½å°†è¢«ç¦ç”¨ 必须与è¯ä¹¦ä¸­çš„ DNS å称之一匹é…", "redirectHttps": "自动é‡å®šå‘到 HTTPS", "httpsPort": "HTTPS 端å£", "tlsPort": "DNS-over-TLS 端å£", "dnsOverQuicPort": "DNS-over-QUIC 端å£", "certificates": "è¯ä¹¦", - "certificatesDescription": "为了使用加密,您需è¦ä¸ºæ‚¨çš„域æä¾›æœ‰æ•ˆçš„ SSL è¯ä¹¦é“¾ã€‚您å¯ä»¥åœ¨ letsencrypt.org 上获得å…è´¹è¯ä¹¦ï¼Œä¹Ÿå¯ä»¥ä»Žå—信任的è¯ä¹¦é¢å‘机构购买", + "certificatesDescription": "为了使用加密,您需è¦ä¸ºæ‚¨çš„域æä¾›æœ‰æ•ˆçš„ SSL è¯ä¹¦é“¾ 您å¯ä»¥åœ¨ letsencrypt.org 上获得å…è´¹è¯ä¹¦ï¼Œä¹Ÿå¯ä»¥ä»Žå—信任的è¯ä¹¦é¢å‘机构购买", "certificateFilePath": "设置è¯ä¹¦æ–‡ä»¶è·¯å¾„", "pasteCertificateContent": "粘贴è¯ä¹¦å†…容", "certificatePath": "è¯ä¹¦è·¯å¾„", @@ -526,13 +526,13 @@ "encryptionConfigSaved": "加密é…置已æˆåŠŸä¿å­˜", "encryptionConfigNotSaved": "无法ä¿å­˜åР坆é…ç½®", "configError": "é…置错误", - "enterOnlyCertificate": "åªè¾“å…¥è¯ä¹¦ã€‚ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", - "enterOnlyPrivateKey": "åªè¾“入密钥。ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行。", + "enterOnlyCertificate": "åªè¾“å…¥è¯ä¹¦ ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行 ", + "enterOnlyPrivateKey": "åªè¾“入密钥 ä¸è¦è¾“å…¥ ---BEGIN--- å’Œ ---END--- 行 ", "noItemsSearch": "没有匹é…的项目", "clearSearch": "清除æœç´¢", "exitSearch": "退出æœç´¢", "searchClients": "æœç´¢å®¢æˆ·ç«¯", - "noClientsSearch": "没有匹é…的客户端。", + "noClientsSearch": "没有匹é…的客户端 ", "customization": "定制", "customizationDescription": "自定义此应用程åº", "color": "颜色", @@ -598,7 +598,7 @@ "checkUpdates": "检查更新", "requestingUpdate": "正在请求更新...", "autoupdateUnavailable": "自动更新ä¸å¯ç”¨", - "autoupdateUnavailableDescription": "æ­¤æœåС噍䏿”¯æŒè‡ªåŠ¨æ›´æ–°æœåŠ¡ã€‚è¿™å¯èƒ½æ˜¯å› ä¸ºæœåŠ¡å™¨æ­£åœ¨ Docker 容器中è¿è¡Œã€‚æ‚¨éœ€è¦æ‰‹åŠ¨æ›´æ–°æœåС噍", + "autoupdateUnavailableDescription": "æ­¤æœåС噍䏿”¯æŒè‡ªåŠ¨æ›´æ–°æœåŠ¡ è¿™å¯èƒ½æ˜¯å› ä¸ºæœåŠ¡å™¨æ­£åœ¨ Docker 容器中è¿è¡Œ æ‚¨éœ€è¦æ‰‹åŠ¨æ›´æ–°æœåС噍", "minute": "{time} 分钟", "minutes": "{time} 分钟", "hour": "{time} å°æ—¶", @@ -606,7 +606,7 @@ "remainingTime": "剩余时间", "safeSearchSettings": "安全æœç´¢è®¾ç½®", "loadingSafeSearchSettings": "正在加载安全æœç´¢è®¾ç½®...", - "safeSearchSettingsNotLoaded": "加载安全æœç´¢è®¾ç½®æ—¶å‡ºé”™ã€‚", + "safeSearchSettingsNotLoaded": "加载安全æœç´¢è®¾ç½®æ—¶å‡ºé”™ ", "loadingLogsSettings": "正在加载日志设置...", "selectOptionLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªé€‰é¡¹", "selectClientLeftColumn": "在左侧æ ä¸­é€‰æ‹©ä¸€ä¸ªå®¢æˆ·ç«¯", @@ -619,7 +619,7 @@ "copyListUrl": "å¤åˆ¶è®¢é˜…规则 URL", "listUrlCopied": "订阅规则 URL å·²å¤åˆ¶åˆ°å‰ªè´´æ¿", "unsupportedVersion": "䏿”¯æŒçš„版本", - "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\n\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ã€‚alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", + "unsupprtedVersionMessage": "您的æœåŠ¡å™¨ç‰ˆæœ¬ {version} ä¸åœ¨æ”¯æŒèŒƒå›´ï¼Œé…åˆä½¿ç”¨å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜\n\nAdGuard Home Manager åªé€‚é…了 AdGuard Home æœåŠ¡å™¨çš„ç¨³å®šç‰ˆæœ¬ alpha å’Œ beta 版本也许能用,但ä¸ä¿è¯å…¼å®¹æ€§ï¼ŒåŒæ—¶ä½¿ç”¨æ—¶å¯èƒ½ä¼šå­˜åœ¨é—®é¢˜", "iUnderstand": "我了解", "appUpdates": "åº”ç”¨ç¨‹åºæ›´æ–°", "usingLatestVersion": "您正在使用最新版本", @@ -658,7 +658,136 @@ "hideServerAddressDescription": "在主页上éšè—æœåŠ¡å™¨åœ°å€", "topItemsOrder": "顶部项目顺åº", "topItemsOrderDescription": "排列主页顶部项目列表", - "topItemsReorderInfo": "按ä½å¹¶æ»‘åŠ¨ä¸€ä¸ªé¡¹ç›®ä»¥é‡æ–°æŽ’åºã€‚", + "topItemsReorderInfo": "按ä½å¹¶æ»‘åŠ¨ä¸€ä¸ªé¡¹ç›®ä»¥é‡æ–°æŽ’åº ", "discardChanges": "放弃更改", "discardChangesDescription": "æ‚¨ç¡®å®šè¦æ”¾å¼ƒæ›´æ”¹å—?" + "others": "å…¶ä»–", + "showChart": "显示图表", + "hideChart": "éšè—图表", + "showTopItemsChart": "显示顶部项目图表", + "showTopItemsChartDescription": "默认情况下在移动视图中显示顶部项目部分的环形图 ", + "openMenu": "打开èœå•", + "closeMenu": "关闭èœå•", + "openListUrl": "打开列表URL", + "selectionMode": "选择模å¼", + "enableDisableSelected": "å¯ç”¨æˆ–ç¦ç”¨é€‰å®šé¡¹ç›®", + "deleteSelected": "删除选定项目", + "deleteSelectedLists": "删除选定列表", + "allSelectedListsDeletedSuccessfully": "所有选定列表已æˆåŠŸåˆ é™¤ ", + "deletionResult": "删除结果", + "deletingLists": "正在删除列表...", + "failedElements": "失败元素", + "processingLists": "正在处ç†åˆ—表...", + "enableDisableResult": "å¯ç”¨æˆ–ç¦ç”¨ç»“æžœ", + "selectedListsEnabledDisabledSuccessfully": "所有选定列表已æˆåŠŸå¯ç”¨æˆ–ç¦ç”¨" + "sslWarning": "如果您正在使用带有自签åè¯ä¹¦çš„ HTTPS 连接,请确ä¿åœ¨è®¾ç½® > 高级设置中å¯ç”¨ '䏿£€æŸ¥ SSL è¯ä¹¦' ", + "unsupportedServerVersion": "䏿”¯æŒçš„æœåŠ¡å™¨ç‰ˆæœ¬", + "unsupportedServerVersionMessage": "您的 AdGuard Home æœåŠ¡å™¨ç‰ˆæœ¬è¿‡æ—§ï¼Œä¸å— AdGuard Home Manager æ”¯æŒ æ‚¨éœ€è¦å°† AdGuard Home æœåС噍å‡çº§åˆ°æ›´æ–°çš„版本æ‰èƒ½ä½¿ç”¨æ­¤åº”ç”¨ç¨‹åº ", + "yourVersion": "您的版本:{version}", + "minimumRequiredVersion": "æœ€ä½Žè¦æ±‚版本:{version}", + "topUpstreams": "主è¦ä¸Šæ¸¸", + "averageUpstreamResponseTime": "å¹³å‡ä¸Šæ¸¸å“应时间", + "dhcpNotAvailable": "DHCP æœåС噍ä¸å¯ç”¨ ", + "osServerInstalledIncompatible": "æœåŠ¡å™¨å®‰è£…çš„æ“作系统与此功能ä¸å…¼å®¹ ", + "resetSettings": "é‡ç½®è®¾ç½®", + "resetEncryptionSettingsDescription": "您确定è¦å°†åŠ å¯†è®¾ç½®é‡ç½®ä¸ºé»˜è®¤å€¼å—?", + "resettingConfig": "正在é‡ç½®é…ç½®...", + "configurationResetSuccessfully": "é…置已æˆåŠŸé‡ç½®", + "configurationResetError": "é…置无法é‡ç½®", + "testUpstreamDnsServers": "测试上游 DNS æœåС噍", + "errorTestUpstreamDns": "测试上游 DNS æœåŠ¡å™¨æ—¶å‡ºé”™ ", + "useCustomIpEdns": "使用 EDNS 的自定义 IP", + "useCustomIpEdnsDescription": "å…许使用 EDNS 的自定义 IP", + "sortingOptions": "排åºé€‰é¡¹", + "fromHighestToLowest": "从高到低", + "fromLowestToHighest": "从低到高", + "queryLogsAndStatistics": "查询日志和统计", + "ignoreClientQueryLog": "在查询日志中忽略此客户端", + "ignoreClientStatistics": "在统计中忽略此客户端", + "savingChanges": "正在ä¿å­˜æ›´æ”¹...", + "fallbackDnsServers": "备用 DNS æœåС噍", + "fallbackDnsServersDescription": "é…置备用 DNS æœåС噍", + "fallbackDnsServersInfo": "当上游 DNS æœåŠ¡å™¨æ— å“应时使用的备用 DNS æœåŠ¡å™¨åˆ—è¡¨ 语法与上é¢çš„ä¸»ä¸Šæ¸¸å­—æ®µç›¸åŒ ", + "noFallbackDnsAdded": "未添加备用 DNS æœåС噍 ", + "blockedResponseTtl": "被阻止的å“应 TTL", + "blockedResponseTtlDescription": "指定客户端应缓存过滤å“应的秒数", + "invalidValue": "无效值", + "noDataChart": "æ²¡æœ‰æ•°æ®æ˜¾ç¤ºæ­¤å›¾è¡¨ ", + "noData": "æ— æ•°æ®", + "unblockClient": "解除客户端å°é”", + "blockingClient": "正在å°é”客户端...", + "unblockingClient": "正在解除客户端å°é”...", + "upstreamDnsCacheConfiguration": "DNS 上游缓存é…ç½®", + "enableDnsCachingClient": "为此客户端å¯ç”¨ DNS 缓存", + "dnsCacheSize": "DNS 缓存大å°", + "nameInvalid": "å称是必需的", + "oneIdentifierRequired": "至少需è¦ä¸€ä¸ªæ ‡è¯†ç¬¦", + "dnsCacheNumber": "DNS 缓存大å°å¿…须是一个数字", + "errors": "错误", + "redirectHttpsWarning": "如果您在 AdGuard Home æœåŠ¡å™¨ä¸Šå¯ç”¨äº† '自动é‡å®šå‘到 HTTPS',则必须选择 HTTPS 连接并使用æœåŠ¡å™¨çš„ HTTPS ç«¯å£ ", + "logsSettingsDescription": "é…置查询日志", + "ignoredDomains": "忽略的域å", + "noIgnoredDomainsAdded": "未添加忽略的域å", + "pauseServiceBlocking": "æš‚åœæœåŠ¡é˜»æ­¢", + "newSchedule": "新计划", + "editSchedule": "编辑计划", + "timezone": "时区", + "monday": "星期一", + "tuesday": "星期二", + "wednesday": "星期三", + "thursday": "星期四", + "friday": "星期五", + "saturday": "星期六", + "sunday": "星期日", + "from": "从", + "to": "到", + "selectStartTime": "选择开始时间", + "selectEndTime": "é€‰æ‹©ç»“æŸæ—¶é—´", + "startTimeBeforeEndTime": "å¼€å§‹æ—¶é—´å¿…é¡»åœ¨ç»“æŸæ—¶é—´ä¹‹å‰ ", + "noBlockingScheduleThisDevice": "此设备没有阻止计划 ", + "selectTimezone": "选择时区", + "selectClientsFiltersInfo": "é€‰æ‹©æ‚¨æƒ³è¦æ˜¾ç¤ºçš„客户端 如果没有选择任何客户端,将显示所有客户端 ", + "noDataThisSection": "æœ¬èŠ‚æ²¡æœ‰æ•°æ® ", + "statisticsSettings": "统计设置", + "statisticsSettingsDescription": "é…ç½®ç»Ÿè®¡æ•°æ®æ”¶é›†", + "loadingStatisticsSettings": "正在加载统计设置...", + "statisticsSettingsLoadError": "加载统计设置时å‘生错误 ", + "statisticsConfigUpdated": "统计设置æˆåŠŸæ›´æ–°", + "statisticsConfigNotUpdated": "统计设置无法更新", + "customTimeInHours": "è‡ªå®šä¹‰æ—¶é—´ï¼ˆä»¥å°æ—¶ä¸ºå•ä½ï¼‰", + "invalidTime": "无效时间", + "removeDomain": "移除域å", + "addDomain": "添加域å", + "notLess1Hour": "æ—¶é—´ä¸èƒ½å°‘于 1 å°æ—¶", + "rateLimit": "速率é™åˆ¶", + "subnetPrefixLengthIpv4": "IPv4 çš„å­ç½‘å‰ç¼€é•¿åº¦", + "subnetPrefixLengthIpv6": "IPv6 çš„å­ç½‘å‰ç¼€é•¿åº¦", + "rateLimitAllowlist": "速率é™åˆ¶ç™½åå•", + "rateLimitAllowlistDescription": "从速率é™åˆ¶ä¸­æŽ’除的 IP 地å€", + "dnsOptions": "DNS 选项", + "editor": "编辑器", + "editCustomRules": "编辑自定义规则", + "savingCustomRules": "正在ä¿å­˜è‡ªå®šä¹‰è§„则...", + "customRulesUpdatedSuccessfully": "自定义规则æˆåŠŸæ›´æ–°", + "customRulesNotUpdated": "自定义规则无法更新", + "reorder": "釿–°æŽ’åº", + "showHide": "显示/éšè—", + "noElementsReorderMessage": "在显示/éšè—标签页上å¯ç”¨ä¸€äº›å…ƒç´ ï¼Œç„¶åŽåœ¨è¿™é‡Œé‡æ–°æŽ’åº ", + "enablePlainDns": "å¯ç”¨æ™®é€š DNS", + "enablePlainDnsDescription": "默认å¯ç”¨æ™®é€š DNS 您å¯ä»¥ç¦ç”¨å®ƒï¼Œå¼ºåˆ¶æ‰€æœ‰è®¾å¤‡ä½¿ç”¨åР坆 DNS è¦åšåˆ°è¿™ä¸€ç‚¹ï¼Œæ‚¨å¿…须至少å¯ç”¨ä¸€ä¸ªåР坆 DNS åè®® ", + "date": "日期", + "loadingChangelog": "正在加载更新日志...", + "invalidIpOrUrl": "无效的 IP åœ°å€æˆ– URL", + "addPersistentClient": "添加为æŒä¹…客户端", + "blockThisClientOnly": "仅为此客户端å°é”", + "unblockThisClientOnly": "仅为此客户端解å°", + "domainBlockedThisClient": "{domain} 已为此客户端å°é”", + "domainUnblockedThisClient": "{domain} 已为此客户端解å°", + "disallowThisClient": "ç¦æ­¢æ­¤å®¢æˆ·ç«¯", + "allowThisClient": "å…许此客户端", + "clientAllowedSuccessfully": "客户端æˆåŠŸå…许", + "clientDisallowedSuccessfully": "客户端æˆåŠŸç¦æ­¢", + "changesNotSaved": "更改无法ä¿å­˜", + "allowingClient": "正在å…许客户端...", + "disallowingClient": "æ­£åœ¨ç¦æ­¢å®¢æˆ·ç«¯..." } From e4298cc0620002cceba047664b58a88f48b53ae9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 Apr 2024 17:44:31 +0200 Subject: [PATCH 600/676] Fixed chinese translation --- lib/l10n/app_zh.arb | 4 ++-- lib/l10n/app_zh_CN.arb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 7599fc5..a789942 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -660,7 +660,7 @@ "topItemsOrderDescription": "排列主页顶部项目列表", "topItemsReorderInfo": "按ä½å¹¶æ»‘åŠ¨ä¸€ä¸ªé¡¹ç›®ä»¥é‡æ–°æŽ’åº ", "discardChanges": "放弃更改", - "discardChangesDescription": "æ‚¨ç¡®å®šè¦æ”¾å¼ƒæ›´æ”¹å—?" + "discardChangesDescription": "æ‚¨ç¡®å®šè¦æ”¾å¼ƒæ›´æ”¹å—?", "others": "å…¶ä»–", "showChart": "显示图表", "hideChart": "éšè—图表", @@ -679,7 +679,7 @@ "failedElements": "失败元素", "processingLists": "正在处ç†åˆ—表...", "enableDisableResult": "å¯ç”¨æˆ–ç¦ç”¨ç»“æžœ", - "selectedListsEnabledDisabledSuccessfully": "所有选定列表已æˆåŠŸå¯ç”¨æˆ–ç¦ç”¨" + "selectedListsEnabledDisabledSuccessfully": "所有选定列表已æˆåŠŸå¯ç”¨æˆ–ç¦ç”¨", "sslWarning": "如果您正在使用带有自签åè¯ä¹¦çš„ HTTPS 连接,请确ä¿åœ¨è®¾ç½® > 高级设置中å¯ç”¨ '䏿£€æŸ¥ SSL è¯ä¹¦' ", "unsupportedServerVersion": "䏿”¯æŒçš„æœåŠ¡å™¨ç‰ˆæœ¬", "unsupportedServerVersionMessage": "您的 AdGuard Home æœåŠ¡å™¨ç‰ˆæœ¬è¿‡æ—§ï¼Œä¸å— AdGuard Home Manager æ”¯æŒ æ‚¨éœ€è¦å°† AdGuard Home æœåС噍å‡çº§åˆ°æ›´æ–°çš„版本æ‰èƒ½ä½¿ç”¨æ­¤åº”ç”¨ç¨‹åº ", diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb index 7599fc5..a789942 100644 --- a/lib/l10n/app_zh_CN.arb +++ b/lib/l10n/app_zh_CN.arb @@ -660,7 +660,7 @@ "topItemsOrderDescription": "排列主页顶部项目列表", "topItemsReorderInfo": "按ä½å¹¶æ»‘åŠ¨ä¸€ä¸ªé¡¹ç›®ä»¥é‡æ–°æŽ’åº ", "discardChanges": "放弃更改", - "discardChangesDescription": "æ‚¨ç¡®å®šè¦æ”¾å¼ƒæ›´æ”¹å—?" + "discardChangesDescription": "æ‚¨ç¡®å®šè¦æ”¾å¼ƒæ›´æ”¹å—?", "others": "å…¶ä»–", "showChart": "显示图表", "hideChart": "éšè—图表", @@ -679,7 +679,7 @@ "failedElements": "失败元素", "processingLists": "正在处ç†åˆ—表...", "enableDisableResult": "å¯ç”¨æˆ–ç¦ç”¨ç»“æžœ", - "selectedListsEnabledDisabledSuccessfully": "所有选定列表已æˆåŠŸå¯ç”¨æˆ–ç¦ç”¨" + "selectedListsEnabledDisabledSuccessfully": "所有选定列表已æˆåŠŸå¯ç”¨æˆ–ç¦ç”¨", "sslWarning": "如果您正在使用带有自签åè¯ä¹¦çš„ HTTPS 连接,请确ä¿åœ¨è®¾ç½® > 高级设置中å¯ç”¨ '䏿£€æŸ¥ SSL è¯ä¹¦' ", "unsupportedServerVersion": "䏿”¯æŒçš„æœåŠ¡å™¨ç‰ˆæœ¬", "unsupportedServerVersionMessage": "您的 AdGuard Home æœåŠ¡å™¨ç‰ˆæœ¬è¿‡æ—§ï¼Œä¸å— AdGuard Home Manager æ”¯æŒ æ‚¨éœ€è¦å°† AdGuard Home æœåС噍å‡çº§åˆ°æ›´æ–°çš„版本æ‰èƒ½ä½¿ç”¨æ­¤åº”ç”¨ç¨‹åº ", From 3c397d208f6f41279fe60b2316f1998b61347fd1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 Apr 2024 17:52:20 +0200 Subject: [PATCH 601/676] Small bug fixes --- lib/screens/logs/log_tile.dart | 19 +++++++++++-------- .../settings/dns/test_upstream_dns_modal.dart | 4 ++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 9dfea35..2a6a720 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -1,5 +1,3 @@ -// ignore_for_file: use_build_context_synchronously - import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -133,6 +131,8 @@ class LogTile extends StatelessWidget { processModal.close(); + if (!context.mounted) return; + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, @@ -224,12 +224,15 @@ class LogTile extends StatelessWidget { void openAddClient() { Future.delayed( const Duration(milliseconds: 0), - () => openClientFormModal( - context: context, - width: MediaQuery.of(context).size.width, - onConfirm: confirmAddClient, - initialData: ClientInitialData(name: "Client ${log.client}", ip: log.client) - ) + () { + if (!context.mounted) return; + openClientFormModal( + context: context, + width: MediaQuery.of(context).size.width, + onConfirm: confirmAddClient, + initialData: ClientInitialData(name: "Client ${log.client}", ip: log.client) + ); + } ); } diff --git a/lib/screens/settings/dns/test_upstream_dns_modal.dart b/lib/screens/settings/dns/test_upstream_dns_modal.dart index 8410334..7bff710 100644 --- a/lib/screens/settings/dns/test_upstream_dns_modal.dart +++ b/lib/screens/settings/dns/test_upstream_dns_modal.dart @@ -29,6 +29,10 @@ class _TestUpstreamDnsModalState extends State { void checkDns() async { final dnsProvider = Provider.of(context, listen: false); + if (dnsProvider.dnsInfo == null) { + setState(() => loadStatus = LoadStatus.error); + return; + } final result = await Provider.of(context, listen: false).apiClient2!.testUpstreamDns( body: { "bootstrap_dns": dnsProvider.dnsInfo!.bootstrapDns, From 23264705789bbc5021c7bf83db248ec73ed3554d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 Apr 2024 17:59:25 +0200 Subject: [PATCH 602/676] Updated libraries --- lib/widgets/combined_line_chart.dart | 2 +- lib/widgets/line_chart.dart | 2 +- pubspec.lock | 120 +++++++++++++-------------- pubspec.yaml | 10 +-- 4 files changed, 67 insertions(+), 67 deletions(-) diff --git a/lib/widgets/combined_line_chart.dart b/lib/widgets/combined_line_chart.dart index d22b2cc..6f3a87f 100644 --- a/lib/widgets/combined_line_chart.dart +++ b/lib/widgets/combined_line_chart.dart @@ -86,7 +86,7 @@ class CustomCombinedLineChart extends StatelessWidget { enabled: true, touchTooltipData: LineTouchTooltipData( fitInsideHorizontally: true, - tooltipBgColor: selectedTheme == ThemeMode.light + getTooltipColor: (touchedSpot) => selectedTheme == ThemeMode.light ? const Color.fromRGBO(220, 220, 220, 0.9) : const Color.fromRGBO(35, 35, 35, 0.9), getTooltipItems: (items) { diff --git a/lib/widgets/line_chart.dart b/lib/widgets/line_chart.dart index 5a5e181..5ac8bdd 100644 --- a/lib/widgets/line_chart.dart +++ b/lib/widgets/line_chart.dart @@ -91,7 +91,7 @@ class CustomLineChart extends StatelessWidget { enabled: true, touchTooltipData: LineTouchTooltipData( fitInsideHorizontally: true, - tooltipBgColor: selectedTheme == ThemeMode.light + getTooltipColor: (touchedSpot) => selectedTheme == ThemeMode.light ? const Color.fromRGBO(220, 220, 220, 0.9) : const Color.fromRGBO(35, 35, 35, 0.9), getTooltipItems: (items) => [ diff --git a/pubspec.lock b/pubspec.lock index 7b50c80..4c0330d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.5.0" async: dependency: "direct main" description: @@ -133,18 +133,18 @@ packages: dependency: "direct main" description: name: cupertino_icons - sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 url: "https://pub.dev" source: hosted - version: "1.0.6" + version: "1.0.8" device_info_plus: dependency: "direct main" description: name: device_info_plus - sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110" + sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91 url: "https://pub.dev" source: hosted - version: "9.1.2" + version: "10.1.0" device_info_plus_platform_interface: dependency: transitive description: @@ -213,10 +213,10 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: "00b74ae680df6b1135bdbea00a7d1fc072a9180b7c3f3702e4b19a9943f5ed7d" + sha256: "2b7c1f5d867da9a054661641c8f499c55c47c39acccb97b3bc673f5fa9a39e74" url: "https://pub.dev" source: hosted - version: "0.66.2" + version: "0.67.0" flutter: dependency: "direct main" description: flutter @@ -298,10 +298,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" flutter_localizations: dependency: "direct main" description: flutter @@ -311,18 +311,18 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: cb44f7831b23a6bdd0f501718b0d2e8045cbc625a15f668af37ddb80314821db + sha256: "9921f9deda326f8a885e202b1e35237eadfc1345239a0f6f0f1ff287e047547f" url: "https://pub.dev" source: hosted - version: "0.6.21" + version: "0.7.1" flutter_native_splash: dependency: "direct dev" description: name: flutter_native_splash - sha256: "558f10070f03ee71f850a78f7136ab239a67636a294a44a06b6b7345178edb1e" + sha256: edf39bcf4d74aca1eb2c1e43c3e445fd9f494013df7f0da752fefe72020eedc0 url: "https://pub.dev" source: hosted - version: "2.3.10" + version: "2.4.0" flutter_reorderable_list: dependency: "direct main" description: @@ -361,10 +361,10 @@ packages: dependency: "direct main" description: name: http - sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" http_parser: dependency: transitive description: @@ -393,10 +393,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" json_annotation: dependency: transitive description: @@ -489,18 +489,18 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79" + sha256: "2c582551839386fa7ddbc7770658be7c0f87f388a4bff72066478f597c34d17f" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "7.0.0" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6" + sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.0" path: dependency: transitive description: @@ -585,10 +585,10 @@ packages: dependency: transitive description: name: pointycastle - sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" + sha256: "79fbafed02cfdbe85ef3fd06c7f4bc2cbcba0177e61b765264853d4253b21744" url: "https://pub.dev" source: hosted - version: "3.7.4" + version: "3.9.0" provider: dependency: "direct main" description: @@ -617,34 +617,34 @@ packages: dependency: transitive description: name: sentry - sha256: a524a87d096799b775530176c8c082afe7aa1f10cc31ba078fecdd74e9afc923 + sha256: "961630a4dba41cebd692612421fd3805a991ebd8ef4a8d84a6c179e6b89eaf22" url: "https://pub.dev" source: hosted - version: "7.17.0" + version: "8.0.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: e0f8367f8f7c74dba9f7521f71700bce6c6ee065cf342f065d4fce411b84fc7b + sha256: "705da7adfcd1fb23fc8720b6e222f5e03d53f1d020cd635586c319ee323366b4" url: "https://pub.dev" source: hosted - version: "7.17.0" + version: "8.0.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_foundation: dependency: transitive description: @@ -673,10 +673,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.0" shared_preferences_windows: dependency: transitive description: @@ -710,42 +710,42 @@ packages: dependency: "direct main" description: name: sqflite - sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 + sha256: "5ce2e1a15e822c3b4bfb5400455775e421da7098eed8adc8f26298ada7c9308c" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" + sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" url: "https://pub.dev" source: hosted - version: "2.5.3" + version: "2.5.4" sqflite_common_ffi: dependency: "direct main" description: name: sqflite_common_ffi - sha256: "754927d82de369a6b9e760fb60640aa81da650f35ffd468d5a992814d6022908" + sha256: "4d6137c29e930d6e4a8ff373989dd9de7bac12e3bc87bce950f6e844e8ad3bb5" url: "https://pub.dev" source: hosted - version: "2.3.2+1" + version: "2.3.3" sqlite3: dependency: transitive description: name: sqlite3 - sha256: "072128763f1547e3e9b4735ce846bfd226d68019ccda54db4cd427b12dfdedc9" + sha256: "1abbeb84bf2b1a10e5e1138c913123c8aa9d83cd64e5f9a0dd847b3c83063202" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: d6c31c8511c441d1f12f20b607343df1afe4eddf24a1cf85021677c8eea26060 + sha256: fb2a106a2ea6042fe57de2c47074cc31539a941819c91e105b864744605da3f5 url: "https://pub.dev" source: hosted - version: "0.5.20" + version: "0.5.21" stack_trace: dependency: transitive description: @@ -806,10 +806,10 @@ packages: dependency: "direct main" description: name: timezone - sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" + sha256: a6ccda4a69a442098b602c44e61a1e2b4bf6f5516e875bbf0f427d5df14745d5 url: "https://pub.dev" source: hosted - version: "0.9.2" + version: "0.9.3" typed_data: dependency: transitive description: @@ -830,18 +830,18 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" + sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" url: "https://pub.dev" source: hosted - version: "6.2.5" + version: "6.2.6" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 + sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_ios: dependency: transitive description: @@ -878,10 +878,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b + sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.1" url_launcher_windows: dependency: transitive description: @@ -894,10 +894,10 @@ packages: dependency: "direct main" description: name: uuid - sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 + sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" url: "https://pub.dev" source: hosted - version: "4.3.3" + version: "4.4.0" vector_graphics: dependency: transitive description: @@ -942,26 +942,26 @@ packages: dependency: transitive description: name: web - sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05" + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.4.2" + version: "0.5.1" win32: dependency: transitive description: name: win32 - sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480" + sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a" url: "https://pub.dev" source: hosted - version: "5.3.0" + version: "5.4.0" win32_registry: dependency: transitive description: name: win32_registry - sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" + sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.3" window_manager: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index daf62b3..4caf999 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,18 +41,18 @@ dependencies: intl: any provider: ^6.1.1 sqflite: ^2.3.0 - package_info_plus: ^5.0.1 + package_info_plus: ^7.0.0 flutter_displaymode: ^0.6.0 dynamic_color: ^1.6.8 animations: ^2.0.10 - device_info_plus: ^9.1.1 + device_info_plus: ^10.1.0 uuid: ^4.2.1 expandable: ^5.0.1 - fl_chart: ^0.66.0 + fl_chart: ^0.67.0 flutter_svg: ^2.0.9 percent_indicator: ^4.2.3 store_checker: ^1.4.0 - flutter_markdown: ^0.6.18+2 + flutter_markdown: ^0.7.1 markdown: ^7.1.1 html: ^0.15.4 flutter_html: ^3.0.0-beta.2 @@ -60,7 +60,7 @@ dependencies: sqflite_common_ffi: ^2.3.1 contextmenu: ^3.0.0 async: ^2.11.0 - sentry_flutter: ^7.13.2 + sentry_flutter: ^8.0.0 flutter_dotenv: ^5.1.0 flutter_reorderable_list: ^1.3.1 pie_chart: ^5.4.0 From 9295321cdaa651e8f9fb3d219476e6c2d1194583 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 Apr 2024 18:01:32 +0200 Subject: [PATCH 603/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 4caf999..c90cb23 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.17.0+136 +version: 2.17.1+137 environment: sdk: '>=2.18.1 <3.0.0' From 212e57149f2ed1e73ff6d7d395ef81cd10f53888 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 24 Apr 2024 18:12:53 +0200 Subject: [PATCH 604/676] Updated macos pods --- macos/Podfile.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 5357874..ead0b21 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -10,7 +10,7 @@ PODS: - FlutterMacOS - Sentry/HybridSDK (8.21.0): - SentryPrivate (= 8.21.0) - - sentry_flutter (0.0.1): + - sentry_flutter (8.0.0): - Flutter - FlutterMacOS - Sentry/HybridSDK (= 8.21.0) @@ -21,18 +21,18 @@ PODS: - sqflite (0.0.3): - Flutter - FlutterMacOS - - sqlite3 (3.45.1): - - sqlite3/common (= 3.45.1) - - sqlite3/common (3.45.1) - - sqlite3/fts5 (3.45.1): + - "sqlite3 (3.45.3+1)": + - "sqlite3/common (= 3.45.3+1)" + - "sqlite3/common (3.45.3+1)" + - "sqlite3/fts5 (3.45.3+1)": - sqlite3/common - - sqlite3/perf-threadsafe (3.45.1): + - "sqlite3/perf-threadsafe (3.45.3+1)": - sqlite3/common - - sqlite3/rtree (3.45.1): + - "sqlite3/rtree (3.45.3+1)": - sqlite3/common - sqlite3_flutter_libs (0.0.1): - FlutterMacOS - - sqlite3 (~> 3.45.1) + - "sqlite3 (~> 3.45.3+1)" - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree @@ -85,18 +85,18 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: - device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f + device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720 dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce + package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 Sentry: ebc12276bd17613a114ab359074096b6b3725203 - sentry_flutter: dff1df05dc39c83d04f9330b36360fc374574c5e + sentry_flutter: 4ce59806771a82cc2d2a4657b320c9801530db62 SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec - sqlite3: 73b7fc691fdc43277614250e04d183740cb15078 - sqlite3_flutter_libs: 06a05802529659a272beac4ee1350bfec294f386 + sqlite3: 02d1f07eaaa01f80a1c16b4b31dfcbb3345ee01a + sqlite3_flutter_libs: 8d204ef443cf0d5c1c8b058044eab53f3943a9c5 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 From 5f5d79147f4b0081954a81e3d2b67cc594c9bc53 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 8 Jun 2024 21:45:49 +0200 Subject: [PATCH 605/676] Updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 93788ac..96520c4 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Check the privacy policy [here](https://github.com/JGeek00/adguard-home-manager/ This is an unofficial application. The AdGuard Home team and the development of the AdGuard Home software is not related in any way with this application. ## Recommended configuration and lists -On [this repository](https://github.com/JuanRodenas/Pihole_list) you can find a recommended configuration for AdGuard Home and some lists. Thanks to [JuanRodenas](https://github.com/JuanRodenas). +On [this repository](https://github.com/juanico10/Pihole_list) you can find a recommended configuration for AdGuard Home and some lists. Thanks to [juanico10](https://github.com/juanico10). ## Generate production build
      From c5d2892ec2c5f504ea0b137859275277b0f82f93 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 17 Jun 2024 13:28:00 +0200 Subject: [PATCH 606/676] Updated libraries --- pubspec.lock | 144 +++++++++++++++++++++------------------------------ pubspec.yaml | 6 +-- 2 files changed, 63 insertions(+), 87 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 4c0330d..b196e63 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,10 +29,10 @@ packages: dependency: transitive description: name: archive - sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d url: "https://pub.dev" source: hosted - version: "3.4.10" + version: "3.6.1" args: dependency: transitive description: @@ -105,14 +105,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" - convert: - dependency: transitive - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" crypto: dependency: transitive description: @@ -213,10 +205,10 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: "2b7c1f5d867da9a054661641c8f499c55c47c39acccb97b3bc673f5fa9a39e74" + sha256: d0f0d49112f2f4b192481c16d05b6418bd7820e021e265a3c22db98acf7ed7fb url: "https://pub.dev" source: hosted - version: "0.67.0" + version: "0.68.0" flutter: dependency: "direct main" description: flutter @@ -298,10 +290,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" + sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "4.0.0" flutter_localizations: dependency: "direct main" description: flutter @@ -311,10 +303,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "9921f9deda326f8a885e202b1e35237eadfc1345239a0f6f0f1ff287e047547f" + sha256: ff76a9300a06ad1f2b394e54c0b4beaaf6a95f95c98540c918b870221499bb10 url: "https://pub.dev" source: hosted - version: "0.7.1" + version: "0.7.2" flutter_native_splash: dependency: "direct dev" description: @@ -377,66 +369,58 @@ packages: dependency: transitive description: name: image - sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" + sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" url: "https://pub.dev" source: hosted - version: "4.1.7" + version: "4.2.0" intl: dependency: "direct main" description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.18.1" - js: - dependency: transitive - description: - name: js - sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf - url: "https://pub.dev" - source: hosted - version: "0.7.1" + version: "0.19.0" json_annotation: dependency: transitive description: name: json_annotation - sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" url: "https://pub.dev" source: hosted - version: "4.8.1" + version: "4.9.0" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.4" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.3" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: name: lints - sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "4.0.0" list_counter: dependency: transitive description: @@ -473,10 +457,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.0" nested: dependency: transitive description: @@ -489,10 +473,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "2c582551839386fa7ddbc7770658be7c0f87f388a4bff72066478f597c34d17f" + sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "8.0.0" package_info_plus_platform_interface: dependency: transitive description: @@ -569,10 +553,10 @@ packages: dependency: transitive description: name: platform - sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" plugin_platform_interface: dependency: transitive description: @@ -581,14 +565,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: "79fbafed02cfdbe85ef3fd06c7f4bc2cbcba0177e61b765264853d4253b21744" - url: "https://pub.dev" - source: hosted - version: "3.9.0" provider: dependency: "direct main" description: @@ -617,18 +593,18 @@ packages: dependency: transitive description: name: sentry - sha256: "961630a4dba41cebd692612421fd3805a991ebd8ef4a8d84a6c179e6b89eaf22" + sha256: fd1fbfe860c05f5c52820ec4dbf2b6473789e83ead26cfc18bca4fe80bf3f008 url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.2.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "705da7adfcd1fb23fc8720b6e222f5e03d53f1d020cd635586c319ee323366b4" + sha256: c64f0aec5332bec87083b61514d1b6b29e435b9045d03ce1575861192b9a5680 url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.2.0" shared_preferences: dependency: "direct main" description: @@ -641,18 +617,18 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" + sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" + sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" url: "https://pub.dev" source: hosted - version: "2.3.5" + version: "2.4.0" shared_preferences_linux: dependency: transitive description: @@ -710,10 +686,10 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "5ce2e1a15e822c3b4bfb5400455775e421da7098eed8adc8f26298ada7c9308c" + sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.3+1" sqflite_common: dependency: transitive description: @@ -734,18 +710,18 @@ packages: dependency: transitive description: name: sqlite3 - sha256: "1abbeb84bf2b1a10e5e1138c913123c8aa9d83cd64e5f9a0dd847b3c83063202" + sha256: b384f598b813b347c5a7e5ffad82cbaff1bec3d1561af267041e66f6f0899295 url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.3" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: fb2a106a2ea6042fe57de2c47074cc31539a941819c91e105b864744605da3f5 + sha256: "62bbb4073edbcdf53f40c80775f33eea01d301b7b81417e5b3fb7395416258c1" url: "https://pub.dev" source: hosted - version: "0.5.21" + version: "0.5.24" stack_trace: dependency: transitive description: @@ -798,10 +774,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" timezone: dependency: "direct main" description: @@ -830,26 +806,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" url: "https://pub.dev" source: hosted - version: "6.2.6" + version: "6.3.0" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775" + sha256: ceb2625f0c24ade6ef6778d1de0b2e44f2db71fded235eb52295247feba8c5cf url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.3" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" + sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89" url: "https://pub.dev" source: hosted - version: "6.2.5" + version: "6.3.0" url_launcher_linux: dependency: transitive description: @@ -862,10 +838,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.2.0" url_launcher_platform_interface: dependency: transitive description: @@ -934,10 +910,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.1" web: dependency: transitive description: @@ -950,10 +926,10 @@ packages: dependency: transitive description: name: win32 - sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a" + sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "5.5.1" win32_registry: dependency: transitive description: @@ -966,10 +942,10 @@ packages: dependency: "direct main" description: name: window_manager - sha256: b3c895bdf936c77b83c5254bec2e6b3f066710c1f89c38b20b8acc382b525494 + sha256: "8699323b30da4cdbe2aa2e7c9de567a6abd8a97d9a5c850a3c86dcd0b34bbfbf" url: "https://pub.dev" source: hosted - version: "0.3.8" + version: "0.3.9" xdg_directories: dependency: transitive description: @@ -995,5 +971,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.0 <4.0.0" - flutter: ">=3.19.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index c90cb23..f2b0e49 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,14 +41,14 @@ dependencies: intl: any provider: ^6.1.1 sqflite: ^2.3.0 - package_info_plus: ^7.0.0 + package_info_plus: ^8.0.0 flutter_displaymode: ^0.6.0 dynamic_color: ^1.6.8 animations: ^2.0.10 device_info_plus: ^10.1.0 uuid: ^4.2.1 expandable: ^5.0.1 - fl_chart: ^0.67.0 + fl_chart: ^0.68.0 flutter_svg: ^2.0.9 percent_indicator: ^4.2.3 store_checker: ^1.4.0 @@ -81,7 +81,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^3.0.1 + flutter_lints: ^4.0.0 flutter_launcher_icons: ^0.13.1 flutter_native_splash: ^2.3.8 From 1dd23906c3203036a325f269695c175d18debf30 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 17 Jun 2024 13:28:12 +0200 Subject: [PATCH 607/676] Added options to copy to clipboard on log details --- lib/l10n/app_en.arb | 5 +- lib/l10n/app_es.arb | 5 +- .../logs/details/log_details_screen.dart | 15 ++- lib/screens/logs/details/log_list_tile.dart | 95 ++++++++++--------- 4 files changed, 68 insertions(+), 52 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 93b08af..3348119 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -791,5 +791,8 @@ "clientDisallowedSuccessfully": "Client disallowed successfully", "changesNotSaved": "Changes could not be saved", "allowingClient": "Allowing client...", - "disallowingClient": "Disallowing client..." + "disallowingClient": "Disallowing client...", + "clientIpCopied": "Client IP copied to the clipboard", + "clientNameCopied": "Client name copied to the clipboard", + "dnsServerAddressCopied": "DNS server address copied to the clipboard" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index e777f48..811ee22 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -791,5 +791,8 @@ "clientDisallowedSuccessfully": "Cliente no permitido correctamente", "changesNotSaved": "Los cambios no han podido ser guardados", "allowingClient": "Permitiendo cliente...", - "disallowingClient": "No permitiendo cliente..." + "disallowingClient": "No permitiendo cliente...", + "clientIpCopied": "Dirección IP del cliente copiada al portapapeles", + "clientNameCopied": "Nombre del cliente copiado al portapapeles", + "dnsServerAddressCopied": "Dirección del servidor DNS copiada al portapapeles" } \ No newline at end of file diff --git a/lib/screens/logs/details/log_details_screen.dart b/lib/screens/logs/details/log_details_screen.dart index 0c35f35..5d78823 100644 --- a/lib/screens/logs/details/log_details_screen.dart +++ b/lib/screens/logs/details/log_details_screen.dart @@ -1,5 +1,6 @@ // ignore_for_file: use_build_context_synchronously +import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -275,10 +276,11 @@ class _Content extends StatelessWidget { subtitle: convertTimestampLocalTimezone(log.time, 'HH:mm:ss') ), SectionLabel(label: AppLocalizations.of(context)!.request), - LogListTile( + if (log.question.name != null) LogListTile( icon: Icons.domain_rounded, title: AppLocalizations.of(context)!.domain, - subtitle: log.question.name + subtitle: log.question.name, + onTap: () => copyToClipboard(value: log.question.name!, successMessage: AppLocalizations.of(context)!.domainCopiedClipboard), ), LogListTile( icon: Icons.category_rounded, @@ -294,7 +296,8 @@ class _Content extends StatelessWidget { if (log.upstream != null && log.upstream != '') LogListTile( icon: Icons.dns_rounded, title: AppLocalizations.of(context)!.dnsServer, - subtitle: log.upstream + subtitle: log.upstream, + onTap: () => copyToClipboard(value: log.upstream!, successMessage: AppLocalizations.of(context)!.dnsServerAddressCopied) ), LogListTile( icon: Icons.timer_rounded, @@ -310,12 +313,14 @@ class _Content extends StatelessWidget { LogListTile( icon: Icons.smartphone_rounded, title: AppLocalizations.of(context)!.deviceIp, - subtitle: log.client + subtitle: log.client, + onTap: () => copyToClipboard(value: log.client, successMessage: AppLocalizations.of(context)!.clientIpCopied), ), if (log.clientInfo != null && log.clientInfo!.name != '') LogListTile( icon: Icons.abc_rounded, title: AppLocalizations.of(context)!.deviceName, - subtitle: log.clientInfo!.name + subtitle: log.clientInfo!.name, + onTap: () => copyToClipboard(value: log.clientInfo!.name, successMessage: AppLocalizations.of(context)!.clientNameCopied), ), if (log.rules.isNotEmpty) ...[ SectionLabel(label: AppLocalizations.of(context)!.rules), diff --git a/lib/screens/logs/details/log_list_tile.dart b/lib/screens/logs/details/log_list_tile.dart index c45f0f8..15edd6b 100644 --- a/lib/screens/logs/details/log_list_tile.dart +++ b/lib/screens/logs/details/log_list_tile.dart @@ -6,63 +6,68 @@ class LogListTile extends StatelessWidget { final String? subtitle; final Widget? subtitleWidget; final Widget? trailing; + final void Function()? onTap; const LogListTile({ - Key? key, + super.key, required this.icon, required this.title, this.subtitle, this.subtitleWidget, this.trailing, - }) : super(key: key); + this.onTap, + }); @override Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Row( - children: [ - Icon( - icon, - size: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(width: 16), - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 3), - subtitleWidget ?? Text( - subtitle!, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).listTileTheme.textColor, - ), - ) - ], + return InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + children: [ + Icon( + icon, + size: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - ), - ], + const SizedBox(width: 16), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 3), + subtitleWidget ?? Text( + subtitle!, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).listTileTheme.textColor, + ), + ) + ], + ), + ), + ], + ), ), - ), - if (trailing != null) ...[ - const SizedBox(width: 16), - trailing! - ] - ], + if (trailing != null) ...[ + const SizedBox(width: 16), + trailing! + ] + ], + ), ), ); } From 8801428167f5bc1c58f395399e1419ad2ed8038a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 17 Jun 2024 13:55:54 +0200 Subject: [PATCH 608/676] Fixed missing language --- lib/screens/settings/server_info/server_info.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/settings/server_info/server_info.dart b/lib/screens/settings/server_info/server_info.dart index 9757497..8f5c927 100644 --- a/lib/screens/settings/server_info/server_info.dart +++ b/lib/screens/settings/server_info/server_info.dart @@ -138,7 +138,7 @@ class _ServerInformationState extends State { title: AppLocalizations.of(context)!.serverVersion, subtitle: serverInfo.data!.version, ), - CustomListTile( + if (serverInfo.data!.language != "") CustomListTile( title: AppLocalizations.of(context)!.serverLanguage, subtitle: serverInfo.data!.language, ), From 4dd77a39d8409bfcec3fe4de5663dcd61c59284c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 17 Jun 2024 13:56:02 +0200 Subject: [PATCH 609/676] Fixed wrong colors --- lib/config/theme.dart | 12 ++++++++++++ pubspec.yaml | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/config/theme.dart b/lib/config/theme.dart index 8a8aadf..fce953a 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -15,6 +15,15 @@ ThemeData lightTheme(ColorScheme? dynamicColorScheme) => ThemeData( textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), ), + cardTheme: CardTheme( + surfaceTintColor: dynamicColorScheme?.surfaceTint + ), + popupMenuTheme: PopupMenuThemeData( + surfaceTintColor: dynamicColorScheme?.surfaceTint + ), + navigationBarTheme: NavigationBarThemeData( + surfaceTintColor: dynamicColorScheme?.surfaceTint + ) ); ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( @@ -33,6 +42,9 @@ ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( textColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), iconColor: dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), ), + cardTheme: CardTheme( + surfaceTintColor: dynamicColorScheme?.surfaceTint + ) ); ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( diff --git a/pubspec.yaml b/pubspec.yaml index f2b0e49..1b1c059 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -43,7 +43,7 @@ dependencies: sqflite: ^2.3.0 package_info_plus: ^8.0.0 flutter_displaymode: ^0.6.0 - dynamic_color: ^1.6.8 + dynamic_color: ^1.7.0 animations: ^2.0.10 device_info_plus: ^10.1.0 uuid: ^4.2.1 From ad6e75b6fbace41231884957c06c4a8e7947fb5d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 17 Jun 2024 13:56:59 +0200 Subject: [PATCH 610/676] Fixed on dark theme --- lib/config/theme.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/config/theme.dart b/lib/config/theme.dart index fce953a..fc81165 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -44,6 +44,12 @@ ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( ), cardTheme: CardTheme( surfaceTintColor: dynamicColorScheme?.surfaceTint + ), + popupMenuTheme: PopupMenuThemeData( + surfaceTintColor: dynamicColorScheme?.surfaceTint + ), + navigationBarTheme: NavigationBarThemeData( + surfaceTintColor: dynamicColorScheme?.surfaceTint ) ); From d34d88172202cd6207c25f0110290541622e2bfa Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 17 Jun 2024 17:16:08 +0200 Subject: [PATCH 611/676] Added predictive navigation --- lib/config/theme.dart | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/config/theme.dart b/lib/config/theme.dart index fc81165..a9ffa71 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -23,6 +23,11 @@ ThemeData lightTheme(ColorScheme? dynamicColorScheme) => ThemeData( ), navigationBarTheme: NavigationBarThemeData( surfaceTintColor: dynamicColorScheme?.surfaceTint + ), + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + } ) ); @@ -50,6 +55,11 @@ ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( ), navigationBarTheme: NavigationBarThemeData( surfaceTintColor: dynamicColorScheme?.surfaceTint + ), + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + } ) ); @@ -69,6 +79,11 @@ ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( iconColor: Color.fromRGBO(117, 117, 117, 1), ), brightness: Brightness.light, + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + } + ) ); ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( @@ -90,4 +105,9 @@ ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( iconColor: Color.fromRGBO(187, 187, 187, 1), ), brightness: Brightness.dark, + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + } + ) ); \ No newline at end of file From b981f4a5cb810b7cd2fafd90d42454d8c955fb3e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 17 Jun 2024 17:17:13 +0200 Subject: [PATCH 612/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 1b1c059..1a8cda0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.17.1+137 +version: 2.18.0-beta.1+138 environment: sdk: '>=2.18.1 <3.0.0' From 27b0c3a3a02a17426c956266a96a957587b458f2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 18 Jun 2024 01:30:54 +0200 Subject: [PATCH 613/676] Updated macOS stuff --- macos/Podfile.lock | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index ead0b21..96c9ba0 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -8,31 +8,32 @@ PODS: - FlutterMacOS - screen_retriever (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.21.0): - - SentryPrivate (= 8.21.0) - - sentry_flutter (8.0.0): + - Sentry/HybridSDK (8.25.2) + - sentry_flutter (8.2.0): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.21.0) - - SentryPrivate (8.21.0) + - Sentry/HybridSDK (= 8.25.2) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - sqflite (0.0.3): - Flutter - FlutterMacOS - - "sqlite3 (3.45.3+1)": - - "sqlite3/common (= 3.45.3+1)" - - "sqlite3/common (3.45.3+1)" - - "sqlite3/fts5 (3.45.3+1)": + - "sqlite3 (3.46.0+1)": + - "sqlite3/common (= 3.46.0+1)" + - "sqlite3/common (3.46.0+1)" + - "sqlite3/dbstatvtab (3.46.0+1)": - sqlite3/common - - "sqlite3/perf-threadsafe (3.45.3+1)": + - "sqlite3/fts5 (3.46.0+1)": - sqlite3/common - - "sqlite3/rtree (3.45.3+1)": + - "sqlite3/perf-threadsafe (3.46.0+1)": + - sqlite3/common + - "sqlite3/rtree (3.46.0+1)": - sqlite3/common - sqlite3_flutter_libs (0.0.1): - FlutterMacOS - - "sqlite3 (~> 3.45.3+1)" + - "sqlite3 (~> 3.46.0+1)" + - sqlite3/dbstatvtab - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree @@ -57,7 +58,6 @@ DEPENDENCIES: SPEC REPOS: trunk: - Sentry - - SentryPrivate - sqlite3 EXTERNAL SOURCES: @@ -90,14 +90,13 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 - Sentry: ebc12276bd17613a114ab359074096b6b3725203 - sentry_flutter: 4ce59806771a82cc2d2a4657b320c9801530db62 - SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe - shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 + Sentry: 51b056d96914a741f63eca774d118678b1eb05a1 + sentry_flutter: e8397d13e297a5d4b6be8a752e33140b21c5cc97 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec - sqlite3: 02d1f07eaaa01f80a1c16b4b31dfcbb3345ee01a - sqlite3_flutter_libs: 8d204ef443cf0d5c1c8b058044eab53f3943a9c5 - url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 + sqlite3: 292c3e1bfe89f64e51ea7fc7dab9182a017c8630 + sqlite3_flutter_libs: 5ca46c1a04eddfbeeb5b16566164aa7ad1616e7b + url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 From 9a747dd2fb5c49707637024bf4f250d652a27820 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 18 Jun 2024 01:31:21 +0200 Subject: [PATCH 614/676] Added added clients list to client filters on logs --- lib/screens/logs/filters/clients_modal.dart | 163 ++++++++++++-------- 1 file changed, 96 insertions(+), 67 deletions(-) diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index ca15219..5e5dbc6 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:segmented_button_slide/segmented_button_slide.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; @@ -14,10 +15,12 @@ import 'package:adguard_home_manager/providers/logs_provider.dart'; class _ClientLog { final String ip; final String? name; + final List? ids; const _ClientLog({ required this.ip, - required this.name + required this.name, + this.ids, }); } @@ -38,6 +41,7 @@ class ClientsModal extends StatefulWidget { class _ClientsModalState extends State { List<_ClientLog> _filteredClients = []; final _searchController = TextEditingController(); + int _selectedList = 0; @override void initState() { @@ -65,22 +69,46 @@ class _ClientsModalState extends State { final logsProvider = Provider.of(context); final statusProvider = Provider.of(context); - void onSearch(String value) { - final filtered = clientsProvider.clients!.autoClients.map((e) { - String? name; - try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(e.ip)).name; - } catch (e) { - // ---- // - } - return _ClientLog( - ip: e.ip, - name: name - ); - }).where( - (c) => c.ip.contains(value.toLowerCase()) || (c.name != null && c.name!.toLowerCase().contains(value.toLowerCase())) - ).toList(); - setState(() => _filteredClients = filtered); + void onSearch({required String value, int? selectedList}) { + if ((selectedList ?? _selectedList) == 1) { + final filtered = clientsProvider.clients!.clients.map((e) { + String? name; + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(e.ids[0])).name; + } catch (e) { + // ---- // + } + return _ClientLog( + ip: e.ids[0], + name: name, + ids: e.ids + ); + }).where( + (c) => c.ip.contains(value.toLowerCase()) || (c.name != null && c.name!.toLowerCase().contains(value.toLowerCase())) + ).toList(); + setState(() => _filteredClients = filtered); + } + else { + final filtered = clientsProvider.clients!.autoClients.map((e) { + String? name; + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(e.ip)).name; + } catch (e) { + // ---- // + } + return _ClientLog( + ip: e.ip, + name: name + ); + }).where( + (c) => c.ip.contains(value.toLowerCase()) || (c.name != null && c.name!.toLowerCase().contains(value.toLowerCase())) + ).toList(); + setState(() => _filteredClients = filtered); + } + } + + void onListChange(int list) { + onSearch(value: _searchController.text, selectedList: list); } if (widget.dialog == true) { @@ -115,7 +143,7 @@ class _ClientsModalState extends State { _SearchField( controller: _searchController, onClear: () => setState(() => _searchController.text = ""), - onSearch: onSearch + onSearch: (v) => onSearch(value: v) ), Card( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), @@ -135,30 +163,34 @@ class _ClientsModalState extends State { ), ), ), - CustomCheckboxListTile( - padding: const EdgeInsets.only( - left: 24, - top: 8, - right: 12, - bottom: 8 + Padding( + padding: const EdgeInsets.all(16), + child: SegmentedButtonSlide( + entries: [ + SegmentedButtonSlideEntry(icon: Icons.devices, label: AppLocalizations.of(context)!.activeClients), + SegmentedButtonSlideEntry(icon: Icons.add_rounded, label: AppLocalizations.of(context)!.added), + ], + selectedEntry: _selectedList, + onChange: (v) { + onListChange(v); + setState(() => _selectedList = v); + }, + colors: SegmentedButtonSlideColors( + barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), + backgroundSelectedColor: Theme.of(context).colorScheme.primary, + foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, + foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, + hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), - value: logsProvider.selectedClients.length == clientsProvider.clients!.autoClients.length, - onChanged: (v) { - if (v == true) { - logsProvider.setSelectedClients(clientsProvider.clients!.autoClients.map((e) => e.ip).toList()); - } - else { - logsProvider.setSelectedClients([]); - } - }, - title: AppLocalizations.of(context)!.selectAll ), ListView.builder( primary: false, shrinkWrap: true, itemCount: _filteredClients.length, itemBuilder: (context, index) => _ListItem( - label: _filteredClients[index].ip, + title: _filteredClients[index].ip, + subtitle: _selectedList == 0 ? _filteredClients[index].name : _filteredClients[index].ids?.join(", "), checkboxActive: logsProvider.selectedClients.contains(_filteredClients[index].ip), onChanged: (isSelected) { if (isSelected == true) { @@ -196,7 +228,7 @@ class _ClientsModalState extends State { _SearchField( controller: _searchController, onClear: () => setState(() => _searchController.text = ""), - onSearch: onSearch + onSearch: (v) => onSearch(value: v) ), Card( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), @@ -216,30 +248,34 @@ class _ClientsModalState extends State { ), ), ), - CustomCheckboxListTile( - padding: const EdgeInsets.only( - left: 24, - top: 8, - right: 12, - bottom: 8 + Padding( + padding: const EdgeInsets.all(16), + child: SegmentedButtonSlide( + entries: [ + SegmentedButtonSlideEntry(icon: Icons.devices, label: AppLocalizations.of(context)!.activeClients), + SegmentedButtonSlideEntry(icon: Icons.add_rounded, label: AppLocalizations.of(context)!.added), + ], + selectedEntry: _selectedList, + onChange: (v) { + onListChange(v); + setState(() => _selectedList = v); + }, + colors: SegmentedButtonSlideColors( + barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), + backgroundSelectedColor: Theme.of(context).colorScheme.primary, + foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, + foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, + hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), - value: logsProvider.selectedClients.length == clientsProvider.clients!.autoClients.length, - onChanged: (v) { - if (v == true) { - logsProvider.setSelectedClients(clientsProvider.clients!.autoClients.map((e) => e.ip).toList()); - } - else { - logsProvider.setSelectedClients([]); - } - }, - title: AppLocalizations.of(context)!.selectAll ), ListView.builder( shrinkWrap: true, primary: false, itemCount: _filteredClients.length, itemBuilder: (context, index) => _ListItem( - label: _filteredClients[index].ip, + title: _selectedList == 0 ? _filteredClients[index].ip : _filteredClients[index].name ?? "", + subtitle: _selectedList == 0 ? _filteredClients[index].name : _filteredClients[index].ids?.join(", "), checkboxActive: logsProvider.selectedClients.contains(_filteredClients[index].ip), onChanged: (isSelected) { if (isSelected == true) { @@ -257,7 +293,7 @@ class _ClientsModalState extends State { } } ) - ) + ), ] ), ); @@ -309,32 +345,25 @@ class _SearchField extends StatelessWidget { } class _ListItem extends StatelessWidget { - final String label; + final String title; + final String? subtitle; final bool checkboxActive; final void Function(bool) onChanged; const _ListItem({ - required this.label, + required this.title, + this.subtitle, required this.checkboxActive, required this.onChanged, }); @override Widget build(BuildContext context) { - final statusProvider = Provider.of(context); - - String? name; - try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(label)).name; - } catch (e) { - // ---- // - } - return CustomCheckboxListTile( value: checkboxActive, onChanged: (v) => onChanged(v), - title: label, - subtitle: name, + title: title, + subtitle: subtitle, padding: const EdgeInsets.only( left: 24, top: 8, From 4f903d8e4c5718135d5499c604539bd88b569f9e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 18 Jun 2024 01:32:04 +0200 Subject: [PATCH 615/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 1a8cda0..c9259b7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.18.0-beta.1+138 +version: 2.18.0-beta.2+139 environment: sdk: '>=2.18.1 <3.0.0' From cce54c8ba5567a4325744c1deaea86744ed34097 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 18 Jun 2024 21:50:38 +0200 Subject: [PATCH 616/676] Check if it's not ip to apply "" --- lib/functions/is_ip.dart | 10 ++++++++++ lib/screens/logs/filters/clients_modal.dart | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 lib/functions/is_ip.dart diff --git a/lib/functions/is_ip.dart b/lib/functions/is_ip.dart new file mode 100644 index 0000000..667bf0b --- /dev/null +++ b/lib/functions/is_ip.dart @@ -0,0 +1,10 @@ +bool isIpAddress(String value) { + final ipv4Regexp = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$'); + final ipv6Regexp = RegExp(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]))'); + if (ipv4Regexp.hasMatch(value) || ipv6Regexp.hasMatch(value)) { + return true; + } + else { + return false; + } +} \ No newline at end of file diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index 5e5dbc6..ea15c41 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -6,6 +6,7 @@ import 'package:segmented_button_slide/segmented_button_slide.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; +import 'package:adguard_home_manager/functions/is_ip.dart'; import 'package:adguard_home_manager/widgets/list_bottom_sheet.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; @@ -79,9 +80,9 @@ class _ClientsModalState extends State { // ---- // } return _ClientLog( - ip: e.ids[0], + ip: isIpAddress(e.ids[0]) ? e.ids[0] : '"${e.ids[0]}"', name: name, - ids: e.ids + ids: e.ids.map((i) => isIpAddress(i) ? i : '"$i"').toList() ); }).where( (c) => c.ip.contains(value.toLowerCase()) || (c.name != null && c.name!.toLowerCase().contains(value.toLowerCase())) From a8cbed5ca09551c3ee016b5f1160e3a74d76ed70 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 21 Jun 2024 02:32:23 +0200 Subject: [PATCH 617/676] Added search button to added clients --- lib/l10n/app_en.arb | 3 +- lib/l10n/app_es.arb | 3 +- lib/screens/logs/filters/clients_modal.dart | 56 +++++++++++++++------ 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 3348119..39ec621 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -794,5 +794,6 @@ "disallowingClient": "Disallowing client...", "clientIpCopied": "Client IP copied to the clipboard", "clientNameCopied": "Client name copied to the clipboard", - "dnsServerAddressCopied": "DNS server address copied to the clipboard" + "dnsServerAddressCopied": "DNS server address copied to the clipboard", + "select": "Select" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 811ee22..399f429 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -794,5 +794,6 @@ "disallowingClient": "No permitiendo cliente...", "clientIpCopied": "Dirección IP del cliente copiada al portapapeles", "clientNameCopied": "Nombre del cliente copiado al portapapeles", - "dnsServerAddressCopied": "Dirección del servidor DNS copiada al portapapeles" + "dnsServerAddressCopied": "Dirección del servidor DNS copiada al portapapeles", + "select": "Seleccionar" } \ No newline at end of file diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index ea15c41..ac7b384 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -8,6 +8,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; import 'package:adguard_home_manager/functions/is_ip.dart'; import 'package:adguard_home_manager/widgets/list_bottom_sheet.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/clients_provider.dart'; @@ -80,9 +81,9 @@ class _ClientsModalState extends State { // ---- // } return _ClientLog( - ip: isIpAddress(e.ids[0]) ? e.ids[0] : '"${e.ids[0]}"', + ip: e.ids[0], name: name, - ids: e.ids.map((i) => isIpAddress(i) ? i : '"$i"').toList() + ids: e.ids ); }).where( (c) => c.ip.contains(value.toLowerCase()) || (c.name != null && c.name!.toLowerCase().contains(value.toLowerCase())) @@ -112,6 +113,13 @@ class _ClientsModalState extends State { onSearch(value: _searchController.text, selectedList: list); } + void searchAddedClient(_ClientLog client) { + final notIps = client.ids?.where((e) => isIpAddress(e) == false).toList(); + if (notIps == null) return; + logsProvider.setSearchText('"${notIps[0]}"'); + Navigator.of(context).pop(); + } + if (widget.dialog == true) { return Dialog( child: ConstrainedBox( @@ -193,6 +201,8 @@ class _ClientsModalState extends State { title: _filteredClients[index].ip, subtitle: _selectedList == 0 ? _filteredClients[index].name : _filteredClients[index].ids?.join(", "), checkboxActive: logsProvider.selectedClients.contains(_filteredClients[index].ip), + isAddedClient: _selectedList == 0, + onSearchAddedClient: () => searchAddedClient(_filteredClients[index]), onChanged: (isSelected) { if (isSelected == true) { logsProvider.setSelectedClients([ @@ -278,6 +288,8 @@ class _ClientsModalState extends State { title: _selectedList == 0 ? _filteredClients[index].ip : _filteredClients[index].name ?? "", subtitle: _selectedList == 0 ? _filteredClients[index].name : _filteredClients[index].ids?.join(", "), checkboxActive: logsProvider.selectedClients.contains(_filteredClients[index].ip), + isAddedClient: _selectedList == 1, + onSearchAddedClient: () => searchAddedClient(_filteredClients[index]), onChanged: (isSelected) { if (isSelected == true) { logsProvider.setSelectedClients([ @@ -350,27 +362,43 @@ class _ListItem extends StatelessWidget { final String? subtitle; final bool checkboxActive; final void Function(bool) onChanged; + final bool isAddedClient; + final void Function() onSearchAddedClient; const _ListItem({ required this.title, this.subtitle, required this.checkboxActive, required this.onChanged, + required this.isAddedClient, + required this.onSearchAddedClient, }); @override Widget build(BuildContext context) { - return CustomCheckboxListTile( - value: checkboxActive, - onChanged: (v) => onChanged(v), - title: title, - subtitle: subtitle, - padding: const EdgeInsets.only( - left: 24, - top: 8, - right: 12, - bottom: 8 - ), - ); + if (isAddedClient == true) { + return CustomListTile( + title: title, + subtitle: subtitle, + trailing: TextButton( + onPressed: onSearchAddedClient, + child: Text(AppLocalizations.of(context)!.select) + ), + ); + } + else { + return CustomCheckboxListTile( + value: checkboxActive, + onChanged: (v) => onChanged(v), + title: title, + subtitle: subtitle, + padding: const EdgeInsets.only( + left: 24, + top: 8, + right: 12, + bottom: 8 + ), + ); + } } } \ No newline at end of file From b685010a03f95545c84d32ffaf15d7b105d8230a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Fri, 21 Jun 2024 15:31:54 +0200 Subject: [PATCH 618/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index c9259b7..9779159 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.18.0-beta.2+139 +version: 2.18.0-beta.3+140 environment: sdk: '>=2.18.1 <3.0.0' From f8f18be7230e10ac62b32bff7359f13a283a6f7f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 24 Jun 2024 03:00:02 +0200 Subject: [PATCH 619/676] Fix windows installer builder --- windows/innosetup_installer_builder.iss | 1 + 1 file changed, 1 insertion(+) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index 53b8fc7..b2a93ce 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -40,6 +40,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ Source: "..\build\windows\x64\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\dynamic_color_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\screen_retriever_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion From 0eae951eedae7dd52cfe322c2d6f51a5f5182551 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 24 Jun 2024 03:02:33 +0200 Subject: [PATCH 620/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 9779159..a12e5aa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.18.0-beta.3+140 +version: 2.18.0+141 environment: sdk: '>=2.18.1 <3.0.0' From be3e76eafca562795580d3da7252d8b45c1f998b Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Sep 2024 17:16:07 +0200 Subject: [PATCH 621/676] Updated libraries --- .../modals/custom_rules/add_custom_rule.dart | 14 +- lib/screens/logs/filters/clients_modal.dart | 25 ++- lib/widgets/add_server/add_server_modal.dart | 14 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 196 +++++++++--------- pubspec.yaml | 6 +- 6 files changed, 142 insertions(+), 115 deletions(-) diff --git a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart index 7e6e604..b528c02 100644 --- a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart +++ b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart @@ -276,16 +276,22 @@ class _CustomRuleEditor extends StatelessWidget { colors: SegmentedButtonSlideColors( barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), backgroundSelectedColor: Theme.of(context).colorScheme.primary, - foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, - foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, - hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, ), textOverflow: TextOverflow.ellipsis, - fontSize: 14, height: 40, margin: const EdgeInsets.symmetric( horizontal: 24, ), + selectedTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onPrimary, + fontWeight: FontWeight.w700 + ), + unselectedTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + hoverTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), Container(height: 20), Material( diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index ac7b384..403f098 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -187,9 +187,15 @@ class _ClientsModalState extends State { colors: SegmentedButtonSlideColors( barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), backgroundSelectedColor: Theme.of(context).colorScheme.primary, - foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, - foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, - hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, + ), + selectedTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onPrimary, + ), + unselectedTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + hoverTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ), @@ -274,9 +280,16 @@ class _ClientsModalState extends State { colors: SegmentedButtonSlideColors( barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), backgroundSelectedColor: Theme.of(context).colorScheme.primary, - foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, - foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, - hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, + ), + selectedTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onPrimary, + fontWeight: FontWeight.w700 + ), + unselectedTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + hoverTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ), diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index ac7d4a1..e6888da 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -419,16 +419,22 @@ class _AddServerModalState extends State { colors: SegmentedButtonSlideColors( barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), backgroundSelectedColor: Theme.of(context).colorScheme.primary, - foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, - foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, - hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, ), textOverflow: TextOverflow.ellipsis, - fontSize: 14, height: 40, margin: const EdgeInsets.symmetric( horizontal: 24, ), + selectedTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onPrimary, + fontWeight: FontWeight.w700 + ), + unselectedTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + hoverTextStyle: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), Card( margin: const EdgeInsets.only( diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 28ea475..cf249ab 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -13,6 +13,7 @@ import sentry_flutter import shared_preferences_foundation import sqflite import sqlite3_flutter_libs +import store_checker import url_launcher_macos import window_manager @@ -25,6 +26,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) + StoreCheckerPlugin.register(with: registry.registrar(forPlugin: "StoreCheckerPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index b196e63..235ec9f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: ansicolor - sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880" + sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" archive: dependency: transitive description: @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" csslib: dependency: transitive description: @@ -133,18 +133,18 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91 + sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 url: "https://pub.dev" source: hosted - version: "10.1.0" + version: "10.1.2" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba" url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" dynamic_color: dependency: "direct main" description: @@ -181,10 +181,10 @@ packages: dependency: transitive description: name: ffi - sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" file: dependency: transitive description: @@ -205,10 +205,10 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: d0f0d49112f2f4b192481c16d05b6418bd7820e021e265a3c22db98acf7ed7fb + sha256: "94307bef3a324a0d329d3ab77b2f0c6e5ed739185ffc029ed28c0f9b019ea7ef" url: "https://pub.dev" source: hosted - version: "0.68.0" + version: "0.69.0" flutter: dependency: "direct main" description: flutter @@ -218,42 +218,42 @@ packages: dependency: "direct main" description: name: flutter_custom_tabs - sha256: "961fe962ae55e9e41097c34e68c6d7d2de10e9a71034f83834919e31a891e728" + sha256: "34167bd15fa3479855c011f868e0789c9569c12b64358ca7250accc5a24c3312" url: "https://pub.dev" source: hosted - version: "2.0.0+1" + version: "2.1.0" flutter_custom_tabs_android: dependency: transitive description: name: flutter_custom_tabs_android - sha256: "5701a3e38117dfc59e5fa9e84a29eea9203e0062de7be56d1f775845c34456d9" + sha256: cf06fde8c002f326dc6cbf69ee3f97c3feead4436229da02d2e2aa39d5a5dbf4 url: "https://pub.dev" source: hosted - version: "2.0.0+1" + version: "2.1.0" flutter_custom_tabs_ios: dependency: transitive description: name: flutter_custom_tabs_ios - sha256: b29f687f7f366159d37347f888369fcd1259adac8ca6c7f07d356a80b091e08a + sha256: ef2de533bc45fb84fefc3854bc8b1e43001671c6bc6bc55faa57942eecd3f70a url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" flutter_custom_tabs_platform_interface: dependency: transitive description: name: flutter_custom_tabs_platform_interface - sha256: "13531a743486695d87b462b151801e11476b1b5a15274caec092420cc1943064" + sha256: e18e9b08f92582123bdb84fb6e4c91804b0579700fed6f887d32fd9a1e96a5d5 url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" flutter_custom_tabs_web: dependency: transitive description: name: flutter_custom_tabs_web - sha256: "3114b511d3942ed42c502cc57ad47eaef9622ac06dd036e2b21b19d8876f6498" + sha256: "08ae322b11e1972a233d057542279873d0f9d1d5f8159c2c741457239d9d562c" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" flutter_displaymode: dependency: "direct main" description: @@ -303,18 +303,18 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: ff76a9300a06ad1f2b394e54c0b4beaaf6a95f95c98540c918b870221499bb10 + sha256: a23c41ee57573e62fc2190a1f36a0480c4d90bde3a8a8d7126e5d5992fb53fb7 url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.3+1" flutter_native_splash: dependency: "direct dev" description: name: flutter_native_splash - sha256: edf39bcf4d74aca1eb2c1e43c3e445fd9f494013df7f0da752fefe72020eedc0 + sha256: aa06fec78de2190f3db4319dd60fdc8d12b2626e93ef9828633928c2dcaea840 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" flutter_reorderable_list: dependency: "direct main" description: @@ -353,10 +353,10 @@ packages: dependency: "direct main" description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" http_parser: dependency: transitive description: @@ -393,18 +393,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -449,18 +449,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" nested: dependency: transitive description: @@ -473,18 +473,18 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0 + sha256: a75164ade98cb7d24cfd0a13c6408927c6b217fa60dee5a7ff5c116a58f28918 url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.0.2" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e + sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" path: dependency: transitive description: @@ -521,10 +521,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" percent_indicator: dependency: "direct main" description: @@ -585,82 +585,82 @@ packages: dependency: "direct main" description: name: segmented_button_slide - sha256: "96d67344fa65f6b98a317d930bfd4e81e47c4f9e3e2ab1ee8925b55f72cded13" + sha256: d0563010c79a101340cfc127ee5a27c8c7d8640d5ef857a36e9d0b46bc01fed4 url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "2.0.0" sentry: dependency: transitive description: name: sentry - sha256: fd1fbfe860c05f5c52820ec4dbf2b6473789e83ead26cfc18bca4fe80bf3f008 + sha256: "1af8308298977259430d118ab25be8e1dda626cdefa1e6ce869073d530d39271" url: "https://pub.dev" source: hosted - version: "8.2.0" + version: "8.8.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: c64f0aec5332bec87083b61514d1b6b29e435b9045d03ce1575861192b9a5680 + sha256: "18fe4d125c2d529bd6127200f0d2895768266a8c60b4fb50b2086fd97e1a4ab2" url: "https://pub.dev" source: hosted - version: "8.2.0" + version: "8.8.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 + sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.2" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" + sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.2" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" + sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.5.2" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.2" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" sky_engine: dependency: transitive description: flutter @@ -694,10 +694,10 @@ packages: dependency: transitive description: name: sqflite_common - sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" + sha256: "7b41b6c3507854a159e24ae90a8e3e9cc01eb26a477c118d6dca065b5f55453e" url: "https://pub.dev" source: hosted - version: "2.5.4" + version: "2.5.4+2" sqflite_common_ffi: dependency: "direct main" description: @@ -710,10 +710,10 @@ packages: dependency: transitive description: name: sqlite3 - sha256: b384f598b813b347c5a7e5ffad82cbaff1bec3d1561af267041e66f6f0899295 + sha256: "45f168ae2213201b54e09429ed0c593dc2c88c924a1488d6f9c523a255d567cb" url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.4.6" sqlite3_flutter_libs: dependency: "direct main" description: @@ -734,10 +734,10 @@ packages: dependency: "direct main" description: name: store_checker - sha256: c9c1a93f11fa756fea23a2a08d7e54e84626a8d3c759cf49fc694a3a5afdc705 + sha256: "9e5841e4f922cc7f0283323ff3c78fd31ace14c22e988525d33355c35d7c815a" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.6.0" stream_channel: dependency: transitive description: @@ -758,10 +758,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255 url: "https://pub.dev" source: hosted - version: "3.1.0+1" + version: "3.2.0" term_glyph: dependency: transitive description: @@ -774,18 +774,18 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.2" timezone: dependency: "direct main" description: name: timezone - sha256: a6ccda4a69a442098b602c44e61a1e2b4bf6f5516e875bbf0f427d5df14745d5 + sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" url: "https://pub.dev" source: hosted - version: "0.9.3" + version: "0.9.4" typed_data: dependency: transitive description: @@ -814,26 +814,26 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: ceb2625f0c24ade6ef6778d1de0b2e44f2db71fded235eb52295247feba8c5cf + sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab url: "https://pub.dev" source: hosted - version: "6.3.3" + version: "6.3.10" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89" + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.2.0" url_launcher_macos: dependency: transitive description: @@ -854,26 +854,26 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" uuid: dependency: "direct main" description: name: uuid - sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" + sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77 url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.5.0" vector_graphics: dependency: transitive description: @@ -910,42 +910,42 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.2.5" web: dependency: transitive description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "1.0.0" win32: dependency: transitive description: name: win32 - sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 + sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a" url: "https://pub.dev" source: hosted - version: "5.5.1" + version: "5.5.4" win32_registry: dependency: transitive description: name: win32_registry - sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb" + sha256: "723b7f851e5724c55409bb3d5a32b203b3afe8587eaf5dafb93a5fed8ecda0d6" url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "1.1.4" window_manager: dependency: "direct main" description: name: window_manager - sha256: "8699323b30da4cdbe2aa2e7c9de567a6abd8a97d9a5c850a3c86dcd0b34bbfbf" + sha256: ab8b2a7f97543d3db2b506c9d875e637149d48ee0c6a5cb5f5fd6e0dac463792 url: "https://pub.dev" source: hosted - version: "0.3.9" + version: "0.4.2" xdg_directories: dependency: transitive description: @@ -971,5 +971,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.22.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index a12e5aa..150159a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,7 +48,7 @@ dependencies: device_info_plus: ^10.1.0 uuid: ^4.2.1 expandable: ^5.0.1 - fl_chart: ^0.68.0 + fl_chart: ^0.69.0 flutter_svg: ^2.0.9 percent_indicator: ^4.2.3 store_checker: ^1.4.0 @@ -64,13 +64,13 @@ dependencies: flutter_dotenv: ^5.1.0 flutter_reorderable_list: ^1.3.1 pie_chart: ^5.4.0 - segmented_button_slide: ^1.0.4 + segmented_button_slide: ^2.0.0 http: ^1.1.2 timezone: ^0.9.2 flutter_custom_tabs: ^2.0.0+1 url_launcher: ^6.2.4 shared_preferences: ^2.2.2 - window_manager: ^0.3.8 + window_manager: ^0.4.2 dev_dependencies: flutter_test: From 7991f29707bb54ae679b9af48994d4e2e5cb8ae0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Sep 2024 18:17:05 +0200 Subject: [PATCH 622/676] Added realtime logs --- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/providers/live_logs_provider.dart | 51 ++++++++++++ lib/screens/logs/live/live_logs_screen.dart | 89 +++++++++++++++++++++ lib/screens/logs/logs_list_appbar.dart | 46 ++++++++++- lib/services/api_client.dart | 4 +- 6 files changed, 190 insertions(+), 8 deletions(-) create mode 100644 lib/providers/live_logs_provider.dart create mode 100644 lib/screens/logs/live/live_logs_screen.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 39ec621..609c616 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -795,5 +795,7 @@ "clientIpCopied": "Client IP copied to the clipboard", "clientNameCopied": "Client name copied to the clipboard", "dnsServerAddressCopied": "DNS server address copied to the clipboard", - "select": "Select" + "select": "Select", + "liveLogs": "Live logs", + "hereWillAppearRealtimeLogs": "Here there will appear the logs on realtime." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 399f429..231eeaf 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -795,5 +795,7 @@ "clientIpCopied": "Dirección IP del cliente copiada al portapapeles", "clientNameCopied": "Nombre del cliente copiado al portapapeles", "dnsServerAddressCopied": "Dirección del servidor DNS copiada al portapapeles", - "select": "Seleccionar" + "select": "Seleccionar", + "liveLogs": "Registros en directo", + "hereWillAppearRealtimeLogs": "Aquí aparecerán los registros en tiempo real." } \ No newline at end of file diff --git a/lib/providers/live_logs_provider.dart b/lib/providers/live_logs_provider.dart new file mode 100644 index 0000000..044dd57 --- /dev/null +++ b/lib/providers/live_logs_provider.dart @@ -0,0 +1,51 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; + +import 'package:adguard_home_manager/models/logs.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class LiveLogsProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + + bool _isDisposed = false; + + @override + void dispose() { + _isDisposed = true; + super.dispose(); + } + + List _logs = []; + + List get logs { + return _logs; + } + + DateTime? _lastTime; + + void startFetchLogs() { + _lastTime = DateTime.now(); + _fetchLogs(); + } + + void _fetchLogs() async { + if (_lastTime == null) return; + final result = await _serversProvider!.apiClient2!.getLogs( + count: 100 + ); + if (result.successful == false || result.content == null) return; + final valid = (result.content as LogsData).data.where((e) => e.time.isAfter(_lastTime!)); + _logs = [...valid, ..._logs]; + _lastTime = DateTime.now(); + notifyListeners(); + + await Future.delayed(const Duration(seconds: 2)); + if (_isDisposed == true) return; + _fetchLogs(); + } +} \ No newline at end of file diff --git a/lib/screens/logs/live/live_logs_screen.dart b/lib/screens/logs/live/live_logs_screen.dart new file mode 100644 index 0000000..7d20374 --- /dev/null +++ b/lib/screens/logs/live/live_logs_screen.dart @@ -0,0 +1,89 @@ +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/logs/details/log_details_screen.dart'; +import 'package:adguard_home_manager/screens/logs/log_tile.dart'; + +import 'package:adguard_home_manager/providers/live_logs_provider.dart'; + +class LiveLogsScreen extends StatefulWidget { + const LiveLogsScreen({super.key}); + + @override + State createState() => _LiveLogsScreenState(); +} + +class _LiveLogsScreenState extends State { + @override + void initState() { + Provider.of(context, listen: false).startFetchLogs(); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + final liveLogsProvider = Provider.of(context); +print(liveLogsProvider.logs.length); + return Scaffold( + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + title: Text(AppLocalizations.of(context)!.liveLogs), + ) + ) + ], + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (liveLogsProvider.logs.isEmpty) SliverFillRemaining( + child: Center( + child: Padding( + padding: const EdgeInsets.all(16), + child: Text( + AppLocalizations.of(context)!.hereWillAppearRealtimeLogs, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontSize: 24 + ), + ), + ), + ), + ), + if (liveLogsProvider.logs.isNotEmpty) SliverList.builder( + itemCount: liveLogsProvider.logs.length, + itemBuilder: (context, index) => LogTile( + log: liveLogsProvider.logs[index], + length: liveLogsProvider.logs.length, + index: index, + onLogTap: (log) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + ) + ) + ); + }, + twoColumns: false + ), + ) + ], + ), + ) + ) + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 5014806..88c1c29 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -6,11 +6,14 @@ 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/logs/live/live_logs_screen.dart'; import 'package:adguard_home_manager/screens/logs/filters/logs_filters_modal.dart'; import 'package:adguard_home_manager/config/globals.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/providers/live_logs_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; @@ -74,6 +77,22 @@ class LogsListAppBar extends StatelessWidget { ); } + void openLiveLogsScreen() { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => MultiProvider( + providers: [ + ChangeNotifierProxyProvider( + create: (context) => LiveLogsProvider(), + update: (context, servers, logs) => logs!..update(servers), + ), + ], + child: const LiveLogsScreen() + ) + ) + ); + } + final Map translatedString = { "all": AppLocalizations.of(context)!.all, "filtered": AppLocalizations.of(context)!.filtered, @@ -104,10 +123,29 @@ class LogsListAppBar extends StatelessWidget { icon: const Icon(Icons.search_rounded), tooltip: AppLocalizations.of(context)!.search, ), - if (logsProvider.loadStatus == LoadStatus.loaded) IconButton( - onPressed: openFilersModal, - icon: const Icon(Icons.filter_list_rounded), - tooltip: AppLocalizations.of(context)!.filters, + if (logsProvider.loadStatus == LoadStatus.loaded) PopupMenuButton( + itemBuilder: (context) => [ + PopupMenuItem( + onTap: openFilersModal, + child: Row( + children: [ + const Icon(Icons.filter_list_rounded), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.filters) + ], + ) + ), + PopupMenuItem( + onTap: openLiveLogsScreen, + child: Row( + children: [ + const Icon(Icons.stream_rounded), + const SizedBox(width: 10), + Text(AppLocalizations.of(context)!.liveLogs) + ], + ) + ), + ], ), const SizedBox(width: 8), ], diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index 9bc283e..ce3e033 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -206,14 +206,14 @@ class ApiClientV2 { } Future getLogs({ - required int count, + int? count, int? offset, DateTime? olderThan, String? responseStatus, String? search }) async { final result = await HttpRequestClient.get( - urlPath: '/querylog?limit=$count${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}', + urlPath: '/querylog?${count != null ? 'limit=$count' : ''}${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}', server: server ); if (result.successful == true) { From bd08c98849b1342deb5e4b645d56a947a853d193 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Sep 2024 18:17:26 +0200 Subject: [PATCH 623/676] Removed print --- lib/screens/logs/live/live_logs_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/logs/live/live_logs_screen.dart b/lib/screens/logs/live/live_logs_screen.dart index 7d20374..1c09957 100644 --- a/lib/screens/logs/live/live_logs_screen.dart +++ b/lib/screens/logs/live/live_logs_screen.dart @@ -25,7 +25,7 @@ class _LiveLogsScreenState extends State { @override Widget build(BuildContext context) { final liveLogsProvider = Provider.of(context); -print(liveLogsProvider.logs.length); + return Scaffold( body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ From 7d1845f8064fc5065a94ac0f7e13f99c7669a381 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Sep 2024 18:21:13 +0200 Subject: [PATCH 624/676] Fix blocked services screen --- .../modals/blocked_services_screen.dart | 82 ++++++++++--------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/lib/screens/filters/modals/blocked_services_screen.dart b/lib/screens/filters/modals/blocked_services_screen.dart index f3f52ec..c62950d 100644 --- a/lib/screens/filters/modals/blocked_services_screen.dart +++ b/lib/screens/filters/modals/blocked_services_screen.dart @@ -119,24 +119,26 @@ class _BlockedServicesScreenStateWidget extends State { SliverOverlapInjector( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), - if (filteringProvider.blockedServicesLoadStatus == LoadStatus.loading) Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.loadingBlockedServicesList, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ) - ], + if (filteringProvider.blockedServicesLoadStatus == LoadStatus.loading) SliverFillRemaining( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingBlockedServicesList, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), ), ), if (filteringProvider.blockedServicesLoadStatus == LoadStatus.loaded) SliverList.builder( @@ -181,28 +183,30 @@ class _BlockedServicesScreenStateWidget extends State { ), ) ), - if (filteringProvider.blockedServicesLoadStatus == LoadStatus.error) Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - width: double.maxFinite, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon( - Icons.error, - color: Colors.red, - size: 50, - ), - const SizedBox(height: 30), - Text( - AppLocalizations.of(context)!.blockedServicesListNotLoaded, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, + if (filteringProvider.blockedServicesLoadStatus == LoadStatus.error) SliverFillRemaining( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, ), - ) - ], + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.blockedServicesListNotLoaded, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ) + ], + ), ), ) ], From d6b16b230c25474531b7c61b48c5079710c16f31 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Sep 2024 19:03:57 +0200 Subject: [PATCH 625/676] Added split view --- .../clients/client/logs_list_client.dart | 6 +- .../logs/details/log_details_screen.dart | 8 +- lib/screens/logs/live/live_logs_list.dart | 90 ++++++++++++++++ lib/screens/logs/live/live_logs_screen.dart | 101 ++++++++---------- lib/screens/logs/logs.dart | 1 + lib/screens/logs/logs_list.dart | 1 + 6 files changed, 144 insertions(+), 63 deletions(-) create mode 100644 lib/screens/logs/live/live_logs_list.dart diff --git a/lib/screens/clients/client/logs_list_client.dart b/lib/screens/clients/client/logs_list_client.dart index 2d76396..f12f8e4 100644 --- a/lib/screens/clients/client/logs_list_client.dart +++ b/lib/screens/clients/client/logs_list_client.dart @@ -237,7 +237,8 @@ class _LogsListClientState extends State { context: context, builder: (context) => LogDetailsScreen( log: log, - dialog: true + dialog: true, + twoColumns: widget.splitView, ) ) } @@ -246,7 +247,8 @@ class _LogsListClientState extends State { MaterialPageRoute( builder: (context) => LogDetailsScreen( log: log, - dialog: false + dialog: false, + twoColumns: widget.splitView, ) ) ) diff --git a/lib/screens/logs/details/log_details_screen.dart b/lib/screens/logs/details/log_details_screen.dart index 5d78823..d0a80e9 100644 --- a/lib/screens/logs/details/log_details_screen.dart +++ b/lib/screens/logs/details/log_details_screen.dart @@ -1,6 +1,5 @@ // ignore_for_file: use_build_context_synchronously -import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -11,6 +10,7 @@ import 'package:adguard_home_manager/screens/logs/details/log_list_tile.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; +import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; @@ -24,11 +24,13 @@ import 'package:adguard_home_manager/providers/app_config_provider.dart'; class LogDetailsScreen extends StatelessWidget { final Log log; final bool dialog; + final bool twoColumns; const LogDetailsScreen({ super.key, required this.log, - required this.dialog + required this.dialog, + required this.twoColumns, }); @override @@ -137,6 +139,7 @@ class LogDetailsScreen extends StatelessWidget { ); } else { + print(twoColumns); return Scaffold( body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ @@ -148,6 +151,7 @@ class LogDetailsScreen extends StatelessWidget { centerTitle: false, forceElevated: innerBoxIsScrolled, surfaceTintColor: isDesktop(width) ? Colors.transparent : null, + automaticallyImplyLeading: twoColumns != true, title: Text(AppLocalizations.of(context)!.logDetails), actions: [ IconButton( diff --git a/lib/screens/logs/live/live_logs_list.dart b/lib/screens/logs/live/live_logs_list.dart new file mode 100644 index 0000000..bf812e8 --- /dev/null +++ b/lib/screens/logs/live/live_logs_list.dart @@ -0,0 +1,90 @@ +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/logs/log_tile.dart'; +import 'package:adguard_home_manager/screens/logs/details/log_details_screen.dart'; + +import 'package:adguard_home_manager/models/logs.dart'; +import 'package:adguard_home_manager/providers/live_logs_provider.dart'; + +class LiveLogsList extends StatelessWidget { + final Log? selectedLog; + final void Function(Log) onLogSelected; + final bool twoColumns; + + const LiveLogsList({ + super.key, + required this.selectedLog, + required this.onLogSelected, + required this.twoColumns, + }); + + @override + Widget build(BuildContext context) { + final liveLogsProvider = Provider.of(context); + + return NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + title: Text(AppLocalizations.of(context)!.liveLogs), + ) + ) + ], + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (liveLogsProvider.logs.isEmpty) SliverFillRemaining( + child: Center( + child: Padding( + padding: const EdgeInsets.all(16), + child: Text( + AppLocalizations.of(context)!.hereWillAppearRealtimeLogs, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontSize: 24 + ), + ), + ), + ), + ), + if (liveLogsProvider.logs.isNotEmpty) SliverList.builder( + itemCount: liveLogsProvider.logs.length, + itemBuilder: (context, index) => LogTile( + log: liveLogsProvider.logs[index], + length: liveLogsProvider.logs.length, + index: index, + onLogTap: (log) { + if (!twoColumns) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + twoColumns: twoColumns, + ) + ) + ); + } + onLogSelected(log); + }, + isLogSelected: selectedLog == liveLogsProvider.logs[index], + twoColumns: twoColumns + ), + ) + ], + ), + ) + ) + ); + } +} \ No newline at end of file diff --git a/lib/screens/logs/live/live_logs_screen.dart b/lib/screens/logs/live/live_logs_screen.dart index 1c09957..06977b1 100644 --- a/lib/screens/logs/live/live_logs_screen.dart +++ b/lib/screens/logs/live/live_logs_screen.dart @@ -3,8 +3,10 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/details/log_details_screen.dart'; +import 'package:adguard_home_manager/screens/logs/live/live_logs_list.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; +import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/live_logs_provider.dart'; class LiveLogsScreen extends StatefulWidget { @@ -15,6 +17,8 @@ class LiveLogsScreen extends StatefulWidget { } class _LiveLogsScreenState extends State { + Log? _selectedLog; + @override void initState() { Provider.of(context, listen: false).startFetchLogs(); @@ -24,66 +28,45 @@ class _LiveLogsScreenState extends State { @override Widget build(BuildContext context) { - final liveLogsProvider = Provider.of(context); - - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - title: Text(AppLocalizations.of(context)!.liveLogs), - ) - ) - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (liveLogsProvider.logs.isEmpty) SliverFillRemaining( - child: Center( - child: Padding( - padding: const EdgeInsets.all(16), - child: Text( - AppLocalizations.of(context)!.hereWillAppearRealtimeLogs, - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant, - fontSize: 24 - ), - ), - ), + return Scaffold( + body: LayoutBuilder( + builder: (context, constraints) { + if (constraints.maxWidth > 800) { + return Material( + color: Colors.transparent, + child: Row( + children: [ + Expanded( + flex: 2, + child: LiveLogsList( + twoColumns: true, + selectedLog: _selectedLog, + onLogSelected: (log) => setState(() => _selectedLog = log), + ) ), - ), - if (liveLogsProvider.logs.isNotEmpty) SliverList.builder( - itemCount: liveLogsProvider.logs.length, - itemBuilder: (context, index) => LogTile( - log: liveLogsProvider.logs[index], - length: liveLogsProvider.logs.length, - index: index, - onLogTap: (log) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false, - ) + Expanded( + flex: 3, + child: _selectedLog != null + ? LogDetailsScreen( + log: _selectedLog!, + dialog: false, + twoColumns: true, ) - ); - }, - twoColumns: false - ), - ) - ], - ), - ) - ) - ), - ); + : const SizedBox() + ) + ], + ), + ); + } + else { + return LiveLogsList( + twoColumns: false, + selectedLog: _selectedLog, + onLogSelected: (log) => setState(() => _selectedLog = log), + ); + } + }, + ), + ); } } \ No newline at end of file diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index e99317d..d008297 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -48,6 +48,7 @@ class _LogsState extends State { ? LogDetailsScreen( log: _selectedLog!, dialog: false, + twoColumns: true, ) : const SizedBox() ) diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart index 6036f77..e50847a 100644 --- a/lib/screens/logs/logs_list.dart +++ b/lib/screens/logs/logs_list.dart @@ -188,6 +188,7 @@ class _LogsListWidgetState extends State { builder: (context) => LogDetailsScreen( log: log, dialog: false, + twoColumns: widget.twoColumns, ) ) ); From b7d4680f9c9acb0fd110e2ae3267cc4b4708c247 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Sep 2024 19:07:05 +0200 Subject: [PATCH 626/676] Updated macOS stuff --- macos/Podfile.lock | 32 +++++++++++++++++++------------- macos/Runner/AppDelegate.swift | 2 +- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 96c9ba0..54fe2f5 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -8,27 +8,27 @@ PODS: - FlutterMacOS - screen_retriever (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.25.2) - - sentry_flutter (8.2.0): + - Sentry/HybridSDK (8.35.1) + - sentry_flutter (8.8.0): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.25.2) + - Sentry/HybridSDK (= 8.35.1) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - sqflite (0.0.3): - Flutter - FlutterMacOS - - "sqlite3 (3.46.0+1)": - - "sqlite3/common (= 3.46.0+1)" - - "sqlite3/common (3.46.0+1)" - - "sqlite3/dbstatvtab (3.46.0+1)": + - "sqlite3 (3.46.1+1)": + - "sqlite3/common (= 3.46.1+1)" + - "sqlite3/common (3.46.1+1)" + - "sqlite3/dbstatvtab (3.46.1+1)": - sqlite3/common - - "sqlite3/fts5 (3.46.0+1)": + - "sqlite3/fts5 (3.46.1+1)": - sqlite3/common - - "sqlite3/perf-threadsafe (3.46.0+1)": + - "sqlite3/perf-threadsafe (3.46.1+1)": - sqlite3/common - - "sqlite3/rtree (3.46.0+1)": + - "sqlite3/rtree (3.46.1+1)": - sqlite3/common - sqlite3_flutter_libs (0.0.1): - FlutterMacOS @@ -37,6 +37,8 @@ PODS: - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree + - store_checker (0.0.1): + - FlutterMacOS - url_launcher_macos (0.0.1): - FlutterMacOS - window_manager (0.2.0): @@ -52,6 +54,7 @@ DEPENDENCIES: - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) + - store_checker (from `Flutter/ephemeral/.symlinks/plugins/store_checker/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) @@ -79,6 +82,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin sqlite3_flutter_libs: :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos + store_checker: + :path: Flutter/ephemeral/.symlinks/plugins/store_checker/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos window_manager: @@ -90,12 +95,13 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 - Sentry: 51b056d96914a741f63eca774d118678b1eb05a1 - sentry_flutter: e8397d13e297a5d4b6be8a752e33140b21c5cc97 + Sentry: 1fe34e9c2cbba1e347623610d26db121dcb569f1 + sentry_flutter: a39c2a2d67d5e5b9cb0b94a4985c76dd5b3fc737 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec - sqlite3: 292c3e1bfe89f64e51ea7fc7dab9182a017c8630 + sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb sqlite3_flutter_libs: 5ca46c1a04eddfbeeb5b16566164aa7ad1616e7b + store_checker: 387169de0dffe57b6370d54cc027e9f95051b57f url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift index d53ef64..8e02df2 100644 --- a/macos/Runner/AppDelegate.swift +++ b/macos/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true From 8761652eaa5ac33062957f77b35aba4b0d5c3f74 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Sep 2024 19:08:23 +0200 Subject: [PATCH 627/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 150159a..4d754b2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.18.0+141 +version: 2.19.0-beta.1+142 environment: sdk: '>=2.18.1 <3.0.0' From ffcc0c2da0bebe71467c3d0522e838f40fa6fe12 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Sep 2024 19:27:34 +0200 Subject: [PATCH 628/676] Removed store checker and added install referrer --- README.md | 4 +++- lib/functions/check_app_updates.dart | 10 +++------- lib/main.dart | 4 ++-- lib/providers/app_config_provider.dart | 8 ++++---- lib/screens/logs/live/live_logs_screen.dart | 2 -- .../general_settings/general_settings.dart | 11 ++--------- macos/Flutter/GeneratedPluginRegistrant.swift | 2 -- pubspec.lock | 16 ++++++++-------- pubspec.yaml | 2 +- 9 files changed, 23 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 96520c4..dac7569 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,6 @@ On [this repository](https://github.com/juanico10/Pihole_list) you can find a re - [fl chart](https://pub.dev/packages/fl_chart) - [flutter svg](https://pub.dev/packages/flutter_svg) - [percent indicator](https://pub.dev/packages/percent_indicator) -- [store checker](https://pub.dev/packages/store_checker) - [flutter markdown](https://pub.dev/packages/flutter_markdown) - [markdown](https://pub.dev/packages/markdown) - [html](https://pub.dev/packages/html) @@ -132,6 +131,9 @@ On [this repository](https://github.com/juanico10/Pihole_list) you can find a re - [timezone](https://pub.dev/packages/timezone) - [url launcher](https://pub.dev/packages/url_launcher) - [flutter custom tabs](https://pub.dev/packages/flutter_custom_tabs) +- [shared preferences](https://pub.dev/packages/shared_preferences) +- [window manager](https://pub.dev/packages/window_manager) +- [install referrer](https://pub.dev/packages/install_referrer)
      diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart index dc08f29..e6137d7 100644 --- a/lib/functions/check_app_updates.dart +++ b/lib/functions/check_app_updates.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:store_checker/store_checker.dart'; +import 'package:install_referrer/install_referrer.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/services/external_requests.dart'; @@ -9,7 +9,7 @@ import 'package:adguard_home_manager/models/github_release.dart'; Future checkAppUpdates({ required String currentBuildNumber, required void Function(GitHubRelease?) setUpdateAvailable, - required Source installationSource, + required InstallationAppReferrer? installationSource, required bool isBeta }) async { var result = isBeta @@ -35,11 +35,7 @@ Future checkAppUpdates({ setUpdateAvailable(gitHubRelease); if (Platform.isAndroid) { - if ( - installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || - installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || - installationSource == Source.UNKNOWN - ) { + if (installationSource == InstallationAppReferrer.androidManually) { return gitHubRelease; } else { diff --git a/lib/main.dart b/lib/main.dart index dce3456..ecd9f7e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:install_referrer/install_referrer.dart'; import 'package:provider/provider.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:dynamic_color/dynamic_color.dart'; @@ -12,7 +13,6 @@ import 'package:package_info_plus/package_info_plus.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; -import 'package:store_checker/store_checker.dart'; import 'package:window_manager/window_manager.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -80,7 +80,7 @@ void main() async { } if (Platform.isAndroid || Platform.isIOS) { - Source installationSource = await StoreChecker.getSource; + InstallationAppReferrer installationSource = await InstallReferrer.referrer; appConfigProvider.setInstallationSource(installationSource); } diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index f31eb3c..afdc467 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/scheduler.dart'; +import 'package:install_referrer/install_referrer.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:store_checker/store_checker.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -58,7 +58,7 @@ class AppConfigProvider with ChangeNotifier { GitHubRelease? _appUpdatesAvailable; - Source _installationSource = Source.UNKNOWN; + InstallationAppReferrer? _installationSource; PackageInfo? get getAppInfo { return _appInfo; @@ -162,7 +162,7 @@ class AppConfigProvider with ChangeNotifier { return _appUpdatesAvailable; } - Source get installationSource { + InstallationAppReferrer? get installationSource { return _installationSource; } @@ -227,7 +227,7 @@ class AppConfigProvider with ChangeNotifier { notifyListeners(); } - void setInstallationSource(Source value) { + void setInstallationSource(InstallationAppReferrer value) { _installationSource = value; notifyListeners(); } diff --git a/lib/screens/logs/live/live_logs_screen.dart b/lib/screens/logs/live/live_logs_screen.dart index 06977b1..5c35e1a 100644 --- a/lib/screens/logs/live/live_logs_screen.dart +++ b/lib/screens/logs/live/live_logs_screen.dart @@ -1,10 +1,8 @@ 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/logs/details/log_details_screen.dart'; import 'package:adguard_home_manager/screens/logs/live/live_logs_list.dart'; -import 'package:adguard_home_manager/screens/logs/log_tile.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/live_logs_provider.dart'; diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index 7c396da..936bd8b 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -3,8 +3,8 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:install_referrer/install_referrer.dart'; import 'package:provider/provider.dart'; -import 'package:store_checker/store_checker.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/settings.dart'; @@ -253,14 +253,7 @@ class _GeneralSettingsState extends State { right: 10 ) ), - if ( - !(Platform.isAndroid || Platform.isIOS) || - (Platform.isAndroid && ( - appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || - appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || - appConfigProvider.installationSource == Source.UNKNOWN - )) - ) ...[ + if (!(Platform.isAndroid || Platform.isIOS) || (Platform.isAndroid && (appConfigProvider.installationSource == InstallationAppReferrer.androidManually ))) ...[ SectionLabel(label: AppLocalizations.of(context)!.application), CustomListTile( icon: Icons.system_update_rounded, diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cf249ab..28ea475 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -13,7 +13,6 @@ import sentry_flutter import shared_preferences_foundation import sqflite import sqlite3_flutter_libs -import store_checker import url_launcher_macos import window_manager @@ -26,7 +25,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) - StoreCheckerPlugin.register(with: registry.registrar(forPlugin: "StoreCheckerPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 235ec9f..e7c67eb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -373,6 +373,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.2.0" + install_referrer: + dependency: "direct main" + description: + name: install_referrer + sha256: "901c56d24ee3c3010dfd0bbebf305ed6b4b0f3fe969192081c167590a64cd78b" + url: "https://pub.dev" + source: hosted + version: "1.2.1" intl: dependency: "direct main" description: @@ -730,14 +738,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.11.1" - store_checker: - dependency: "direct main" - description: - name: store_checker - sha256: "9e5841e4f922cc7f0283323ff3c78fd31ace14c22e988525d33355c35d7c815a" - url: "https://pub.dev" - source: hosted - version: "1.6.0" stream_channel: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4d754b2..3378718 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -51,7 +51,6 @@ dependencies: fl_chart: ^0.69.0 flutter_svg: ^2.0.9 percent_indicator: ^4.2.3 - store_checker: ^1.4.0 flutter_markdown: ^0.7.1 markdown: ^7.1.1 html: ^0.15.4 @@ -71,6 +70,7 @@ dependencies: url_launcher: ^6.2.4 shared_preferences: ^2.2.2 window_manager: ^0.4.2 + install_referrer: ^1.2.1 dev_dependencies: flutter_test: From 715ca0ab3fbfb2d0434af02621a76bb2f998ffc8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 8 Sep 2024 19:30:50 +0200 Subject: [PATCH 629/676] Updated readme --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index dac7569..d46c921 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,15 @@ This is an unofficial application. The AdGuard Home team and the development of ## Recommended configuration and lists On [this repository](https://github.com/juanico10/Pihole_list) you can find a recommended configuration for AdGuard Home and some lists. Thanks to [juanico10](https://github.com/juanico10). +## Donations +If you like the project and you want to contribute with the development, you can [become a sponsor on GitHub](https://github.com/sponsors/JGeek00), or you can donate using PayPal. + + + ## Generate production build
      • From f7c3ba03746295e00ff3b592f6ab3f977dbcec5f Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 18:13:26 +0200 Subject: [PATCH 630/676] Fixed most of the warnings --- lib/functions/snackbar.dart | 2 +- lib/models/filtering.dart | 2 +- lib/models/filtering_status.dart | 2 +- lib/models/logs.dart | 2 +- lib/providers/app_config_provider.dart | 2 +- lib/screens/clients/added_list.dart | 8 ++++---- .../clients/client/client_placeholder.dart | 4 ++-- .../clients/client/remove_client_modal.dart | 4 ++-- .../clients/client/safe_search_modal.dart | 4 ++-- lib/screens/clients/client/services_modal.dart | 4 ++-- lib/screens/clients/fab.dart | 4 ++-- lib/screens/clients/search_clients.dart | 10 +++++----- lib/screens/connect/fab.dart | 2 +- lib/screens/filters/add_button.dart | 16 ++++++++-------- lib/screens/filters/custom_rules_list.dart | 4 ++-- .../filters/details/list_details_screen.dart | 16 ++++++++++------ lib/screens/filters/filters.dart | 18 +++++++++--------- lib/screens/filters/filters_list.dart | 8 ++++---- lib/screens/filters/filters_triple_column.dart | 2 +- lib/screens/filters/list_options_menu.dart | 4 ++-- .../modals/blocked_services_screen.dart | 4 ++-- .../modals/remove_custom_rule_modal.dart | 4 ++-- .../modals/update_interval_lists_modal.dart | 4 ++-- .../selection/delete_selection_modal.dart | 4 ++-- .../enable_disable_selection_modal.dart | 4 ++-- .../filters/selection/selection_lists.dart | 7 +++---- .../filters/selection/selection_screen.dart | 4 ++-- lib/screens/home/combined_chart.dart | 5 ++--- lib/screens/home/fab.dart | 2 +- lib/screens/home/home.dart | 2 +- .../management_modal/management_modal.dart | 2 +- .../home/management_modal/small_switch.dart | 4 ++-- .../home/top_items/top_items_lists.dart | 10 +++++----- .../home/top_items/top_items_screen.dart | 2 +- .../logs/details/log_details_screen.dart | 5 ++--- lib/screens/logs/log_tile.dart | 18 +++++++++--------- lib/screens/logs/logs_list.dart | 4 ++-- .../settings/access_settings/clients_list.dart | 14 +++++++------- lib/screens/settings/advanced_setings.dart | 4 ++-- .../settings/customization/color_item.dart | 2 +- .../customization/theme_mode_button.dart | 12 ++++++------ .../dhcp/delete_static_lease_modal.dart | 4 ++-- lib/screens/settings/dhcp/dhcp.dart | 12 ++++++------ lib/screens/settings/dhcp/dhcp_leases.dart | 12 ++++++------ lib/screens/settings/dns/bootstrap_dns.dart | 8 ++++---- lib/screens/settings/dns/cache_config.dart | 10 +++++----- lib/screens/settings/dns/dns.dart | 4 ++-- .../settings/dns/dns_server_settings.dart | 6 +++--- lib/screens/settings/dns/fallback_dns.dart | 6 +++--- .../settings/dns/private_reverse_servers.dart | 6 +++--- lib/screens/settings/dns/upstream_dns.dart | 6 +++--- .../dns_rewrites/delete_dns_rewrite.dart | 4 ++-- .../settings/dns_rewrites/dns_rewrites.dart | 14 +++++++------- .../encryption/config_error_modal.dart | 4 ++-- .../settings/encryption/custom_text_field.dart | 4 ++-- .../settings/encryption/encryption.dart | 8 ++++---- .../settings/encryption/error_message.dart | 4 ++-- .../settings/encryption/master_switch.dart | 4 ++-- lib/screens/settings/encryption/status.dart | 4 ++-- .../general_settings/general_settings.dart | 4 ++-- .../top_items_list_settings.dart | 4 ++-- .../settings/logs_settings/logs_settings.dart | 12 ++++++------ lib/screens/settings/safe_search_settings.dart | 4 ++-- .../statistics_settings.dart | 4 ++-- .../update_server/autoupdate_unavailable.dart | 2 +- lib/screens/settings/update_server/update.dart | 6 +++--- .../settings/update_server/update_screen.dart | 6 +++--- lib/widgets/add_server/add_server_modal.dart | 8 ++++---- lib/widgets/add_server/form_text_field.dart | 4 ++-- lib/widgets/combined_line_chart.dart | 10 +++++----- lib/widgets/confirm_action_modal.dart | 4 ++-- lib/widgets/custom_checkbox_list_tile.dart | 4 ++-- lib/widgets/custom_list_tile.dart | 4 ++-- lib/widgets/custom_radio.dart | 4 ++-- lib/widgets/custom_radio_list_tile.dart | 4 ++-- lib/widgets/custom_radio_toggle.dart | 4 ++-- lib/widgets/line_chart.dart | 10 +++++----- lib/widgets/menu_bar.dart | 4 ++-- lib/widgets/option_box.dart | 4 ++-- lib/widgets/process_dialog.dart | 4 ++-- lib/widgets/section_label.dart | 4 ++-- lib/widgets/servers_list/delete_modal.dart | 8 ++++---- .../servers_list/server_tile_functions.dart | 11 ++++++----- lib/widgets/servers_list/servers_list.dart | 4 ++-- .../servers_list/servers_list_item.dart | 2 +- lib/widgets/update_modal.dart | 4 ++-- lib/widgets/version_warning_modal.dart | 4 ++-- 87 files changed, 252 insertions(+), 250 deletions(-) diff --git a/lib/functions/snackbar.dart b/lib/functions/snackbar.dart index b332fcd..d0d7bc0 100644 --- a/lib/functions/snackbar.dart +++ b/lib/functions/snackbar.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/config/globals.dart'; -void showSnacbkar({ +void showSnackbar({ required AppConfigProvider appConfigProvider, required String label, required Color color, diff --git a/lib/models/filtering.dart b/lib/models/filtering.dart index 7b521d2..5e43bf4 100644 --- a/lib/models/filtering.dart +++ b/lib/models/filtering.dart @@ -63,7 +63,7 @@ class Filter { Map toJson() => { "url": url, "name": name, - "last_updated": lastUpdated != null ? lastUpdated!.toIso8601String() : null, + "last_updated": lastUpdated?.toIso8601String(), "id": id, "rules_count": rulesCount, "enabled": enabled, diff --git a/lib/models/filtering_status.dart b/lib/models/filtering_status.dart index bfd219d..83908c3 100644 --- a/lib/models/filtering_status.dart +++ b/lib/models/filtering_status.dart @@ -65,7 +65,7 @@ class Filter { Map toJson() => { "url": url, "name": name, - "last_updated": lastUpdated != null ? lastUpdated!.toIso8601String() : null, + "last_updated": lastUpdated?.toIso8601String(), "id": id, "rules_count": rulesCount, "enabled": enabled, diff --git a/lib/models/logs.dart b/lib/models/logs.dart index 9ba3738..b4991be 100644 --- a/lib/models/logs.dart +++ b/lib/models/logs.dart @@ -30,7 +30,7 @@ class LogsData { Map toJson() => { "data": List.from(data.map((x) => x.toJson())), - "oldest": oldest != null ? oldest!.toIso8601String() : null, + "oldest": oldest?.toIso8601String(), }; } diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index afdc467..3b843b9 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -33,7 +33,7 @@ class AppConfigProvider with ChangeNotifier { int _selectedTheme = 0; bool _useDynamicColor = true; int _staticColor = 0; - bool _useThemeColorForStatus = false; + final bool _useThemeColorForStatus = false; int _selectedClientsTab = 0; int _selectedFiltersTab = 0; diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 0bb668b..2cceaab 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -82,14 +82,14 @@ class _AddedListState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientUpdatedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotUpdated, color: Colors.red @@ -109,14 +109,14 @@ class _AddedListState extends State { if (widget.splitView == true) { Navigator.of(clientsNavigatorKey.currentContext!).popUntil((route) => false); } - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientDeletedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotDeleted, color: Colors.red diff --git a/lib/screens/clients/client/client_placeholder.dart b/lib/screens/clients/client/client_placeholder.dart index cf4f485..0e8f018 100644 --- a/lib/screens/clients/client/client_placeholder.dart +++ b/lib/screens/clients/client/client_placeholder.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; class ClientPlaceholder extends StatelessWidget { - const ClientPlaceholder({Key? key}) : super(key: key); + const ClientPlaceholder({super.key}); @override Widget build(BuildContext context) { - return Center( + return const Center( child: Text("Select a client"), ); } diff --git a/lib/screens/clients/client/remove_client_modal.dart b/lib/screens/clients/client/remove_client_modal.dart index 4427d22..b531540 100644 --- a/lib/screens/clients/client/remove_client_modal.dart +++ b/lib/screens/clients/client/remove_client_modal.dart @@ -5,9 +5,9 @@ class RemoveClientModal extends StatelessWidget { final void Function() onConfirm; const RemoveClientModal({ - Key? key, + super.key, required this.onConfirm - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/clients/client/safe_search_modal.dart b/lib/screens/clients/client/safe_search_modal.dart index 1be694c..1d539be 100644 --- a/lib/screens/clients/client/safe_search_modal.dart +++ b/lib/screens/clients/client/safe_search_modal.dart @@ -11,11 +11,11 @@ class SafeSearchModal extends StatefulWidget { final void Function(SafeSearch) onConfirm; const SafeSearchModal({ - Key? key, + super.key, required this.safeSearch, required this.disabled, required this.onConfirm - }) : super(key: key); + }); @override State createState() => _SafeSearchModalState(); diff --git a/lib/screens/clients/client/services_modal.dart b/lib/screens/clients/client/services_modal.dart index 1a98275..b8f69dc 100644 --- a/lib/screens/clients/client/services_modal.dart +++ b/lib/screens/clients/client/services_modal.dart @@ -10,10 +10,10 @@ class ServicesModal extends StatefulWidget { final void Function(List) onConfirm; const ServicesModal({ - Key? key, + super.key, required this.blockedServices, required this.onConfirm, - }) : super(key: key); + }); @override State createState() => _ServicesModalStateWidget(); diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index a46b89a..383a2f3 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -33,14 +33,14 @@ class ClientsFab extends StatelessWidget { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAddedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotAdded, color: Colors.red diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index e5b1451..2654c24 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -95,14 +95,14 @@ class _SearchClientsState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientDeletedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotDeleted, color: Colors.red @@ -119,14 +119,14 @@ class _SearchClientsState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientUpdatedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotUpdated, color: Colors.red @@ -205,7 +205,7 @@ class _SearchClientsState extends State { height: 1, decoration: BoxDecoration( color: showDivider == true - ? Theme.of(context).colorScheme.surfaceVariant + ? Theme.of(context).colorScheme.surfaceContainerHighest : Colors.transparent ), ), diff --git a/lib/screens/connect/fab.dart b/lib/screens/connect/fab.dart index 05ed1a2..f826485 100644 --- a/lib/screens/connect/fab.dart +++ b/lib/screens/connect/fab.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; class FabConnect extends StatelessWidget { - const FabConnect({Key? key}) : super(key: key); + const FabConnect({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index be9f0f4..2eca7d4 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -42,14 +42,14 @@ class AddFiltersButton extends StatelessWidget { if (!context.mounted) return; if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleAddedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleNotAdded, color: Colors.red @@ -67,14 +67,14 @@ class AddFiltersButton extends StatelessWidget { if (!context.mounted) return; if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.customRulesUpdatedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.customRulesNotUpdated, color: Colors.red @@ -146,28 +146,28 @@ class AddFiltersButton extends StatelessWidget { if (!context.mounted) return; if (result['success'] == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: "${AppLocalizations.of(context)!.listAdded} ${result['data']}.", color: Colors.green ); } else if (result['success'] == false && result['error'] == 'invalid_url') { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listUrlInvalid, color: Colors.red ); } else if (result['success'] == false && result['error'] == 'url_exists') { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listAlreadyAdded, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listNotAdded, color: Colors.red diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 25a1d4c..304972f 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -163,7 +163,7 @@ class _CustomRulesListState extends State { onPressed: () async { final result = await filteringProvider.fetchFilters(); if (result == false) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, color: Colors.red @@ -203,7 +203,7 @@ class _CustomRulesListState extends State { onRefresh: () async { final result = await filteringProvider.fetchFilters(); if (result == false) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, color: Colors.red diff --git a/lib/screens/filters/details/list_details_screen.dart b/lib/screens/filters/details/list_details_screen.dart index 95da744..188854c 100644 --- a/lib/screens/filters/details/list_details_screen.dart +++ b/lib/screens/filters/details/list_details_screen.dart @@ -94,14 +94,14 @@ class _ListDetailsScreenState extends State { ); processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listDataUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listDataNotUpdated, color: Colors.red @@ -175,6 +175,7 @@ class _ListDetailsScreenState extends State { _Content( isDialog: widget.dialog, list: list, + type: widget.type, ) ], ), @@ -216,6 +217,7 @@ class _ListDetailsScreenState extends State { _Content( isDialog: widget.dialog, list: list, + type: widget.type, ) ], ), @@ -261,10 +263,12 @@ class _ListDetailsScreenState extends State { class _Content extends StatelessWidget { final Filter list; final bool isDialog; + final String type; const _Content({ required this.list, - required this.isDialog + required this.isDialog, + required this.type, }); @override @@ -339,7 +343,7 @@ class _Content extends StatelessWidget { CustomListTile( icon: Icons.shield_rounded, title: AppLocalizations.of(context)!.listType, - subtitle: isDialog == 'whitelist' + subtitle: type == 'whitelist' ? AppLocalizations.of(context)!.whitelist : AppLocalizations.of(context)!.blacklist, padding: isDialog == true @@ -431,7 +435,7 @@ class _Actions extends StatelessWidget { ); processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listDeleted, color: Colors.green @@ -439,7 +443,7 @@ class _Actions extends StatelessWidget { Navigator.pop(context); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listNotDeleted, color: Colors.red diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index 2ab49a3..ab624e0 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -24,7 +24,7 @@ import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients.dart'; class Filters extends StatefulWidget { - const Filters({Key? key}) : super(key: key); + const Filters({super.key}); @override State createState() => _FiltersState(); @@ -57,14 +57,14 @@ class _FiltersState extends State { if (!mounted) return; processModal.close(); if (result['success'] == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: "${result['data']['updated']} ${AppLocalizations.of(context)!.listsUpdated}", color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listsNotUpdated, color: Colors.red @@ -109,14 +109,14 @@ class _FiltersState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.filteringStatusUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.filteringStatusNotUpdated, color: Colors.red @@ -133,14 +133,14 @@ class _FiltersState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.updateFrequencyChanged, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.updateFrequencyNotChanged, color: Colors.red @@ -163,14 +163,14 @@ class _FiltersState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleRemovedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleNotRemoved, color: Colors.red diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index f4cca03..b9d4617 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -27,13 +27,13 @@ class FiltersList extends StatefulWidget { final void Function(Filter, String) onOpenDetailsScreen; const FiltersList({ - Key? key, + super.key, required this.loadStatus, required this.scrollController, required this.data, required this.type, required this.onOpenDetailsScreen - }) : super(key: key); + }); @override State createState() => _FiltersListState(); @@ -133,7 +133,7 @@ class _FiltersListState extends State { onPressed: () async { final result = await filteringProvider.fetchFilters(); if (result == false && mounted) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, color: Colors.red @@ -173,7 +173,7 @@ class _FiltersListState extends State { onRefresh: () async { final result = await filteringProvider.fetchFilters(); if (result == false && mounted) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, color: Colors.red diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index 686ee15..a659fa8 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -84,7 +84,7 @@ class FiltersTripleColumn extends StatelessWidget { onPressed: () async { final result = await filteringProvider.fetchFilters(); if (result == false && context.mounted) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, color: Colors.red diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index c35d080..4d2f57f 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -59,14 +59,14 @@ class ListOptionsMenu extends StatelessWidget { if (!context.mounted) return; if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listDataUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listDataNotUpdated, color: Colors.red diff --git a/lib/screens/filters/modals/blocked_services_screen.dart b/lib/screens/filters/modals/blocked_services_screen.dart index c62950d..ac54c61 100644 --- a/lib/screens/filters/modals/blocked_services_screen.dart +++ b/lib/screens/filters/modals/blocked_services_screen.dart @@ -68,14 +68,14 @@ class _BlockedServicesScreenStateWidget extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.blockedServicesUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.blockedServicesNotUpdated, color: Colors.red diff --git a/lib/screens/filters/modals/remove_custom_rule_modal.dart b/lib/screens/filters/modals/remove_custom_rule_modal.dart index f1c4352..ec281f7 100644 --- a/lib/screens/filters/modals/remove_custom_rule_modal.dart +++ b/lib/screens/filters/modals/remove_custom_rule_modal.dart @@ -5,9 +5,9 @@ class RemoveCustomRule extends StatelessWidget { final void Function() onConfirm; const RemoveCustomRule({ - Key? key, + super.key, required this.onConfirm - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/filters/modals/update_interval_lists_modal.dart b/lib/screens/filters/modals/update_interval_lists_modal.dart index f6504a5..ce7058b 100644 --- a/lib/screens/filters/modals/update_interval_lists_modal.dart +++ b/lib/screens/filters/modals/update_interval_lists_modal.dart @@ -235,10 +235,10 @@ class _Content extends StatelessWidget { } : null, style: ButtonStyle( - overlayColor: MaterialStateProperty.all( + overlayColor: WidgetStateProperty.all( Theme.of(context).colorScheme.primary.withOpacity(0.1) ), - foregroundColor: MaterialStateProperty.all( + foregroundColor: WidgetStateProperty.all( selectedOption != null ? Theme.of(context).colorScheme.primary : Colors.grey, diff --git a/lib/screens/filters/selection/delete_selection_modal.dart b/lib/screens/filters/selection/delete_selection_modal.dart index 944d515..ecf77e5 100644 --- a/lib/screens/filters/selection/delete_selection_modal.dart +++ b/lib/screens/filters/selection/delete_selection_modal.dart @@ -9,11 +9,11 @@ class DeleteSelectionModal extends StatefulWidget { final void Function() onDelete; const DeleteSelectionModal({ - Key? key, + super.key, required this.selectedBlacklists, required this.selectedWhitelists, required this.onDelete, - }) : super(key: key); + }); @override State createState() => _DeleteSelectionModalState(); diff --git a/lib/screens/filters/selection/enable_disable_selection_modal.dart b/lib/screens/filters/selection/enable_disable_selection_modal.dart index fdb809c..d14fe7c 100644 --- a/lib/screens/filters/selection/enable_disable_selection_modal.dart +++ b/lib/screens/filters/selection/enable_disable_selection_modal.dart @@ -9,11 +9,11 @@ class EnableDisableSelectionModal extends StatefulWidget { final void Function() onDelete; const EnableDisableSelectionModal({ - Key? key, + super.key, required this.selectedBlacklists, required this.selectedWhitelists, required this.onDelete, - }) : super(key: key); + }); @override State createState() => _EnableDisableSelectionModalState(); diff --git a/lib/screens/filters/selection/selection_lists.dart b/lib/screens/filters/selection/selection_lists.dart index b423f77..a7988e9 100644 --- a/lib/screens/filters/selection/selection_lists.dart +++ b/lib/screens/filters/selection/selection_lists.dart @@ -13,13 +13,13 @@ class SelectionList extends StatelessWidget { final void Function() unselectAll; const SelectionList({ - Key? key, + super.key, required this.lists, required this.selectedLists, required this.onSelect, required this.selectAll, required this.unselectAll, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -231,11 +231,10 @@ class _CheckboxTile extends StatelessWidget { final bool isSelected; const _CheckboxTile({ - Key? key, required this.list, required this.onSelect, required this.isSelected, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/filters/selection/selection_screen.dart b/lib/screens/filters/selection/selection_screen.dart index 1475454..5907012 100644 --- a/lib/screens/filters/selection/selection_screen.dart +++ b/lib/screens/filters/selection/selection_screen.dart @@ -82,8 +82,8 @@ class _SelectionScreenState extends State with TickerProviderSt blacklists: _selectedBlacklists, whitelists: _selectedWhitelists ); - if (!mounted) return; processModal.close(); + if (!context.mounted) return; showDialog( context: context, builder: (ctx) => SelectionResultModal( @@ -113,8 +113,8 @@ class _SelectionScreenState extends State with TickerProviderSt blacklists: _selectedBlacklists, whitelists: _selectedWhitelists ); - if (!mounted) return; processModal.close(); + if (!context.mounted) return; showDialog( context: context, builder: (ctx) => SelectionResultModal( diff --git a/lib/screens/home/combined_chart.dart b/lib/screens/home/combined_chart.dart index 89519db..f951cea 100644 --- a/lib/screens/home/combined_chart.dart +++ b/lib/screens/home/combined_chart.dart @@ -37,7 +37,7 @@ class CombinedChartItem { } class CombinedHomeChart extends StatelessWidget { - const CombinedHomeChart({Key? key}) : super(key: key); + const CombinedHomeChart({super.key}); List? removeZero(List list) { final removed = list.where((i) => i > 0); @@ -266,12 +266,11 @@ class _Legend extends StatelessWidget { final String? secondaryValue; const _Legend({ - Key? key, required this.label, required this.color, required this.primaryValue, this.secondaryValue - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/home/fab.dart b/lib/screens/home/fab.dart index bd77be7..7e465be 100644 --- a/lib/screens/home/fab.dart +++ b/lib/screens/home/fab.dart @@ -7,7 +7,7 @@ import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; class HomeFab extends StatelessWidget { - const HomeFab({Key? key}) : super(key: key); + const HomeFab({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index b74e959..7a60115 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -93,7 +93,7 @@ class _HomeState extends State { onRefresh: () async { final result = await statusProvider.getServerStatus(); if (mounted && result == false) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverStatusNotRefreshed, color: Colors.red diff --git a/lib/screens/home/management_modal/management_modal.dart b/lib/screens/home/management_modal/management_modal.dart index b18586b..5a931ad 100644 --- a/lib/screens/home/management_modal/management_modal.dart +++ b/lib/screens/home/management_modal/management_modal.dart @@ -82,7 +82,7 @@ class _ManagementModalState extends State with SingleTickerProv time: time ); if (mounted && result == false) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.invalidUsernamePassword, color: Colors.red diff --git a/lib/screens/home/management_modal/small_switch.dart b/lib/screens/home/management_modal/small_switch.dart index 4e34d68..192360c 100644 --- a/lib/screens/home/management_modal/small_switch.dart +++ b/lib/screens/home/management_modal/small_switch.dart @@ -8,13 +8,13 @@ class SmallSwitch extends StatelessWidget { final bool disabled; const SmallSwitch({ - Key? key, + super.key, required this.label, required this.icon, required this.value, required this.onChange, required this.disabled, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/home/top_items/top_items_lists.dart b/lib/screens/home/top_items/top_items_lists.dart index 7c24bd3..3ca6e24 100644 --- a/lib/screens/home/top_items/top_items_lists.dart +++ b/lib/screens/home/top_items/top_items_lists.dart @@ -83,14 +83,14 @@ class TopItemsLists extends StatelessWidget { if (!context.mounted) return; if (rules == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.userFilteringRulesUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, color: Colors.red @@ -121,21 +121,21 @@ class TopItemsLists extends StatelessWidget { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAddedSuccessfully, color: Colors.green ); } else if (result.successful == false && result.content == 'client_another_list') { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: newList == AccessSettingsList.allowed || newList == AccessSettingsList.disallowed ? AppLocalizations.of(context)!.clientNotRemoved diff --git a/lib/screens/home/top_items/top_items_screen.dart b/lib/screens/home/top_items/top_items_screen.dart index 1070953..94675ad 100644 --- a/lib/screens/home/top_items/top_items_screen.dart +++ b/lib/screens/home/top_items/top_items_screen.dart @@ -348,7 +348,7 @@ class _Content extends StatelessWidget { percent: screenData[index].values.toList()[0]/total, barRadius: const Radius.circular(5), progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: Theme.of(context).colorScheme.surfaceVariant, + backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest, ), ), const SizedBox(width: 10), diff --git a/lib/screens/logs/details/log_details_screen.dart b/lib/screens/logs/details/log_details_screen.dart index d0a80e9..5ffe18e 100644 --- a/lib/screens/logs/details/log_details_screen.dart +++ b/lib/screens/logs/details/log_details_screen.dart @@ -52,14 +52,14 @@ class LogDetailsScreen extends StatelessWidget { processModal.close(); if (rules == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.userFilteringRulesUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, color: Colors.red @@ -139,7 +139,6 @@ class LogDetailsScreen extends StatelessWidget { ); } else { - print(twoColumns); return Scaffold( body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 2a6a720..bed2e40 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -108,14 +108,14 @@ class LogTile extends StatelessWidget { if (!context.mounted) return; if (rules == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.userFilteringRulesUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, color: Colors.red @@ -134,14 +134,14 @@ class LogTile extends StatelessWidget { if (!context.mounted) return; if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAddedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotAdded, color: Colors.red @@ -163,7 +163,7 @@ class LogTile extends StatelessWidget { if (!context.mounted) return; if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: isDomainBlocked(log.reason) == true ? AppLocalizations.of(context)!.domainUnblockedThisClient(log.question.name!) @@ -172,7 +172,7 @@ class LogTile extends StatelessWidget { ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleNotAdded, color: Colors.red @@ -199,21 +199,21 @@ class LogTile extends StatelessWidget { if (!context.mounted) return; if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAddedSuccessfully, color: Colors.green ); } else if (result.successful == false && result.content == 'client_another_list') { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.changesNotSaved, color: Colors.red diff --git a/lib/screens/logs/logs_list.dart b/lib/screens/logs/logs_list.dart index e50847a..4281af0 100644 --- a/lib/screens/logs/logs_list.dart +++ b/lib/screens/logs/logs_list.dart @@ -42,7 +42,7 @@ class _LogsListWidgetState extends State { final result = await statusProvider.getFilteringRules(); if (mounted && result == false) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.couldntGetFilteringStatus, color: Colors.red @@ -56,7 +56,7 @@ class _LogsListWidgetState extends State { final result = await clientsProvider.fetchClients(); if (mounted && result == false) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.couldntGetFilteringStatus, color: Colors.red diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index 0b83a4d..bf2c4d4 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -71,7 +71,7 @@ class _ClientsListState extends State { Future refetchClients() async { final result = await clientsProvider.fetchClients(); if (result == false && mounted) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientsNotLoaded, color: Colors.red @@ -104,21 +104,21 @@ class _ClientsListState extends State { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientRemovedSuccessfully, color: Colors.green ); } else if (result.successful == false && result.content == 'client_another_list') { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: type == AccessSettingsList.allowed || type == AccessSettingsList.disallowed ? AppLocalizations.of(context)!.clientNotRemoved @@ -137,21 +137,21 @@ class _ClientsListState extends State { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAddedSuccessfully, color: Colors.green ); } else if (result.successful == false && result.content == 'client_another_list') { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: type == AccessSettingsList.allowed || type == AccessSettingsList.disallowed ? AppLocalizations.of(context)!.clientNotRemoved diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 9483cd8..6026082 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -26,14 +26,14 @@ class AdvancedSettings extends StatelessWidget { final result = await function(newStatus); if (!context.mounted) return; if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsUpdatedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.cannotUpdateSettings, color: Colors.red diff --git a/lib/screens/settings/customization/color_item.dart b/lib/screens/settings/customization/color_item.dart index d753bf5..00873d0 100644 --- a/lib/screens/settings/customization/color_item.dart +++ b/lib/screens/settings/customization/color_item.dart @@ -31,7 +31,7 @@ class ColorItem extends StatelessWidget { child: InkWell( onTap: () => onChanged(numericValue), borderRadius: BorderRadius.circular(50), - overlayColor: const MaterialStatePropertyAll(Colors.grey), + overlayColor: const WidgetStatePropertyAll(Colors.grey), child: Container( width: 50, height: 50, diff --git a/lib/screens/settings/customization/theme_mode_button.dart b/lib/screens/settings/customization/theme_mode_button.dart index df3f8d1..e48a511 100644 --- a/lib/screens/settings/customization/theme_mode_button.dart +++ b/lib/screens/settings/customization/theme_mode_button.dart @@ -9,14 +9,14 @@ class ThemeModeButton extends StatelessWidget { final bool? disabled; const ThemeModeButton({ - Key? key, + super.key, required this.icon, required this.value, required this.selected, required this.label, required this.onChanged, this.disabled - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -32,19 +32,19 @@ class ThemeModeButton extends StatelessWidget { ? () => onChanged(value) : null, style: ButtonStyle( - elevation: MaterialStateProperty.all(0), - shape: MaterialStateProperty.all( + elevation: WidgetStateProperty.all(0), + shape: WidgetStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), ) ), - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( value == selected ? disabled == null || disabled == false ? Theme.of(context).colorScheme.primary : greyBackgroundColor : disabled == null || disabled == false - ? Theme.of(context).colorScheme.surfaceVariant + ? Theme.of(context).colorScheme.surfaceContainerHighest : greyBackgroundColor, ) ), diff --git a/lib/screens/settings/dhcp/delete_static_lease_modal.dart b/lib/screens/settings/dhcp/delete_static_lease_modal.dart index 77ad241..f797e89 100644 --- a/lib/screens/settings/dhcp/delete_static_lease_modal.dart +++ b/lib/screens/settings/dhcp/delete_static_lease_modal.dart @@ -5,9 +5,9 @@ class DeleteStaticLeaseModal extends StatelessWidget { final void Function() onConfirm; const DeleteStaticLeaseModal({ - Key? key, + super.key, required this.onConfirm - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index f7facd6..449b063 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -221,14 +221,14 @@ class _DhcpScreenState extends State { if (!mounted) return; processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsSaved, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsNotSaved, color: Colors.red @@ -245,14 +245,14 @@ class _DhcpScreenState extends State { processModal.close(); if (result.successful == true) { clearAll(); - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.configRestored, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.configNotRestored, color: Colors.red @@ -276,14 +276,14 @@ class _DhcpScreenState extends State { data.dhcpStatus!.leases = []; dhcpProvider.setDhcpData(data); - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.leasesRestored, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.leasesNotRestored, color: Colors.red diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index 9bb1fe3..7b90d13 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -43,14 +43,14 @@ class DhcpLeases extends StatelessWidget { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseDeleted, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseNotDeleted, color: Colors.red @@ -67,28 +67,28 @@ class DhcpLeases extends StatelessWidget { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseCreated, color: Colors.green ); } else if (result.successful == false && result.content == "already_exists") { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseExists, color: Colors.red ); } else if (result.successful == false && result.content == "server_not_configured") { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverNotConfigured, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseNotCreated, color: Colors.red diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index c970f34..833396d 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -80,21 +80,21 @@ class _BootstrapDnsScreenState extends State { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } else if (result.successful == false && result.statusCode == 400) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, color: Colors.red @@ -197,7 +197,7 @@ class _BootstrapDnsScreenState extends State { ) ], ), - )).toList(), + )), Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index 40a99f8..e2edb4d 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -86,21 +86,21 @@ class _CacheConfigDnsScreenState extends State { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } else if (result.successful== false && result.statusCode == 400) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, color: Colors.red @@ -139,14 +139,14 @@ class _CacheConfigDnsScreenState extends State { void clearCache() async { final result = await clearDnsCache(context, serversProvider.selectedServer!); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheCleared, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheNotCleared, color: Colors.red diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index baba9fa..564fff2 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -66,14 +66,14 @@ class _DnsSettingsState extends State { void clearCache() async { final result = await clearDnsCache(context, serversProvider.selectedServer!); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheCleared, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsCacheNotCleared, color: Colors.red diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index a4b7369..fc74d88 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -183,21 +183,21 @@ class _DnsServerSettingsScreenState extends State { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } else if (result.successful == false && result.statusCode == 400) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, color: Colors.red diff --git a/lib/screens/settings/dns/fallback_dns.dart b/lib/screens/settings/dns/fallback_dns.dart index 849eb4d..19040ed 100644 --- a/lib/screens/settings/dns/fallback_dns.dart +++ b/lib/screens/settings/dns/fallback_dns.dart @@ -91,21 +91,21 @@ class _FallbackDnsScreenState extends State { if (!context.mounted) return; if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } else if (result.successful == false && result.statusCode == 400) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, color: Colors.red diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index a9419e9..1ea4cc3 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -112,21 +112,21 @@ class _PrivateReverseDnsServersScreenState extends State { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } else if (result.successful == false && result.statusCode == 400) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, color: Colors.red ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, color: Colors.red diff --git a/lib/screens/settings/dns_rewrites/delete_dns_rewrite.dart b/lib/screens/settings/dns_rewrites/delete_dns_rewrite.dart index fb2c705..be6b7b4 100644 --- a/lib/screens/settings/dns_rewrites/delete_dns_rewrite.dart +++ b/lib/screens/settings/dns_rewrites/delete_dns_rewrite.dart @@ -5,9 +5,9 @@ class DeleteDnsRewrite extends StatelessWidget { final void Function() onConfirm; const DeleteDnsRewrite({ - Key? key, + super.key, required this.onConfirm - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 301c3a1..ad38c44 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -67,14 +67,14 @@ class _DnsRewritesScreenState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleDeleted, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleNotDeleted, color: Colors.red @@ -91,14 +91,14 @@ class _DnsRewritesScreenState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleAdded, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleNotAdded, color: Colors.red @@ -115,14 +115,14 @@ class _DnsRewritesScreenState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleNotUpdated, color: Colors.red @@ -169,7 +169,7 @@ class _DnsRewritesScreenState extends State { onRefresh: () async { final result = await rewriteRulesProvider.fetchRules(); if (result == false) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.rewriteRulesNotLoaded, color: Colors.red diff --git a/lib/screens/settings/encryption/config_error_modal.dart b/lib/screens/settings/encryption/config_error_modal.dart index 1e2cfd0..4fdcec3 100644 --- a/lib/screens/settings/encryption/config_error_modal.dart +++ b/lib/screens/settings/encryption/config_error_modal.dart @@ -5,9 +5,9 @@ class EncryptionErrorModal extends StatelessWidget { final String error; const EncryptionErrorModal({ - Key? key, + super.key, required this.error, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/settings/encryption/custom_text_field.dart b/lib/screens/settings/encryption/custom_text_field.dart index 6a1cac8..1290104 100644 --- a/lib/screens/settings/encryption/custom_text_field.dart +++ b/lib/screens/settings/encryption/custom_text_field.dart @@ -12,7 +12,7 @@ class EncryptionTextField extends StatelessWidget { final String? helperText; const EncryptionTextField({ - Key? key, + super.key, required this.enabled, required this.controller, required this.icon, @@ -22,7 +22,7 @@ class EncryptionTextField extends StatelessWidget { this.keyboardType, this.multiline, this.helperText, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index 4e48f6c..764f303 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -233,14 +233,14 @@ class _EncryptionSettingsState extends State { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.encryptionConfigSaved, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.encryptionConfigNotSaved, color: Colors.red @@ -282,14 +282,14 @@ class _EncryptionSettingsState extends State { processModal.close(); if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.configurationResetSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.configurationResetError, color: Colors.red diff --git a/lib/screens/settings/encryption/error_message.dart b/lib/screens/settings/encryption/error_message.dart index be132d8..01dc221 100644 --- a/lib/screens/settings/encryption/error_message.dart +++ b/lib/screens/settings/encryption/error_message.dart @@ -5,9 +5,9 @@ class ErrorMessageEncryption extends StatelessWidget { final String errorMessage; const ErrorMessageEncryption({ - Key? key, + super.key, required this.errorMessage, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/settings/encryption/master_switch.dart b/lib/screens/settings/encryption/master_switch.dart index f13c4fa..474c0f9 100644 --- a/lib/screens/settings/encryption/master_switch.dart +++ b/lib/screens/settings/encryption/master_switch.dart @@ -6,10 +6,10 @@ class EncryptionMasterSwitch extends StatelessWidget { final void Function(bool) onChange; const EncryptionMasterSwitch({ - Key? key, + super.key, required this.value, required this.onChange - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/settings/encryption/status.dart b/lib/screens/settings/encryption/status.dart index eb344ae..0c11f5a 100644 --- a/lib/screens/settings/encryption/status.dart +++ b/lib/screens/settings/encryption/status.dart @@ -8,10 +8,10 @@ class Status extends StatelessWidget { final String label; const Status({ - Key? key, + super.key, required this.valid, required this.label - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index 936bd8b..0029752 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -49,14 +49,14 @@ class _GeneralSettingsState extends State { }) async { final result = await function(newStatus); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsUpdatedSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.cannotUpdateSettings, color: Colors.red diff --git a/lib/screens/settings/general_settings/top_items_list/top_items_list_settings.dart b/lib/screens/settings/general_settings/top_items_list/top_items_list_settings.dart index 9e9c836..89b1613 100644 --- a/lib/screens/settings/general_settings/top_items_list/top_items_list_settings.dart +++ b/lib/screens/settings/general_settings/top_items_list/top_items_list_settings.dart @@ -43,14 +43,14 @@ class _TopItemsListSettingsState extends State with Ticker final result = await appConfigProvider.setHomeTopItemsOrder(persistHomeTopItemsList); if (!context.mounted) return; if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsSaved, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsNotSaved, color: Colors.red diff --git a/lib/screens/settings/logs_settings/logs_settings.dart b/lib/screens/settings/logs_settings/logs_settings.dart index cd723c7..0d55ce5 100644 --- a/lib/screens/settings/logs_settings/logs_settings.dart +++ b/lib/screens/settings/logs_settings/logs_settings.dart @@ -102,17 +102,17 @@ class _LogsSettingsState extends State { processModal.close(); - if (!mounted) return; + if (!context.mounted) return; if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsCleared, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsNotCleared, color: Colors.red @@ -135,17 +135,17 @@ class _LogsSettingsState extends State { processModal.close(); - if (!mounted) return; + if (!context.mounted) return; if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsConfigUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsConfigNotUpdated, color: Colors.red diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 793a1c2..c9d5eef 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -90,7 +90,7 @@ class _SafeSearchSettingsScreenState extends State { processModal.close(); if (result == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsUpdatedSuccessfully, color: Colors.green, @@ -98,7 +98,7 @@ class _SafeSearchSettingsScreenState extends State { ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsNotSaved, color: Colors.red, diff --git a/lib/screens/settings/statistics_settings/statistics_settings.dart b/lib/screens/settings/statistics_settings/statistics_settings.dart index 27e4570..67a2989 100644 --- a/lib/screens/settings/statistics_settings/statistics_settings.dart +++ b/lib/screens/settings/statistics_settings/statistics_settings.dart @@ -148,14 +148,14 @@ class _StatisticsSettingsState extends State { if (!context.mounted) return; if (result.successful == true) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.statisticsConfigUpdated, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.statisticsConfigNotUpdated, color: Colors.red diff --git a/lib/screens/settings/update_server/autoupdate_unavailable.dart b/lib/screens/settings/update_server/autoupdate_unavailable.dart index 9846448..1ba4ae7 100644 --- a/lib/screens/settings/update_server/autoupdate_unavailable.dart +++ b/lib/screens/settings/update_server/autoupdate_unavailable.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class AutoUpdateUnavailableModal extends StatelessWidget { - const AutoUpdateUnavailableModal({Key? key}) : super(key: key); + const AutoUpdateUnavailableModal({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index d1f8d95..de951b7 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -41,7 +41,7 @@ class UpdateScreen extends StatelessWidget { if (result.successful == true) { serversProvider.recheckPeriodServerUpdated(); - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.requestStartUpdateSuccessful, color: Colors.green, @@ -49,7 +49,7 @@ class UpdateScreen extends StatelessWidget { ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.requestStartUpdateFailed, color: Colors.red, @@ -203,7 +203,7 @@ class UpdateScreen extends StatelessWidget { body: Column( children: [ Container( - color: Theme.of(context).colorScheme.surfaceVariant, + color: Theme.of(context).colorScheme.surfaceContainerHighest, child: SafeArea( child: headerPortrait() ) diff --git a/lib/screens/settings/update_server/update_screen.dart b/lib/screens/settings/update_server/update_screen.dart index 5386ad8..4ddc959 100644 --- a/lib/screens/settings/update_server/update_screen.dart +++ b/lib/screens/settings/update_server/update_screen.dart @@ -88,7 +88,7 @@ class _UpdateScreenState extends State { if (!context.mounted) return; if (result.successful == true) { serversProvider.recheckPeriodServerUpdated(); - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.requestStartUpdateSuccessful, color: Colors.green, @@ -96,7 +96,7 @@ class _UpdateScreenState extends State { ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.requestStartUpdateFailed, color: Colors.red, @@ -220,7 +220,7 @@ class _Header extends SliverPersistentHeaderDelegate { return LayoutBuilder( builder: (context, constraints) => Container( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceVariant, + color: Theme.of(context).colorScheme.surfaceContainerHighest, ), child: Align( alignment: Alignment.topLeft, diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index e6888da..ec00ff6 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -157,7 +157,7 @@ class _AddServerModalState extends State { if (result != AuthStatus.success) { cancelConnecting(); if (mounted) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: getErrorMessage(result), color: Colors.red @@ -206,7 +206,7 @@ class _AddServerModalState extends State { if (serverCreated != null) { if (mounted) setState(() => isConnecting = false); if (mounted) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionNotCreated, color: Colors.red @@ -256,7 +256,7 @@ class _AddServerModalState extends State { if (result != AuthStatus.success) { cancelConnecting(); if (mounted) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: getErrorMessage(result), color: Colors.red @@ -306,7 +306,7 @@ class _AddServerModalState extends State { ) ); if (mounted) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionNotCreated, color: Colors.red diff --git a/lib/widgets/add_server/form_text_field.dart b/lib/widgets/add_server/form_text_field.dart index 0fb6f94..72d410b 100644 --- a/lib/widgets/add_server/form_text_field.dart +++ b/lib/widgets/add_server/form_text_field.dart @@ -13,7 +13,7 @@ class FormTextField extends StatelessWidget { final bool isConnecting; const FormTextField({ - Key? key, + super.key, required this.label, required this.controller, this.error, @@ -24,7 +24,7 @@ class FormTextField extends StatelessWidget { this.hintText, this.helperText, required this.isConnecting - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/combined_line_chart.dart b/lib/widgets/combined_line_chart.dart index 6f3a87f..9aceb67 100644 --- a/lib/widgets/combined_line_chart.dart +++ b/lib/widgets/combined_line_chart.dart @@ -15,12 +15,12 @@ class CustomCombinedLineChart extends StatelessWidget { final bool daysInterval; const CustomCombinedLineChart({ - Key? key, + super.key, required this.inputData, required this.context, required this.dates, required this.daysInterval - }) : super(key: key); + }); LineChartData mainData(Map data, ThemeMode selectedTheme) { String chartDate(DateTime date) { @@ -55,11 +55,11 @@ class CustomCombinedLineChart extends StatelessWidget { } return LineChartData( - gridData: FlGridData( + gridData: const FlGridData( show: false, drawVerticalLine: false, ), - titlesData: FlTitlesData( + titlesData: const FlTitlesData( show: false, ), borderData: FlBorderData( @@ -73,7 +73,7 @@ class CustomCombinedLineChart extends StatelessWidget { barWidth: 2, isStrokeCapRound: true, preventCurveOverShooting: true, - dotData: FlDotData( + dotData: const FlDotData( show: false, ), belowBarData: BarAreaData( diff --git a/lib/widgets/confirm_action_modal.dart b/lib/widgets/confirm_action_modal.dart index d0bb314..4ed9cd7 100644 --- a/lib/widgets/confirm_action_modal.dart +++ b/lib/widgets/confirm_action_modal.dart @@ -8,12 +8,12 @@ class ConfirmActionModal extends StatelessWidget { final void Function() onConfirm; const ConfirmActionModal({ - Key? key, + super.key, required this.icon, required this.title, required this.message, required this.onConfirm - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/custom_checkbox_list_tile.dart b/lib/widgets/custom_checkbox_list_tile.dart index be14a3c..39c4cdf 100644 --- a/lib/widgets/custom_checkbox_list_tile.dart +++ b/lib/widgets/custom_checkbox_list_tile.dart @@ -9,14 +9,14 @@ class CustomCheckboxListTile extends StatelessWidget { final EdgeInsets? padding; const CustomCheckboxListTile({ - Key? key, + super.key, required this.value, required this.onChanged, required this.title, this.disabled, this.subtitle, this.padding - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/custom_list_tile.dart b/lib/widgets/custom_list_tile.dart index 0523468..5bf1e42 100644 --- a/lib/widgets/custom_list_tile.dart +++ b/lib/widgets/custom_list_tile.dart @@ -14,7 +14,7 @@ class CustomListTile extends StatelessWidget { final Color? color; const CustomListTile({ - Key? key, + super.key, required this.title, this.subtitle, this.subtitleWidget, @@ -26,7 +26,7 @@ class CustomListTile extends StatelessWidget { this.disabled, this.onHover, this.color, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/custom_radio.dart b/lib/widgets/custom_radio.dart index f8f2a08..5058316 100644 --- a/lib/widgets/custom_radio.dart +++ b/lib/widgets/custom_radio.dart @@ -7,12 +7,12 @@ class CustomRadio extends StatelessWidget { final Color backgroundColor; const CustomRadio({ - Key? key, + super.key, required this.value, required this.groupValue, this.onChange, required this.backgroundColor, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/custom_radio_list_tile.dart b/lib/widgets/custom_radio_list_tile.dart index 4d59b3c..0469bc9 100644 --- a/lib/widgets/custom_radio_list_tile.dart +++ b/lib/widgets/custom_radio_list_tile.dart @@ -11,14 +11,14 @@ class CustomRadioListTile extends StatelessWidget { final void Function(String) onChanged; const CustomRadioListTile({ - Key? key, + super.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) { diff --git a/lib/widgets/custom_radio_toggle.dart b/lib/widgets/custom_radio_toggle.dart index 59cb9e9..2698243 100644 --- a/lib/widgets/custom_radio_toggle.dart +++ b/lib/widgets/custom_radio_toggle.dart @@ -7,12 +7,12 @@ class CustomRadioToggle extends StatelessWidget { final void Function(String) onTap; const CustomRadioToggle({ - Key? key, + super.key, required this.groupSelected, required this.value, required this.label, required this.onTap, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/line_chart.dart b/lib/widgets/line_chart.dart index 5ac8bdd..f6899d1 100644 --- a/lib/widgets/line_chart.dart +++ b/lib/widgets/line_chart.dart @@ -13,13 +13,13 @@ class CustomLineChart extends StatelessWidget { final BuildContext context; const CustomLineChart({ - Key? key, + super.key, required this.data, required this.color, required this.dates, required this.daysInterval, required this.context - }) : super(key: key); + }); String chartDate(DateTime date) { String twoDigits(int number) => number.toString().padLeft(2, '0'); @@ -55,11 +55,11 @@ class CustomLineChart extends StatelessWidget { LineChartData mainData(Map data, ThemeMode selectedTheme) { return LineChartData( - gridData: FlGridData( + gridData: const FlGridData( show: false, drawVerticalLine: false, ), - titlesData: FlTitlesData( + titlesData: const FlTitlesData( show: false, ), borderData: FlBorderData( @@ -73,7 +73,7 @@ class CustomLineChart extends StatelessWidget { barWidth: 2, isStrokeCapRound: true, preventCurveOverShooting: true, - dotData: FlDotData( + dotData: const FlDotData( show: false, ), belowBarData: BarAreaData( diff --git a/lib/widgets/menu_bar.dart b/lib/widgets/menu_bar.dart index 0151b87..fe80446 100644 --- a/lib/widgets/menu_bar.dart +++ b/lib/widgets/menu_bar.dart @@ -11,9 +11,9 @@ class CustomMenuBar extends StatelessWidget { final Widget child; const CustomMenuBar({ - Key? key, + super.key, required this.child - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/option_box.dart b/lib/widgets/option_box.dart index f19a88f..e8514ef 100644 --- a/lib/widgets/option_box.dart +++ b/lib/widgets/option_box.dart @@ -7,12 +7,12 @@ class OptionBox extends StatelessWidget { final String label; const OptionBox({ - Key? key, + super.key, required this.optionsValue, required this.itemValue, required this.onTap, required this.label, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/process_dialog.dart b/lib/widgets/process_dialog.dart index 0c91442..f7f85a9 100644 --- a/lib/widgets/process_dialog.dart +++ b/lib/widgets/process_dialog.dart @@ -4,9 +4,9 @@ class ProcessDialog extends StatelessWidget { final String message; const ProcessDialog({ - Key? key, + super.key, required this.message, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/section_label.dart b/lib/widgets/section_label.dart index c1f767a..1e3980f 100644 --- a/lib/widgets/section_label.dart +++ b/lib/widgets/section_label.dart @@ -5,10 +5,10 @@ class SectionLabel extends StatelessWidget { final EdgeInsets? padding; const SectionLabel({ - Key? key, + super.key, required this.label, this.padding - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/servers_list/delete_modal.dart b/lib/widgets/servers_list/delete_modal.dart index dbf169d..4067d18 100644 --- a/lib/widgets/servers_list/delete_modal.dart +++ b/lib/widgets/servers_list/delete_modal.dart @@ -13,9 +13,9 @@ class DeleteModal extends StatelessWidget { final Server serverToDelete; const DeleteModal({ - Key? key, + super.key, required this.serverToDelete, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -34,14 +34,14 @@ class DeleteModal extends StatelessWidget { appConfigProvider.setSelectedScreen(0); } - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionRemoved, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionCannotBeRemoved, color: Colors.red diff --git a/lib/widgets/servers_list/server_tile_functions.dart b/lib/widgets/servers_list/server_tile_functions.dart index ec3c92e..06dbaee 100644 --- a/lib/widgets/servers_list/server_tile_functions.dart +++ b/lib/widgets/servers_list/server_tile_functions.dart @@ -50,14 +50,15 @@ void showDeleteModal({ required BuildContext context, required Server server }) async { - await Future.delayed(const Duration(seconds: 0), () => { + await Future.delayed(const Duration(seconds: 0), () { + if (!context.mounted) return; showDialog( context: context, builder: (context) => DeleteModal( serverToDelete: server, ), barrierDismissible: false - ) + ); }); } @@ -133,7 +134,7 @@ void connectToServer({ process.close(); if (!context.mounted) return; final appConfigProvider = Provider.of(context, listen: false); - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.cannotConnect, color: Colors.red @@ -150,14 +151,14 @@ void setDefaultServer({ if (!context.mounted) return; final appConfigProvider = Provider.of(context, listen: false); if (result == null) { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionDefaultSuccessfully, color: Colors.green ); } else { - showSnacbkar( + showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.connectionDefaultFailed, color: Colors.red diff --git a/lib/widgets/servers_list/servers_list.dart b/lib/widgets/servers_list/servers_list.dart index 8e530f2..d5a8d1b 100644 --- a/lib/widgets/servers_list/servers_list.dart +++ b/lib/widgets/servers_list/servers_list.dart @@ -16,13 +16,13 @@ class ServersList extends StatelessWidget { final double breakingWidth; const ServersList({ - Key? key, + super.key, required this.context, required this.controllers, required this.onChange, required this.scrollController, required this.breakingWidth - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 47ca6fe..29b11a5 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -68,7 +68,7 @@ class _ServersListItemState extends State with SingleTickerProv decoration: BoxDecoration( border: Border( bottom: BorderSide( - color: Theme.of(context).colorScheme.surfaceVariant, + color: Theme.of(context).colorScheme.surfaceContainerHighest, width: 1 ) ) diff --git a/lib/widgets/update_modal.dart b/lib/widgets/update_modal.dart index 5b99b66..8cedd2e 100644 --- a/lib/widgets/update_modal.dart +++ b/lib/widgets/update_modal.dart @@ -11,10 +11,10 @@ class UpdateModal extends StatefulWidget { final void Function(String, String) onDownload; const UpdateModal({ - Key? key, + super.key, required this.gitHubRelease, required this.onDownload, - }) : super(key: key); + }); @override State createState() => _UpdateModalState(); diff --git a/lib/widgets/version_warning_modal.dart b/lib/widgets/version_warning_modal.dart index f2230b0..72dbe4d 100644 --- a/lib/widgets/version_warning_modal.dart +++ b/lib/widgets/version_warning_modal.dart @@ -5,9 +5,9 @@ class VersionWarningModal extends StatelessWidget { final String version; const VersionWarningModal({ - Key? key, + super.key, required this.version, - }) : super(key: key); + }); @override Widget build(BuildContext context) { From 29af26f118c5c902cbf76b1cac90ea30e271476d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 18:18:20 +0200 Subject: [PATCH 631/676] Added padding bottom list live logs --- lib/screens/logs/live/live_logs_list.dart | 47 ++++++++++++----------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/lib/screens/logs/live/live_logs_list.dart b/lib/screens/logs/live/live_logs_list.dart index bf812e8..4bdf02f 100644 --- a/lib/screens/logs/live/live_logs_list.dart +++ b/lib/screens/logs/live/live_logs_list.dart @@ -51,34 +51,37 @@ class LiveLogsList extends StatelessWidget { textAlign: TextAlign.center, style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant, - fontSize: 24 + fontSize: 22 ), ), ), ), ), - if (liveLogsProvider.logs.isNotEmpty) SliverList.builder( - itemCount: liveLogsProvider.logs.length, - itemBuilder: (context, index) => LogTile( - log: liveLogsProvider.logs[index], - length: liveLogsProvider.logs.length, - index: index, - onLogTap: (log) { - if (!twoColumns) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => LogDetailsScreen( - log: log, - dialog: false, - twoColumns: twoColumns, + if (liveLogsProvider.logs.isNotEmpty) SliverPadding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewPadding.bottom), + sliver: SliverList.builder( + itemCount: liveLogsProvider.logs.length, + itemBuilder: (context, index) => LogTile( + log: liveLogsProvider.logs[index], + length: liveLogsProvider.logs.length, + index: index, + onLogTap: (log) { + if (!twoColumns) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => LogDetailsScreen( + log: log, + dialog: false, + twoColumns: twoColumns, + ) ) - ) - ); - } - onLogSelected(log); - }, - isLogSelected: selectedLog == liveLogsProvider.logs[index], - twoColumns: twoColumns + ); + } + onLogSelected(log); + }, + isLogSelected: selectedLog == liveLogsProvider.logs[index], + twoColumns: twoColumns + ), ), ) ], From f9149056fdc05dcf98ed80fa179f664ae8e8e548 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 18:21:46 +0200 Subject: [PATCH 632/676] Fixed logs search bar --- lib/screens/logs/logs_list_appbar.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 88c1c29..caab9fa 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -365,7 +365,8 @@ class _SearchState extends State<_Search> { ), tooltip: AppLocalizations.of(context)!.clearSearch, ) - : null + : null, + contentPadding: const EdgeInsets.symmetric(vertical: 12), ), ), ), From 9eb200f5daef69374fad1893ff574a13ab2a401a Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 18:51:57 +0200 Subject: [PATCH 633/676] Changed design top items screen --- .../home/top_items/top_items_screen.dart | 422 +++++++++--------- lib/screens/logs/logs_list_appbar.dart | 120 +---- lib/widgets/floating_search_bar.dart | 110 +++++ 3 files changed, 339 insertions(+), 313 deletions(-) create mode 100644 lib/widgets/floating_search_bar.dart diff --git a/lib/screens/home/top_items/top_items_screen.dart b/lib/screens/home/top_items/top_items_screen.dart index 94675ad..0f7465f 100644 --- a/lib/screens/home/top_items/top_items_screen.dart +++ b/lib/screens/home/top_items/top_items_screen.dart @@ -9,6 +9,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/options_menu.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/widgets/floating_search_bar.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/constants/enums.dart'; @@ -16,6 +17,7 @@ import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; enum _SortingOptions { highestToLowest, lowestToHighest } +final GlobalKey _searchButtonKey = GlobalKey(); class TopItemsScreen extends StatefulWidget { final HomeTopItems type; @@ -47,15 +49,18 @@ class TopItemsScreen extends StatefulWidget { class _TopItemsScreenState extends State { _SortingOptions _sortingOptions = _SortingOptions.highestToLowest; - bool searchActive = false; final TextEditingController searchController = TextEditingController(); + String? _currentSearchValue = ""; List> data = []; List> screenData = []; void search(String value) { List> newValues = widget.data.where((item) => item.keys.toList()[0].contains(value)).toList(); - setState(() => screenData = newValues); + setState(() { + screenData = newValues; + _currentSearchValue = searchController.text; + }); } @override @@ -75,118 +80,129 @@ class _TopItemsScreenState extends State { final sortedValues = _sortingOptions == _SortingOptions.lowestToHighest ? screenData.reversed.toList() : screenData.toList(); + + void showSearchDialog() { + showDialog( + context: context, + builder: (context) => FloatingSearchBar( + existingSearchValue: _currentSearchValue, + searchButtonRenderBox: _searchButtonKey.currentContext?.findRenderObject() as RenderBox?, + onSearchCompleted: (v) { + List> newValues = widget.data.where((item) => item.keys.toList()[0].contains(v)).toList(); + setState(() { + screenData = newValues; + _currentSearchValue = v; + }); + }, + ), + ); + } if (widget.isFullscreen == true) { - return Dialog.fullscreen( - child: Scaffold( - appBar: AppBar( - title: searchActive == true - ? Padding( - padding: const EdgeInsets.only(bottom: 3), - child: TextFormField( - controller: searchController, - onChanged: search, - decoration: InputDecoration( - hintText: AppLocalizations.of(context)!.search, - hintStyle: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 + return Scaffold( + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + title: Text(widget.title), + actions: [ + IconButton( + key: _searchButtonKey, + onPressed: showSearchDialog, + icon: const Icon(Icons.search_rounded), + tooltip: AppLocalizations.of(context)!.search, + ), + PopupMenuButton( + icon: const Icon(Icons.sort_rounded), + itemBuilder: (context) => [ + PopupMenuItem( + onTap: () => setState(() => _sortingOptions = _SortingOptions.highestToLowest), + child: Row( + children: [ + const Icon(Icons.arrow_downward_rounded), + const SizedBox(width: 8), + Expanded( + child: Text(AppLocalizations.of(context)!.fromHighestToLowest) + ), + const SizedBox(width: 16), + Icon( + _sortingOptions == _SortingOptions.highestToLowest + ? Icons.radio_button_checked_rounded + : Icons.radio_button_unchecked_rounded, + color: _sortingOptions == _SortingOptions.highestToLowest + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant, + ) + ], + ) ), - border: InputBorder.none, - ), - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 18 - ), - autofocus: true, - ), - ) - : Text(widget.title), - leading: searchActive == true ? - IconButton( - onPressed: () => setState(() { - searchActive = false; - searchController.text = ''; - screenData = data; - }), - icon: const Icon(Icons.arrow_back), - tooltip: AppLocalizations.of(context)!.exitSearch, - ) : null, - actions: [ - if (searchActive == false) IconButton( - onPressed: () => setState(() => searchActive = true), - icon: const Icon(Icons.search), - tooltip: AppLocalizations.of(context)!.search, - ), - if (searchActive == true) IconButton( - onPressed: () => setState(() { - searchController.text = ''; - screenData = data; - }), - icon: const Icon(Icons.clear_rounded), - tooltip: AppLocalizations.of(context)!.clearSearch, - ), - PopupMenuButton( - icon: const Icon(Icons.sort_rounded), - itemBuilder: (context) => [ - PopupMenuItem( - onTap: () => setState(() => _sortingOptions = _SortingOptions.highestToLowest), - child: Row( - children: [ - const Icon(Icons.arrow_downward_rounded), - const SizedBox(width: 8), - Expanded( - child: Text(AppLocalizations.of(context)!.fromHighestToLowest) - ), - const SizedBox(width: 16), - Icon( - _sortingOptions == _SortingOptions.highestToLowest - ? Icons.radio_button_checked_rounded - : Icons.radio_button_unchecked_rounded, - color: _sortingOptions == _SortingOptions.highestToLowest - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurfaceVariant, + PopupMenuItem( + onTap: () => setState(() => _sortingOptions = _SortingOptions.lowestToHighest), + child: Row( + children: [ + const Icon(Icons.arrow_upward_rounded), + const SizedBox(width: 8), + Expanded( + child: Text(AppLocalizations.of(context)!.fromLowestToHighest) + ), + const SizedBox(width: 16), + Icon( + _sortingOptions == _SortingOptions.lowestToHighest + ? Icons.radio_button_checked_rounded + : Icons.radio_button_unchecked_rounded, + color: _sortingOptions == _SortingOptions.lowestToHighest + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant, + ) + ], ) - ], - ) + ), + ], ), - PopupMenuItem( - onTap: () => setState(() => _sortingOptions = _SortingOptions.lowestToHighest), - child: Row( - children: [ - const Icon(Icons.arrow_upward_rounded), - const SizedBox(width: 8), - Expanded( - child: Text(AppLocalizations.of(context)!.fromLowestToHighest) + const SizedBox(width: 8) + ], + ) + ) + ], + body: SafeArea( + top: false, + bottom: false, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + if (sortedValues.isEmpty) Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.noItemsSearch, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, ), - const SizedBox(width: 16), - Icon( - _sortingOptions == _SortingOptions.lowestToHighest - ? Icons.radio_button_checked_rounded - : Icons.radio_button_unchecked_rounded, - color: _sortingOptions == _SortingOptions.lowestToHighest - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurfaceVariant, - ) - ], - ) + ), + ), + ), + if (sortedValues.isNotEmpty) SliverList.builder( + itemCount: sortedValues.length, + itemBuilder: (context, index) => _Item( + data: sortedValues[index], + isClient: widget.isClient, + options: widget.options, + total: total, + withProgressBar: widget.withProgressBar, + onTapEntry: widget.onTapEntry, + buildValue: widget.buildValue, + ), ), ], ), - const SizedBox(width: 8) - ], - ), - body: SafeArea( - child: _Content( - buildValue: widget.buildValue, - isClient: widget.isClient, - onTapEntry: widget.onTapEntry, - options: widget.options, - screenData: sortedValues, - total: total, - withProgressBar: widget.withProgressBar, - ), - ), + ) + ) ), ); } @@ -242,14 +258,29 @@ class _TopItemsScreenState extends State { ), ), Expanded( - child: _Content( - buildValue: widget.buildValue, - isClient: widget.isClient, - onTapEntry: widget.onTapEntry, - options: widget.options, - screenData: sortedValues, - total: total, - withProgressBar: widget.withProgressBar, + child: sortedValues.isNotEmpty ? ListView.builder( + itemCount: sortedValues.length, + itemBuilder: (context, index) => _Item( + data: sortedValues[index], + isClient: widget.isClient, + options: widget.options, + withProgressBar: widget.withProgressBar, + onTapEntry: widget.onTapEntry, + buildValue: widget.buildValue, + total: total, + ), + ) : Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text( + AppLocalizations.of(context)!.noItemsSearch, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), ), ), ], @@ -260,8 +291,8 @@ class _TopItemsScreenState extends State { } } -class _Content extends StatelessWidget { - final List> screenData; +class _Item extends StatelessWidget { + final dynamic data; final bool? isClient; final List Function(dynamic) options; final bool withProgressBar; @@ -269,8 +300,8 @@ class _Content extends StatelessWidget { final String Function(dynamic) buildValue; final double total; - const _Content({ - required this.screenData, + const _Item({ + required this.data, required this.isClient, required this.options, required this.withProgressBar, @@ -283,98 +314,75 @@ class _Content extends StatelessWidget { Widget build(BuildContext context) { final statusProvider = Provider.of(context); - if (screenData.isNotEmpty) { - return ListView.builder( - padding: const EdgeInsets.only(top: 0), - itemCount: screenData.length, - itemBuilder: (context, index) { - String? name; - if (isClient != null && isClient == true) { - try { - name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; - } catch (e) { - // ---- // - } - } - - return OptionsMenu( - options: options, - value: screenData[index].keys.toList()[0], - onTap: onTapEntry != null - ? (v) { - onTapEntry!(v); - Navigator.pop(context); - } - : null, - child: CustomListTile( - title: screenData[index].keys.toList()[0], - trailing: Text( - buildValue(screenData[index].values.toList()[0]), - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - subtitleWidget: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (name != null) ...[ - Text( - name, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurface - ), - ), - const SizedBox(height: 5), - ], - if (withProgressBar == true) Row( - children: [ - SizedBox( - width: 50, - child: Text( - "${doubleFormat((screenData[index].values.toList()[0]/total*100), Platform.localeName)}%", - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor - ), - ), - ), - const SizedBox(width: 10), - Flexible( - child: LinearPercentIndicator( - animation: true, - lineHeight: 4, - animationDuration: 500, - curve: Curves.easeOut, - percent: screenData[index].values.toList()[0]/total, - barRadius: const Radius.circular(5), - progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest, - ), - ), - const SizedBox(width: 10), - ], - ), - ], - ) - ), - ); - } - ); + String? name; + if (isClient != null && isClient == true) { + try { + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(data.keys.toList()[0])).name; + } catch (e) { + // ---- // + } } - else { - return Center( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - AppLocalizations.of(context)!.noItemsSearch, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), + + return OptionsMenu( + options: options, + value: data.keys.toList()[0], + onTap: onTapEntry != null + ? (v) { + onTapEntry!(v); + Navigator.pop(context); + } + : null, + child: CustomListTile( + title: data.keys.toList()[0], + trailing: Text( + buildValue(data.values.toList()[0]), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant ), ), - ); - } + subtitleWidget: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (name != null) ...[ + Text( + name, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurface + ), + ), + const SizedBox(height: 5), + ], + if (withProgressBar == true) Row( + children: [ + SizedBox( + width: 50, + child: Text( + "${doubleFormat((data.values.toList()[0]/total*100), Platform.localeName)}%", + style: TextStyle( + color: Theme.of(context).listTileTheme.textColor + ), + ), + ), + const SizedBox(width: 10), + Flexible( + child: LinearPercentIndicator( + animation: true, + lineHeight: 4, + animationDuration: 500, + curve: Curves.easeOut, + percent: data.values.toList()[0]/total, + barRadius: const Radius.circular(5), + progressColor: Theme.of(context).colorScheme.primary, + backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest, + ), + ), + const SizedBox(width: 10), + ], + ), + ], + ) + ), + ); } } \ No newline at end of file diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index caab9fa..2a052f6 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -8,8 +8,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/live/live_logs_screen.dart'; import 'package:adguard_home_manager/screens/logs/filters/logs_filters_modal.dart'; +import 'package:adguard_home_manager/widgets/floating_search_bar.dart'; -import 'package:adguard_home_manager/config/globals.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/providers/live_logs_provider.dart'; @@ -61,9 +61,10 @@ class LogsListAppBar extends StatelessWidget { void showSearchDialog() { showDialog( context: context, - builder: (context) => _Search( + builder: (context) => FloatingSearchBar( + existingSearchValue: logsProvider.appliedFilters.searchText ?? "", searchButtonRenderBox: _searchButtonKey.currentContext?.findRenderObject() as RenderBox?, - onSearch: (v) { + onSearchCompleted: (v) { logsProvider.setAppliedFilters( AppliedFiters( selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, @@ -73,6 +74,16 @@ class LogsListAppBar extends StatelessWidget { ); logsProvider.filterLogs(); }, + onSearchFieldUpdated: (v) { + if (v == "") { + logsProvider.setSearchText(null); + return; + } + logsProvider.setSearchText(v); + }, + onSearchFieldCleared: () { + logsProvider.setSearchText(null); + }, ), ); } @@ -279,106 +290,3 @@ class LogsListAppBar extends StatelessWidget { } } -class _Search extends StatefulWidget { - final void Function(String) onSearch; - final RenderBox? searchButtonRenderBox; - - const _Search({ - required this.onSearch, - required this.searchButtonRenderBox, - }); - - @override - State<_Search> createState() => _SearchState(); -} - -class _SearchState extends State<_Search> { - final _searchController = TextEditingController(); - - @override - void initState() { - final logsProvider = Provider.of(context, listen: false); - _searchController.text = logsProvider.appliedFilters.searchText ?? ""; - - super.initState(); - } - - @override - Widget build(BuildContext context) { - final logsProvider = Provider.of(context); - - final position = widget.searchButtonRenderBox?.localToGlobal(Offset.zero); - final topPadding = MediaQuery.of(globalNavigatorKey.currentContext!).viewPadding.top; - - return GestureDetector( - onTap: () => Navigator.pop(context), - child: Material( - color: Colors.transparent, - child: LayoutBuilder( - builder: (context, constraints) { - final double width = constraints.maxWidth - 32 > 500 ? 500 : constraints.maxWidth - 32; - return Stack( - alignment: Alignment.topCenter, - children: [ - Positioned( - top: position != null ? position.dy - topPadding : topPadding, - child: SizedBox( - width: width, - child: GestureDetector( - onTap: () => {}, - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(16) - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - child: TextFormField( - controller: _searchController, - onChanged: (v) { - if (v == "") { - logsProvider.setSearchText(null); - return; - } - logsProvider.setSearchText(v); - }, - onFieldSubmitted: (v) { - widget.onSearch(v); - Navigator.pop(context); - }, - autofocus: true, - decoration: InputDecoration( - hintText: AppLocalizations.of(context)!.search, - prefixIcon: const Icon(Icons.search_rounded), - border: InputBorder.none, - filled: true, - fillColor: Colors.grey.withOpacity(0.2), - suffixIcon: _searchController.text != "" - ? IconButton( - onPressed: () { - _searchController.text = ""; - logsProvider.setSearchText(null); - }, - icon: const Icon( - Icons.close_rounded, - size: 20, - ), - tooltip: AppLocalizations.of(context)!.clearSearch, - ) - : null, - contentPadding: const EdgeInsets.symmetric(vertical: 12), - ), - ), - ), - ), - ), - ), - ) - ], - ); - } - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/widgets/floating_search_bar.dart b/lib/widgets/floating_search_bar.dart new file mode 100644 index 0000000..bc09058 --- /dev/null +++ b/lib/widgets/floating_search_bar.dart @@ -0,0 +1,110 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/config/globals.dart'; + +class FloatingSearchBar extends StatefulWidget { + final void Function(String) onSearchCompleted; + final RenderBox? searchButtonRenderBox; + final String? existingSearchValue; + final void Function(String)? onSearchFieldUpdated; + final void Function()? onSearchFieldCleared; + + const FloatingSearchBar({ + super.key, + required this.onSearchCompleted, + required this.searchButtonRenderBox, + this.existingSearchValue, + this.onSearchFieldUpdated, + this.onSearchFieldCleared, + }); + + @override + State createState() => _SearchState(); +} + +class _SearchState extends State { + final _searchController = TextEditingController(); + + @override + void initState() { + if (widget.existingSearchValue != null) { + _searchController.text = widget.existingSearchValue!; + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { + final position = widget.searchButtonRenderBox?.localToGlobal(Offset.zero); + final topPadding = MediaQuery.of(globalNavigatorKey.currentContext!).viewPadding.top; + + return GestureDetector( + onTap: () => Navigator.pop(context), + child: Material( + color: Colors.transparent, + child: LayoutBuilder( + builder: (context, constraints) { + final double width = constraints.maxWidth - 32 > 500 ? 500 : constraints.maxWidth - 32; + return Stack( + alignment: Alignment.topCenter, + children: [ + Positioned( + top: position != null ? position.dy - topPadding : topPadding, + child: SizedBox( + width: width, + child: GestureDetector( + onTap: () => {}, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(16) + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: TextFormField( + controller: _searchController, + onChanged: widget.onSearchFieldUpdated, + onFieldSubmitted: (v) { + widget.onSearchCompleted(v); + Navigator.pop(context); + }, + autofocus: true, + decoration: InputDecoration( + hintText: AppLocalizations.of(context)!.search, + prefixIcon: const Icon(Icons.search_rounded), + border: InputBorder.none, + filled: true, + fillColor: Colors.grey.withOpacity(0.2), + suffixIcon: _searchController.text != "" + ? IconButton( + onPressed: () { + setState(() => _searchController.text = ""); + if (widget.onSearchFieldCleared != null) { + widget.onSearchFieldCleared!(); + } + }, + icon: const Icon( + Icons.close_rounded, + size: 20, + ), + tooltip: AppLocalizations.of(context)!.clearSearch, + ) + : null, + contentPadding: const EdgeInsets.symmetric(vertical: 12), + ), + ), + ), + ), + ), + ), + ) + ], + ); + } + ), + ), + ); + } +} \ No newline at end of file From b223076daebfcca745f5b9bc4f7e8ffbe7a54ab1 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 18:53:23 +0200 Subject: [PATCH 634/676] Fix bottom padding top items list --- .../home/top_items/top_items_screen.dart | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/screens/home/top_items/top_items_screen.dart b/lib/screens/home/top_items/top_items_screen.dart index 0f7465f..1524f75 100644 --- a/lib/screens/home/top_items/top_items_screen.dart +++ b/lib/screens/home/top_items/top_items_screen.dart @@ -187,16 +187,19 @@ class _TopItemsScreenState extends State { ), ), ), - if (sortedValues.isNotEmpty) SliverList.builder( - itemCount: sortedValues.length, - itemBuilder: (context, index) => _Item( - data: sortedValues[index], - isClient: widget.isClient, - options: widget.options, - total: total, - withProgressBar: widget.withProgressBar, - onTapEntry: widget.onTapEntry, - buildValue: widget.buildValue, + if (sortedValues.isNotEmpty) SliverPadding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewPadding.bottom), + sliver: SliverList.builder( + itemCount: sortedValues.length, + itemBuilder: (context, index) => _Item( + data: sortedValues[index], + isClient: widget.isClient, + options: widget.options, + total: total, + withProgressBar: widget.withProgressBar, + onTapEntry: widget.onTapEntry, + buildValue: widget.buildValue, + ), ), ), ], From c0f7449a954624129b52a30ee1262673f7260010 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 19:05:07 +0200 Subject: [PATCH 635/676] Fixed some colors --- lib/config/theme.dart | 6 ++++++ lib/screens/home/top_items/top_items_screen.dart | 2 +- lib/screens/settings/customization/theme_mode_button.dart | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/config/theme.dart b/lib/config/theme.dart index a9ffa71..93b5365 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -24,6 +24,9 @@ ThemeData lightTheme(ColorScheme? dynamicColorScheme) => ThemeData( navigationBarTheme: NavigationBarThemeData( surfaceTintColor: dynamicColorScheme?.surfaceTint ), + dialogTheme: DialogTheme( + surfaceTintColor: dynamicColorScheme?.surfaceTint + ), pageTransitionsTheme: const PageTransitionsTheme( builders: { TargetPlatform.android: PredictiveBackPageTransitionsBuilder() @@ -56,6 +59,9 @@ ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( navigationBarTheme: NavigationBarThemeData( surfaceTintColor: dynamicColorScheme?.surfaceTint ), + dialogTheme: DialogTheme( + surfaceTintColor: dynamicColorScheme?.surfaceTint + ), pageTransitionsTheme: const PageTransitionsTheme( builders: { TargetPlatform.android: PredictiveBackPageTransitionsBuilder() diff --git a/lib/screens/home/top_items/top_items_screen.dart b/lib/screens/home/top_items/top_items_screen.dart index 1524f75..bf0a0f5 100644 --- a/lib/screens/home/top_items/top_items_screen.dart +++ b/lib/screens/home/top_items/top_items_screen.dart @@ -377,7 +377,7 @@ class _Item extends StatelessWidget { percent: data.values.toList()[0]/total, barRadius: const Radius.circular(5), progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest, + backgroundColor: Theme.of(context).colorScheme.surfaceTint.withOpacity(0.2), ), ), const SizedBox(width: 10), diff --git a/lib/screens/settings/customization/theme_mode_button.dart b/lib/screens/settings/customization/theme_mode_button.dart index e48a511..ec949c0 100644 --- a/lib/screens/settings/customization/theme_mode_button.dart +++ b/lib/screens/settings/customization/theme_mode_button.dart @@ -44,7 +44,7 @@ class ThemeModeButton extends StatelessWidget { ? Theme.of(context).colorScheme.primary : greyBackgroundColor : disabled == null || disabled == false - ? Theme.of(context).colorScheme.surfaceContainerHighest + ? Theme.of(context).colorScheme.surfaceTint.withOpacity(0.1) : greyBackgroundColor, ) ), From 2f1e8d38a868804e995fcbeb710b468080a4b7df Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 19:16:41 +0200 Subject: [PATCH 636/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 3378718..f821dbf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.19.0-beta.1+142 +version: 2.19.0+143 environment: sdk: '>=2.18.1 <3.0.0' From a171eda41c602dc6b8aeb5c6c0d6903345327262 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 19:25:49 +0200 Subject: [PATCH 637/676] Updated workflow --- .github/workflows/release-stable.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 220c56d..45c9beb 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -24,15 +24,14 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: adore-me/read-yaml@v1.0.0 + uses: pietrobolcato/action-read-yaml@1.0.0 id: read_pubspec with: - file: './pubspec.yaml' - key-path: '["version"]' + config: ${{ github.workspace }}/pubspec.yaml - name: Save version on env variable id: save_version run: | - version=${{ steps.read_pubspec.outputs.data }} + version=${{ steps.read_pubspec.outputs['version'] }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV From 67bc6a1716df2b08e4733e72950c6c5a985f2944 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 19:27:04 +0200 Subject: [PATCH 638/676] Updated workflow --- .github/workflows/release-stable.yaml | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 45c9beb..9b0dd17 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -80,15 +80,14 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: adore-me/read-yaml@v1.0.0 + uses: pietrobolcato/action-read-yaml@1.0.0 id: read_pubspec with: - file: './pubspec.yaml' - key-path: '["version"]' + config: ${{ github.workspace }}/pubspec.yaml - name: Save version on env variable id: save_version run: | - version=${{ steps.read_pubspec.outputs.data }} + version=${{ steps.read_pubspec.outputs['version'] }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV @@ -140,15 +139,14 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: adore-me/read-yaml@v1.0.0 + uses: pietrobolcato/action-read-yaml@1.0.0 id: read_pubspec with: - file: './pubspec.yaml' - key-path: '["version"]' + config: ${{ github.workspace }}/pubspec.yaml - name: Save version on env variable id: save_version run: | - version=${{ steps.read_pubspec.outputs.data }} + version=${{ steps.read_pubspec.outputs['version'] }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV @@ -203,16 +201,14 @@ jobs: run: | [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Read pubspec.yaml - uses: adore-me/read-yaml@v1.0.0 + uses: pietrobolcato/action-read-yaml@1.0.0 id: read_pubspec with: - file: './pubspec.yaml' - key-path: '["version"]' + config: ${{ github.workspace }}/pubspec.yaml - name: Save version on env variable - shell: bash id: save_version run: | - version=${{ steps.read_pubspec.outputs.data }} + version=${{ steps.read_pubspec.outputs['version'] }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV From fc2305266fbc5a6f940863ed660af5630ba3f363 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 19:34:04 +0200 Subject: [PATCH 639/676] Updated workflow --- .github/workflows/release-stable.yaml | 28 +++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 9b0dd17..11750fe 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -24,14 +24,15 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: pietrobolcato/action-read-yaml@1.0.0 + uses: jbutcher5/read-yaml@1.6 id: read_pubspec with: - config: ${{ github.workspace }}/pubspec.yaml + file: './pubspec.yaml' # File to read from + key-path: '["version"]' - name: Save version on env variable id: save_version run: | - version=${{ steps.read_pubspec.outputs['version'] }} + version=${{ steps.read_pubspec.outputs.data }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV @@ -80,14 +81,15 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: pietrobolcato/action-read-yaml@1.0.0 + uses: jbutcher5/read-yaml@1.6 id: read_pubspec with: - config: ${{ github.workspace }}/pubspec.yaml + file: './pubspec.yaml' + key-path: '["version"]' - name: Save version on env variable id: save_version run: | - version=${{ steps.read_pubspec.outputs['version'] }} + version=${{ steps.read_pubspec.outputs.data }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV @@ -139,14 +141,15 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: pietrobolcato/action-read-yaml@1.0.0 + uses: jbutcher5/read-yaml@1.6 id: read_pubspec with: - config: ${{ github.workspace }}/pubspec.yaml + file: './pubspec.yaml' + key-path: '["version"]' - name: Save version on env variable id: save_version run: | - version=${{ steps.read_pubspec.outputs['version'] }} + version=${{ steps.read_pubspec.outputs.data }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV @@ -201,14 +204,15 @@ jobs: run: | [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Read pubspec.yaml - uses: pietrobolcato/action-read-yaml@1.0.0 + uses: jbutcher5/read-yaml@1.6 id: read_pubspec with: - config: ${{ github.workspace }}/pubspec.yaml + file: './pubspec.yaml' + key-path: '["version"]' - name: Save version on env variable id: save_version run: | - version=${{ steps.read_pubspec.outputs['version'] }} + version=${{ steps.read_pubspec.outputs.data }} IFS='+' read -r -a split <<< "$version" echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV From 3055c3582b31ee4f56ca11a6d1d95bce87b059a4 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 19:46:45 +0200 Subject: [PATCH 640/676] Updated workflow --- .github/workflows/release-beta.yaml | 2 -- .github/workflows/release-stable.yaml | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 8f72ac4..3ded1c1 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -2,8 +2,6 @@ name: Compile and release beta build on: workflow_dispatch: - branches: - - beta jobs: build-android: diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 11750fe..01630ac 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -2,8 +2,6 @@ name: Compile and release production build on: workflow_dispatch: - branches: - - master jobs: build-android: @@ -210,6 +208,7 @@ jobs: file: './pubspec.yaml' key-path: '["version"]' - name: Save version on env variable + shell: bash id: save_version run: | version=${{ steps.read_pubspec.outputs.data }} From 7579e2d58008c5d390b678c393e7de29b50cd6f6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 21:14:58 +0200 Subject: [PATCH 641/676] Updated workflows --- .github/workflows/release-beta.yaml | 4 ++-- .github/workflows/release-stable.yaml | 8 ++++---- .vscode/settings.json | 6 +++++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml index 3ded1c1..854ee28 100644 --- a/.github/workflows/release-beta.yaml +++ b/.github/workflows/release-beta.yaml @@ -24,10 +24,10 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: adore-me/read-yaml@v1.0.0 + uses: JGeek00/read-yaml-files@2.0.0 id: read_pubspec with: - file: './pubspec.yaml' + file: './pubspec.yaml' # File to read from key-path: '["version"]' - name: Save version on env variable id: save_version diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml index 01630ac..0b0ae0c 100644 --- a/.github/workflows/release-stable.yaml +++ b/.github/workflows/release-stable.yaml @@ -22,7 +22,7 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: jbutcher5/read-yaml@1.6 + uses: JGeek00/read-yaml-files@2.0.0 id: read_pubspec with: file: './pubspec.yaml' # File to read from @@ -79,7 +79,7 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: jbutcher5/read-yaml@1.6 + uses: JGeek00/read-yaml-files@2.0.0 id: read_pubspec with: file: './pubspec.yaml' @@ -139,7 +139,7 @@ jobs: - name: Decode .env run: echo "${{ secrets.ENV }}" | base64 --decode > .env - name: Read pubspec.yaml - uses: jbutcher5/read-yaml@1.6 + uses: JGeek00/read-yaml-files@2.0.0 id: read_pubspec with: file: './pubspec.yaml' @@ -202,7 +202,7 @@ jobs: run: | [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - name: Read pubspec.yaml - uses: jbutcher5/read-yaml@1.6 + uses: JGeek00/read-yaml-files@2.0.0 id: read_pubspec with: file: './pubspec.yaml' diff --git a/.vscode/settings.json b/.vscode/settings.json index 791c93f..769a50d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,5 +12,9 @@ "editor.formatOnSave": false, "editor.formatOnPaste": false, "editor.formatOnType": false - } + }, + "cSpell.ignorePaths": [ + "/pubspec.yaml", + "/.github/workflows" + ] } \ No newline at end of file From 7bb7ad40c4a3358751039d477908dcd9f4c45604 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 22:32:26 +0200 Subject: [PATCH 642/676] Fixed some bugs --- lib/models/dns_statistics.dart | 2 +- lib/providers/dns_provider.dart | 28 +++++++++++-------- lib/screens/filters/add_button.dart | 2 ++ lib/screens/filters/custom_rules_list.dart | 2 +- lib/screens/home/appbar.dart | 1 + lib/screens/logs/filters/clients_modal.dart | 2 +- lib/screens/logs/log_tile.dart | 4 +++ .../statistics_settings.dart | 2 +- 8 files changed, 28 insertions(+), 15 deletions(-) diff --git a/lib/models/dns_statistics.dart b/lib/models/dns_statistics.dart index f279886..ca6c247 100644 --- a/lib/models/dns_statistics.dart +++ b/lib/models/dns_statistics.dart @@ -5,7 +5,7 @@ DnsStatistics dnsStatisticsFromJson(String str) => DnsStatistics.fromJson(json.d String dnsStatisticsToJson(DnsStatistics data) => json.encode(data.toJson()); class DnsStatistics { - final String timeUnits; + final String? timeUnits; final List> topQueriedDomains; final List> topClients; final List> topBlockedDomains; diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index 198053b..a59c3c5 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -151,20 +151,26 @@ class DnsProvider with ChangeNotifier { final result = await _serversProvider!.apiClient2!.setDnsConfig( data: value ); + + void updateValue(dynamic parameter, dynamic value) { + if (value != null) { + parameter = value; + } + } if (result.successful == true) { DnsInfo data = dnsInfo!; - data.ratelimit = value['ratelimit']; - data.ednsCsEnabled = value['edns_cs_enabled']; - data.dnssecEnabled = value['dnssec_enabled']; - data.disableIpv6 = value['disable_ipv6']; - data.blockingMode = value['blocking_mode']; - data.blockingIpv4 = value['blocking_ipv4']; - data.blockingIpv6 = value['blocking_ipv6']; - data.blockedResponseTtl = value['blocked_response_ttl']; - data.ratelimitSubnetLenIpv4 = value['ratelimit_subnet_len_ipv4']; - data.ratelimitSubnetLenIpv6 = value['ratelimit_subnet_len_ipv6']; - data.ratelimitWhitelist = value['ratelimit_whitelist']; + updateValue(data.ratelimit, value['ratelimit']); + updateValue(data.ednsCsEnabled, value['edns_cs_enabled']); + updateValue(data.dnssecEnabled, value['dnssec_enabled']); + updateValue(data.disableIpv6, value['disable_ipv6']); + updateValue(data.blockingMode, value['blocking_mode']); + updateValue(data.blockingIpv4, value['blocking_ipv4']); + updateValue(data.blockingIpv6, value['blocking_ipv6']); + updateValue(data.blockedResponseTtl, value['blocked_response_ttl']); + updateValue(data.ratelimitSubnetLenIpv4, value['ratelimit_subnet_len_ipv4']); + updateValue(data.ratelimitSubnetLenIpv6, value['ratelimit_subnet_len_ipv6']); + updateValue(data.ratelimitWhitelist, value['ratelimit_whitelist']); setDnsInfoData(data); return result; } diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 2eca7d4..1621b68 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -137,6 +137,8 @@ class AddFiltersButton extends StatelessWidget { } void confirmAddList({required String name, required String url, required String type}) async { + if (!context.mounted) return; + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingList); diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 304972f..4cd5bde 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -162,7 +162,7 @@ class _CustomRulesListState extends State { TextButton.icon( onPressed: () async { final result = await filteringProvider.fetchFilters(); - if (result == false) { + if (result == false && context.mounted) { showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 5cd481f..d4b447c 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -34,6 +34,7 @@ class HomeAppBar extends StatelessWidget { void navigateServers() { Future.delayed(const Duration(milliseconds: 0), (() { + if (!context.mounted) return; Navigator.of(context).push( MaterialPageRoute(builder: (context) => const Servers()) ); diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index 403f098..ef0e989 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -115,7 +115,7 @@ class _ClientsModalState extends State { void searchAddedClient(_ClientLog client) { final notIps = client.ids?.where((e) => isIpAddress(e) == false).toList(); - if (notIps == null) return; + if (notIps == null || notIps.isEmpty) return; logsProvider.setSearchText('"${notIps[0]}"'); Navigator.of(context).pop(); } diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index bed2e40..342817f 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -96,6 +96,8 @@ class LogTile extends StatelessWidget { } void blockUnblock({required String domain, required String newStatus}) async { + if (!context.mounted) return; + final ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingUserFilters); @@ -124,6 +126,8 @@ class LogTile extends StatelessWidget { } void confirmAddClient(Client client) async { + if (!context.mounted) return; + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingClient); diff --git a/lib/screens/settings/statistics_settings/statistics_settings.dart b/lib/screens/settings/statistics_settings/statistics_settings.dart index 67a2989..7f58d67 100644 --- a/lib/screens/settings/statistics_settings/statistics_settings.dart +++ b/lib/screens/settings/statistics_settings/statistics_settings.dart @@ -138,7 +138,7 @@ class _StatisticsSettingsState extends State { "enabled": _generalSwitch, "interval": _retentionTime == "custom" ? Duration(hours: int.parse(_customTimeController.text)).inMilliseconds - : int.parse(_retentionTime!), + : int.parse(_retentionTime ?? _retentionItems[0]), "ignored": _ignoredDomainsControllers.map((e) => e.controller.text).toList() } ); From b65dc35cb75b81336544e62be2509eda93ef46a8 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 11 Sep 2024 22:43:26 +0200 Subject: [PATCH 643/676] Exclude some sentry logs --- lib/main.dart | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index ecd9f7e..854dd43 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -169,6 +169,20 @@ void main() async { (options) { options.dsn = dotenv.env['SENTRY_DSN']; options.sendDefaultPii = false; + options.beforeSend = (event, hint) { + if (event.throwable is HttpException) { + return null; + } + + if ( + event.message?.formatted.contains("Unexpected character") ?? false || + (event.throwable != null && event.throwable!.toString().contains("Unexpected character")) + ) { + return null; // Exclude this event + } + + return event; + }; }, appRunner: () => startApp() ); From d903da00510f617ee0e278d804c10d8e6dbf3b98 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 12 Sep 2024 14:33:32 +0200 Subject: [PATCH 644/676] Removed app updates notifier due to a bug on the library --- lib/functions/check_app_updates.dart | 100 ++++++------- lib/main.dart | 6 - .../general_settings/general_settings.dart | 133 +++++++++--------- lib/widgets/layout.dart | 38 +++-- 4 files changed, 130 insertions(+), 147 deletions(-) diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart index e6137d7..504ba2c 100644 --- a/lib/functions/check_app_updates.dart +++ b/lib/functions/check_app_updates.dart @@ -1,57 +1,57 @@ -import 'dart:io'; +// import 'dart:io'; -import 'package:install_referrer/install_referrer.dart'; +// import 'package:install_referrer/install_referrer.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; -import 'package:adguard_home_manager/services/external_requests.dart'; -import 'package:adguard_home_manager/models/github_release.dart'; +// import 'package:adguard_home_manager/functions/compare_versions.dart'; +// import 'package:adguard_home_manager/services/external_requests.dart'; +// import 'package:adguard_home_manager/models/github_release.dart'; -Future checkAppUpdates({ - required String currentBuildNumber, - required void Function(GitHubRelease?) setUpdateAvailable, - required InstallationAppReferrer? installationSource, - required bool isBeta -}) async { - var result = isBeta - ? await ExternalRequests.getReleasesGitHub() - : await ExternalRequests.getReleaseData(); +// Future checkAppUpdates({ +// required String currentBuildNumber, +// required void Function(GitHubRelease?) setUpdateAvailable, +// required InstallationAppReferrer? installationSource, +// required bool isBeta +// }) async { +// var result = isBeta +// ? await ExternalRequests.getReleasesGitHub() +// : await ExternalRequests.getReleaseData(); - if (result.successful == true) { - late GitHubRelease gitHubRelease; - if (isBeta) { - gitHubRelease = (result.content as List).firstWhere((r) => r.prerelease == true); - } - else { - gitHubRelease = result.content as GitHubRelease; - } +// if (result.successful == true) { +// late GitHubRelease gitHubRelease; +// if (isBeta) { +// gitHubRelease = (result.content as List).firstWhere((r) => r.prerelease == true); +// } +// else { +// gitHubRelease = result.content as GitHubRelease; +// } - final update = gitHubUpdateExists( - currentBuildNumber: currentBuildNumber, - gitHubRelease: gitHubRelease, - isBeta: isBeta - ); +// final update = gitHubUpdateExists( +// currentBuildNumber: currentBuildNumber, +// gitHubRelease: gitHubRelease, +// isBeta: isBeta +// ); - if (update == true) { - setUpdateAvailable(gitHubRelease); +// if (update == true) { +// setUpdateAvailable(gitHubRelease); - if (Platform.isAndroid) { - if (installationSource == InstallationAppReferrer.androidManually) { - return gitHubRelease; - } - else { - return null; - } - } - else if (Platform.isIOS) { - return null; - } - else { - return gitHubRelease; - } - } - else { - setUpdateAvailable(null); - } - } - return null; -} \ No newline at end of file +// if (Platform.isAndroid) { +// if (installationSource == InstallationAppReferrer.androidManually) { +// return gitHubRelease; +// } +// else { +// return null; +// } +// } +// else if (Platform.isIOS) { +// return null; +// } +// else { +// return gitHubRelease; +// } +// } +// else { +// setUpdateAvailable(null); +// } +// } +// return null; +// } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 854dd43..10b1862 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:install_referrer/install_referrer.dart'; import 'package:provider/provider.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:dynamic_color/dynamic_color.dart'; @@ -79,11 +78,6 @@ void main() async { HttpOverrides.global = MyHttpOverrides(); } - if (Platform.isAndroid || Platform.isIOS) { - InstallationAppReferrer installationSource = await InstallReferrer.referrer; - appConfigProvider.setInstallationSource(installationSource); - } - final dbData = await loadDb(); serversProvider.setDbInstance(dbData['dbInstance']); serversProvider.saveFromDb(dbData['servers']); diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index 0029752..f32446d 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -1,9 +1,4 @@ -// ignore_for_file: use_build_context_synchronously - -import 'dart:io'; - import 'package:flutter/material.dart'; -import 'package:install_referrer/install_referrer.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -13,11 +8,8 @@ import 'package:adguard_home_manager/screens/settings/general_settings/top_items 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/check_app_updates.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/functions/open_url.dart'; -import 'package:adguard_home_manager/functions/app_update_download_link.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class GeneralSettings extends StatefulWidget { @@ -48,6 +40,7 @@ class _GeneralSettingsState extends State { required Future Function(bool) function }) async { final result = await function(newStatus); + if (!context.mounted) return; if (result == true) { showSnackbar( appConfigProvider: appConfigProvider, @@ -64,60 +57,60 @@ class _GeneralSettingsState extends State { } } - Future checkUpdatesAvailable() async { - setState(() => appUpdatesStatus = AppUpdatesStatus.checking); + // Future checkUpdatesAvailable() async { + // setState(() => appUpdatesStatus = AppUpdatesStatus.checking); - final res = await checkAppUpdates( - currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, - setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, - installationSource: appConfigProvider.installationSource, - isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), - ); + // final res = await checkAppUpdates( + // currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, + // setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, + // installationSource: appConfigProvider.installationSource, + // isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), + // ); - if (!mounted) return; - if (res != null) { - setState(() => appUpdatesStatus = AppUpdatesStatus.available); - } - else { - setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); - } - } + // if (!mounted) return; + // if (res != null) { + // setState(() => appUpdatesStatus = AppUpdatesStatus.available); + // } + // else { + // setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); + // } + // } - Widget generateAppUpdateStatus() { - if (appUpdatesStatus == AppUpdatesStatus.available) { - return IconButton( - onPressed: appConfigProvider.appUpdatesAvailable != null - ? () async { - final link = getAppUpdateDownloadLink(appConfigProvider.appUpdatesAvailable!); - if (link != null) { - openUrl(link); - } - } - : null, - icon: const Icon(Icons.download_rounded), - tooltip: AppLocalizations.of(context)!.downloadUpdate, - ); - } - else if (appUpdatesStatus == AppUpdatesStatus.checking) { - return const Padding( - padding: EdgeInsets.only(right: 16), - child: SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - strokeWidth: 3, - ) - ), - ); - } - else { - return IconButton( - onPressed: checkUpdatesAvailable, - icon: const Icon(Icons.refresh_rounded), - tooltip: AppLocalizations.of(context)!.checkUpdates, - ); - } - } + // Widget generateAppUpdateStatus() { + // if (appUpdatesStatus == AppUpdatesStatus.available) { + // return IconButton( + // onPressed: appConfigProvider.appUpdatesAvailable != null + // ? () async { + // final link = getAppUpdateDownloadLink(appConfigProvider.appUpdatesAvailable!); + // if (link != null) { + // openUrl(link); + // } + // } + // : null, + // icon: const Icon(Icons.download_rounded), + // tooltip: AppLocalizations.of(context)!.downloadUpdate, + // ); + // } + // else if (appUpdatesStatus == AppUpdatesStatus.checking) { + // return const Padding( + // padding: EdgeInsets.only(right: 16), + // child: SizedBox( + // width: 24, + // height: 24, + // child: CircularProgressIndicator( + // strokeWidth: 3, + // ) + // ), + // ); + // } + // else { + // return IconButton( + // onPressed: checkUpdatesAvailable, + // icon: const Icon(Icons.refresh_rounded), + // tooltip: AppLocalizations.of(context)!.checkUpdates, + // ); + // } + // } return Scaffold( appBar: AppBar( @@ -253,17 +246,17 @@ class _GeneralSettingsState extends State { right: 10 ) ), - if (!(Platform.isAndroid || Platform.isIOS) || (Platform.isAndroid && (appConfigProvider.installationSource == InstallationAppReferrer.androidManually ))) ...[ - SectionLabel(label: AppLocalizations.of(context)!.application), - CustomListTile( - icon: Icons.system_update_rounded, - title: AppLocalizations.of(context)!.appUpdates, - subtitle: appConfigProvider.appUpdatesAvailable != null - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.usingLatestVersion, - trailing: generateAppUpdateStatus() - ) - ] + // if (!(Platform.isAndroid || Platform.isIOS) || (Platform.isAndroid && (appConfigProvider.installationSource == InstallationAppReferrer.androidManually ))) ...[ + // SectionLabel(label: AppLocalizations.of(context)!.application), + // CustomListTile( + // icon: Icons.system_update_rounded, + // title: AppLocalizations.of(context)!.appUpdates, + // subtitle: appConfigProvider.appUpdatesAvailable != null + // ? AppLocalizations.of(context)!.updateAvailable + // : AppLocalizations.of(context)!.usingLatestVersion, + // trailing: generateAppUpdateStatus() + // ) + // ] ], ), ) diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index 9a42415..119bee1 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -1,14 +1,10 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/widgets/update_modal.dart'; import 'package:adguard_home_manager/widgets/system_ui_overlay_style.dart'; -import 'package:adguard_home_manager/functions/check_app_updates.dart'; -import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; import 'package:adguard_home_manager/config/sizes.dart'; @@ -37,23 +33,23 @@ class _LayoutState extends State with WidgetsBindingObserver { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { - if (kDebugMode) return; // Don't check for app updates on debug mode - final appConfigProvider = Provider.of(context, listen: false); - final result = await checkAppUpdates( - currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, - installationSource: appConfigProvider.installationSource, - setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, - isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), - ); - if (result != null && appConfigProvider.doNotRememberVersion != result.tagName && mounted) { - await showDialog( - context: context, - builder: (context) => UpdateModal( - gitHubRelease: result, - onDownload: (link, version) => openUrl(link), - ), - ); - } + // if (kDebugMode) return; // Don't check for app updates on debug mode + // final appConfigProvider = Provider.of(context, listen: false); + // final result = await checkAppUpdates( + // currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, + // installationSource: appConfigProvider.installationSource, + // setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, + // isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), + // ); + // if (result != null && appConfigProvider.doNotRememberVersion != result.tagName && mounted) { + // await showDialog( + // context: context, + // builder: (context) => UpdateModal( + // gitHubRelease: result, + // onDownload: (link, version) => openUrl(link), + // ), + // ); + // } }); } From 0d0321a5abce71ebf6c70b3dd30d1e60fa4a0f32 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 12 Sep 2024 14:47:21 +0200 Subject: [PATCH 645/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index f821dbf..2fd5ee4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.19.0+143 +version: 2.19.1+144 environment: sdk: '>=2.18.1 <3.0.0' From a36335ef9203059ff6364cb868d6463c29e26e23 Mon Sep 17 00:00:00 2001 From: Jeremy Wong Date: Sun, 29 Sep 2024 08:41:07 +1000 Subject: [PATCH 646/676] Fix missing 'path' in serverObj --- lib/widgets/add_server/add_server_modal.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index ec00ff6..7164ba0 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -142,6 +142,7 @@ class _AddServerModalState extends State { port: portController.text != '' ? int.parse(portController.text) : null, user: userController.text != "" ? userController.text : null, password: passwordController.text != "" ? passwordController.text : null, + path: pathController.text != "" ? pathController.text : null, defaultServer: defaultServer, authToken: homeAssistant == true ? encodeBase64UserPass(userController.text, passwordController.text) From d7392e4b8d167f08802e46b55ad670fc8f9a21f2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 1 Oct 2024 14:59:24 +0200 Subject: [PATCH 647/676] Updated compileSdkVersion to 35 --- README.md | 1 - android/app/build.gradle | 10 ++- .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/settings.gradle | 2 +- lib/functions/check_app_updates.dart | 57 ----------------- lib/providers/app_config_provider.dart | 12 ---- pubspec.lock | 64 ++++++++----------- pubspec.yaml | 5 +- .../flutter/generated_plugin_registrant.cc | 3 - windows/flutter/generated_plugins.cmake | 2 +- 10 files changed, 37 insertions(+), 121 deletions(-) delete mode 100644 lib/functions/check_app_updates.dart diff --git a/README.md b/README.md index d46c921..843bff8 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,6 @@ If you like the project and you want to contribute with the development, you can - [flutter custom tabs](https://pub.dev/packages/flutter_custom_tabs) - [shared preferences](https://pub.dev/packages/shared_preferences) - [window manager](https://pub.dev/packages/window_manager) -- [install referrer](https://pub.dev/packages/install_referrer)
        diff --git a/android/app/build.gradle b/android/app/build.gradle index 29785d0..ab6291c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -29,8 +29,9 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 34 - ndkVersion flutter.ndkVersion + namespace "com.jgeek00.adguard_home_manager" + compileSdkVersion 35 + ndkVersion "26.1.10909125" compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -46,12 +47,9 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.jgeek00.adguard_home_manager" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. minSdkVersion 26 - targetSdkVersion 34 + targetSdkVersion 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 3c472b9..19cfad9 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index b14b9f7..e8481f5 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '7.4.2' apply false + id "com.android.application" version '8.6.0' apply false id "org.jetbrains.kotlin.android" version "1.8.20" apply false } diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart deleted file mode 100644 index 504ba2c..0000000 --- a/lib/functions/check_app_updates.dart +++ /dev/null @@ -1,57 +0,0 @@ -// import 'dart:io'; - -// import 'package:install_referrer/install_referrer.dart'; - -// import 'package:adguard_home_manager/functions/compare_versions.dart'; -// import 'package:adguard_home_manager/services/external_requests.dart'; -// import 'package:adguard_home_manager/models/github_release.dart'; - -// Future checkAppUpdates({ -// required String currentBuildNumber, -// required void Function(GitHubRelease?) setUpdateAvailable, -// required InstallationAppReferrer? installationSource, -// required bool isBeta -// }) async { -// var result = isBeta -// ? await ExternalRequests.getReleasesGitHub() -// : await ExternalRequests.getReleaseData(); - -// if (result.successful == true) { -// late GitHubRelease gitHubRelease; -// if (isBeta) { -// gitHubRelease = (result.content as List).firstWhere((r) => r.prerelease == true); -// } -// else { -// gitHubRelease = result.content as GitHubRelease; -// } - -// final update = gitHubUpdateExists( -// currentBuildNumber: currentBuildNumber, -// gitHubRelease: gitHubRelease, -// isBeta: isBeta -// ); - -// if (update == true) { -// setUpdateAvailable(gitHubRelease); - -// if (Platform.isAndroid) { -// if (installationSource == InstallationAppReferrer.androidManually) { -// return gitHubRelease; -// } -// else { -// return null; -// } -// } -// else if (Platform.isIOS) { -// return null; -// } -// else { -// return gitHubRelease; -// } -// } -// else { -// setUpdateAvailable(null); -// } -// } -// return null; -// } \ No newline at end of file diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 3b843b9..bb6887c 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/scheduler.dart'; -import 'package:install_referrer/install_referrer.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -58,8 +57,6 @@ class AppConfigProvider with ChangeNotifier { GitHubRelease? _appUpdatesAvailable; - InstallationAppReferrer? _installationSource; - PackageInfo? get getAppInfo { return _appInfo; } @@ -162,10 +159,6 @@ class AppConfigProvider with ChangeNotifier { return _appUpdatesAvailable; } - InstallationAppReferrer? get installationSource { - return _installationSource; - } - List get homeTopItemsOrder { return _homeTopItemsOrder; } @@ -227,11 +220,6 @@ class AppConfigProvider with ChangeNotifier { notifyListeners(); } - void setInstallationSource(InstallationAppReferrer value) { - _installationSource = value; - notifyListeners(); - } - Future setOverrideSslCheck(bool status) async { try { sharedPreferencesInstance.setBool('overrideSslCheck', status); diff --git a/pubspec.lock b/pubspec.lock index e7c67eb..0b93bac 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -282,18 +282,18 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + sha256: "619817c4b65b322b5104b6bb6dfe6cda62d9729bd7ad4303ecc8b4e690a67a77" url: "https://pub.dev" source: hosted - version: "0.13.1" + version: "0.14.1" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" flutter_localizations: dependency: "direct main" description: flutter @@ -303,10 +303,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: a23c41ee57573e62fc2190a1f36a0480c4d90bde3a8a8d7126e5d5992fb53fb7 + sha256: e17575ca576a34b46c58c91f9948891117a1bd97815d2e661813c7f90c647a78 url: "https://pub.dev" source: hosted - version: "0.7.3+1" + version: "0.7.3+2" flutter_native_splash: dependency: "direct dev" description: @@ -373,14 +373,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.2.0" - install_referrer: - dependency: "direct main" - description: - name: install_referrer - sha256: "901c56d24ee3c3010dfd0bbebf305ed6b4b0f3fe969192081c167590a64cd78b" - url: "https://pub.dev" - source: hosted - version: "1.2.1" intl: dependency: "direct main" description: @@ -425,10 +417,10 @@ packages: dependency: transitive description: name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" list_counter: dependency: transitive description: @@ -601,18 +593,18 @@ packages: dependency: transitive description: name: sentry - sha256: "1af8308298977259430d118ab25be8e1dda626cdefa1e6ce869073d530d39271" + sha256: "033287044a6644a93498969449d57c37907e56f5cedb17b88a3ff20a882261dd" url: "https://pub.dev" source: hosted - version: "8.8.0" + version: "8.9.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "18fe4d125c2d529bd6127200f0d2895768266a8c60b4fb50b2086fd97e1a4ab2" + sha256: "3780b5a0bb6afd476857cfbc6c7444d969c29a4d9bd1aa5b6960aa76c65b737a" url: "https://pub.dev" source: hosted - version: "8.8.0" + version: "8.9.0" shared_preferences: dependency: "direct main" description: @@ -694,26 +686,26 @@ packages: dependency: "direct main" description: name: sqflite - sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d + sha256: ff5a2436ef8ebdfda748fbfe957f9981524cb5ff11e7bafa8c42771840e8a788 url: "https://pub.dev" source: hosted - version: "2.3.3+1" + version: "2.3.3+2" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "7b41b6c3507854a159e24ae90a8e3e9cc01eb26a477c118d6dca065b5f55453e" + sha256: "2d8e607db72e9cb7748c9c6e739e2c9618320a5517de693d5a24609c4671b1a4" url: "https://pub.dev" source: hosted - version: "2.5.4+2" + version: "2.5.4+4" sqflite_common_ffi: dependency: "direct main" description: name: sqflite_common_ffi - sha256: "4d6137c29e930d6e4a8ff373989dd9de7bac12e3bc87bce950f6e844e8ad3bb5" + sha256: a6057d4c87e9260ba1ec436ebac24760a110589b9c0a859e128842eb69a7ef04 url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.3+1" sqlite3: dependency: transitive description: @@ -758,10 +750,10 @@ packages: dependency: transitive description: name: synchronized - sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255 + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -838,10 +830,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" url_launcher_platform_interface: dependency: transitive description: @@ -870,10 +862,10 @@ packages: dependency: "direct main" description: name: uuid - sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77 + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.5.1" vector_graphics: dependency: transitive description: @@ -918,10 +910,10 @@ packages: dependency: transitive description: name: web - sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.1.0" win32: dependency: transitive description: @@ -934,10 +926,10 @@ packages: dependency: transitive description: name: win32_registry - sha256: "723b7f851e5724c55409bb3d5a32b203b3afe8587eaf5dafb93a5fed8ecda0d6" + sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" url: "https://pub.dev" source: hosted - version: "1.1.4" + version: "1.1.5" window_manager: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2fd5ee4..4007ef8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -70,7 +70,6 @@ dependencies: url_launcher: ^6.2.4 shared_preferences: ^2.2.2 window_manager: ^0.4.2 - install_referrer: ^1.2.1 dev_dependencies: flutter_test: @@ -81,8 +80,8 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^4.0.0 - flutter_launcher_icons: ^0.13.1 + flutter_lints: ^5.0.0 + flutter_launcher_icons: ^0.14.1 flutter_native_splash: ^2.3.8 # For information on the generic Dart part of this file, see the diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 683e616..e79e36b 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -18,8 +17,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); ScreenRetrieverPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); - SentryFlutterPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("SentryFlutterPlugin")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b2ba396..38558c8 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,13 +5,13 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color screen_retriever - sentry_flutter sqlite3_flutter_libs url_launcher_windows window_manager ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + sentry_flutter ) set(PLUGIN_BUNDLED_LIBRARIES) From 9d4c0028138048b69597b19ff0526788214d8789 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 1 Oct 2024 15:00:18 +0200 Subject: [PATCH 648/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 4007ef8..e1bb529 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.19.1+144 +version: 2.19.2+145 environment: sdk: '>=2.18.1 <3.0.0' From aa511f8c4273cb16dd491cf9c3e51a4b1ef8ad5d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 1 Oct 2024 16:21:00 +0200 Subject: [PATCH 649/676] Updated macos pods --- macos/Podfile.lock | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 54fe2f5..e815ee7 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -8,11 +8,11 @@ PODS: - FlutterMacOS - screen_retriever (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.35.1) - - sentry_flutter (8.8.0): + - Sentry/HybridSDK (8.36.0) + - sentry_flutter (8.9.0): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.35.1) + - Sentry/HybridSDK (= 8.36.0) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS @@ -37,8 +37,6 @@ PODS: - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree - - store_checker (0.0.1): - - FlutterMacOS - url_launcher_macos (0.0.1): - FlutterMacOS - window_manager (0.2.0): @@ -54,7 +52,6 @@ DEPENDENCIES: - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) - - store_checker (from `Flutter/ephemeral/.symlinks/plugins/store_checker/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) @@ -82,8 +79,6 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin sqlite3_flutter_libs: :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos - store_checker: - :path: Flutter/ephemeral/.symlinks/plugins/store_checker/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos window_manager: @@ -95,14 +90,13 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 - Sentry: 1fe34e9c2cbba1e347623610d26db121dcb569f1 - sentry_flutter: a39c2a2d67d5e5b9cb0b94a4985c76dd5b3fc737 + Sentry: f8374b5415bc38dfb5645941b3ae31230fbeae57 + sentry_flutter: 0eb93e5279eb41e2392212afe1ccd2fecb4f8cbe shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb sqlite3_flutter_libs: 5ca46c1a04eddfbeeb5b16566164aa7ad1616e7b - store_checker: 387169de0dffe57b6370d54cc027e9f95051b57f - url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 + url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 From 1b5f258c96f6feb74652e34d031a911b6e329a15 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 1 Oct 2024 18:50:37 +0200 Subject: [PATCH 650/676] Fixed windows installer builder --- windows/innosetup_installer_builder.iss | 1 - 1 file changed, 1 deletion(-) diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index b2a93ce..ed5df88 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -41,7 +41,6 @@ Source: "..\build\windows\x64\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Source: "..\build\windows\x64\runner\Release\dynamic_color_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\screen_retriever_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\build\windows\x64\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion From 2a0db8495928b69f5e3c4033cf1ae4b722cf7ede Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Jan 2025 20:47:10 +0100 Subject: [PATCH 651/676] Updated libraries and other stuff --- linux/flutter/generated_plugin_registrant.cc | 8 +- linux/flutter/generated_plugins.cmake | 2 +- macos/Flutter/GeneratedPluginRegistrant.swift | 6 +- pubspec.lock | 306 +++++++++++------- pubspec.yaml | 6 +- .../flutter/generated_plugin_registrant.cc | 9 +- windows/flutter/generated_plugins.cmake | 4 +- 7 files changed, 204 insertions(+), 137 deletions(-) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index fd3f3f5..4fbee04 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,7 +7,7 @@ #include "generated_plugin_registrant.h" #include -#include +#include #include #include #include @@ -17,9 +17,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) dynamic_color_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); - g_autoptr(FlPluginRegistrar) screen_retriever_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin"); - screen_retriever_plugin_register_with_registrar(screen_retriever_registrar); + g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin"); + screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar); g_autoptr(FlPluginRegistrar) sentry_flutter_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin"); sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 307410d..787cc64 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,7 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color - screen_retriever + screen_retriever_linux sentry_flutter sqlite3_flutter_libs url_launcher_linux diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 28ea475..69e9dbc 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,10 +8,10 @@ import Foundation import device_info_plus import dynamic_color import package_info_plus -import screen_retriever +import screen_retriever_macos import sentry_flutter import shared_preferences_foundation -import sqflite +import sqflite_darwin import sqlite3_flutter_libs import url_launcher_macos import window_manager @@ -20,7 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) - ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) + ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin")) SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/pubspec.lock b/pubspec.lock index 0b93bac..da7317f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,18 +29,18 @@ packages: dependency: transitive description: name: archive - sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + sha256: "6199c74e3db4fbfbd04f66d739e72fe11c8a8957d5f219f1f4482dbde6420b5a" url: "https://pub.dev" source: hosted - version: "3.6.1" + version: "4.0.2" args: dependency: transitive description: name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.6.0" async: dependency: "direct main" description: @@ -77,10 +77,10 @@ packages: dependency: transitive description: name: cli_util - sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c url: "https://pub.dev" source: hosted - version: "0.4.1" + version: "0.4.2" clock: dependency: transitive description: @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" contextmenu: dependency: "direct main" description: @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: crypto - sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" csslib: dependency: transitive description: @@ -133,18 +133,18 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 + sha256: b37d37c2f912ad4e8ec694187de87d05de2a3cb82b465ff1f65f65a2d05de544 url: "https://pub.dev" source: hosted - version: "10.1.2" + version: "11.2.1" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba" + sha256: "0b04e02b30791224b31969eb1b50d723498f402971bff3630bca2ba839bd1ed2" url: "https://pub.dev" source: hosted - version: "7.0.1" + version: "7.0.2" dynamic_color: dependency: "direct main" description: @@ -157,10 +157,10 @@ packages: dependency: transitive description: name: equatable - sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.7" expandable: dependency: "direct main" description: @@ -189,26 +189,26 @@ packages: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" fixnum: dependency: transitive description: name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" fl_chart: dependency: "direct main" description: name: fl_chart - sha256: "94307bef3a324a0d329d3ab77b2f0c6e5ed739185ffc029ed28c0f9b019ea7ef" + sha256: "5276944c6ffc975ae796569a826c38a62d2abcf264e26b88fa6f482e107f4237" url: "https://pub.dev" source: hosted - version: "0.69.0" + version: "0.70.2" flutter: dependency: "direct main" description: flutter @@ -266,10 +266,10 @@ packages: dependency: "direct main" description: name: flutter_dotenv - sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77" + sha256: b7c7be5cd9f6ef7a78429cabd2774d3c4af50e79cb2b7593e3d5d763ef95c61b url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.2.1" flutter_html: dependency: "direct main" description: @@ -282,10 +282,10 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: "619817c4b65b322b5104b6bb6dfe6cda62d9729bd7ad4303ecc8b4e690a67a77" + sha256: bfa04787c85d80ecb3f8777bde5fc10c3de809240c48fa061a2c2bf15ea5211c url: "https://pub.dev" source: hosted - version: "0.14.1" + version: "0.14.3" flutter_lints: dependency: "direct dev" description: @@ -303,18 +303,18 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: e17575ca576a34b46c58c91f9948891117a1bd97815d2e661813c7f90c647a78 + sha256: e37f4c69a07b07bb92622ef6b131a53c9aae48f64b176340af9e8e5238718487 url: "https://pub.dev" source: hosted - version: "0.7.3+2" + version: "0.7.5" flutter_native_splash: dependency: "direct dev" description: name: flutter_native_splash - sha256: aa06fec78de2190f3db4319dd60fdc8d12b2626e93ef9828633928c2dcaea840 + sha256: "7062602e0dbd29141fb8eb19220b5871ca650be5197ab9c1f193a28b17537bc7" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.4" flutter_reorderable_list: dependency: "direct main" description: @@ -327,10 +327,10 @@ packages: dependency: "direct main" description: name: flutter_svg - sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b url: "https://pub.dev" source: hosted - version: "2.0.10+1" + version: "2.0.17" flutter_test: dependency: "direct dev" description: flutter @@ -353,26 +353,26 @@ packages: dependency: "direct main" description: name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.3.0" http_parser: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.2" image: dependency: transitive description: name: image - sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" + sha256: "8346ad4b5173924b5ddddab782fc7d8a6300178c8b1dc427775405a01701c4a6" url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "4.5.2" intl: dependency: "direct main" description: @@ -393,18 +393,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" url: "https://pub.dev" source: hosted - version: "10.0.5" + version: "10.0.7" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.8" leak_tracker_testing: dependency: transitive description: @@ -417,10 +417,10 @@ packages: dependency: transitive description: name: lints - sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.1.1" list_counter: dependency: transitive description: @@ -433,10 +433,10 @@ packages: dependency: "direct main" description: name: markdown - sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051 + sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" url: "https://pub.dev" source: hosted - version: "7.2.2" + version: "7.3.0" matcher: dependency: transitive description: @@ -473,18 +473,18 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: a75164ade98cb7d24cfd0a13c6408927c6b217fa60dee5a7ff5c116a58f28918 + sha256: "739e0a5c3c4055152520fa321d0645ee98e932718b4c8efeeb51451968fe0790" url: "https://pub.dev" source: hosted - version: "8.0.2" + version: "8.1.3" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66 + sha256: a5ef9986efc7bf772f2696183a3992615baa76c1ffb1189318dd8803778fb05b url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" path: dependency: transitive description: @@ -497,10 +497,10 @@ packages: dependency: transitive description: name: path_parsing - sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" path_provider_linux: dependency: transitive description: @@ -529,10 +529,10 @@ packages: dependency: "direct main" description: name: percent_indicator - sha256: c37099ad833a883c9d71782321cb65c3a848c21b6939b6185f0ff6640d05814c + sha256: "0d77d5c6fa9b7f60202cedf748b568ba9ba38d3f30405d6ceae4da76f5185462" url: "https://pub.dev" source: hosted - version: "4.2.3" + version: "4.2.4" petitparser: dependency: transitive description: @@ -553,10 +553,10 @@ packages: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.1.6" plugin_platform_interface: dependency: transitive description: @@ -565,6 +565,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + posix: + dependency: transitive + description: + name: posix + sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a + url: "https://pub.dev" + source: hosted + version: "6.0.1" provider: dependency: "direct main" description: @@ -577,10 +585,42 @@ packages: dependency: transitive description: name: screen_retriever - sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90" + sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" url: "https://pub.dev" source: hosted - version: "0.1.9" + version: "0.2.0" + screen_retriever_linux: + dependency: transitive + description: + name: screen_retriever_linux + sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_macos: + dependency: transitive + description: + name: screen_retriever_macos + sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_platform_interface: + dependency: transitive + description: + name: screen_retriever_platform_interface + sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_windows: + dependency: transitive + description: + name: screen_retriever_windows + sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" + url: "https://pub.dev" + source: hosted + version: "0.2.0" segmented_button_slide: dependency: "direct main" description: @@ -593,42 +633,42 @@ packages: dependency: transitive description: name: sentry - sha256: "033287044a6644a93498969449d57c37907e56f5cedb17b88a3ff20a882261dd" + sha256: "576ad83415102ba2060142a6701611abc6e67a55af1d7ab339cedd3ba1b0f84c" url: "https://pub.dev" source: hosted - version: "8.9.0" + version: "8.12.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "3780b5a0bb6afd476857cfbc6c7444d969c29a4d9bd1aa5b6960aa76c65b737a" + sha256: dc3761e8659839cc67a18432d9f12e5531affb7ff68e196dbb56846909b5dfdc url: "https://pub.dev" source: hosted - version: "8.9.0" + version: "8.12.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" + sha256: a752ce92ea7540fc35a0d19722816e04d0e72828a4200e83a98cf1a1eb524c9a url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.5" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" + sha256: "138b7bbbc7f59c56236e426c37afb8f78cbc57b094ac64c440e0bb90e380a4f5" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.2" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.4" shared_preferences_linux: dependency: transitive description: @@ -665,7 +705,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -686,50 +726,74 @@ packages: dependency: "direct main" description: name: sqflite - sha256: ff5a2436ef8ebdfda748fbfe957f9981524cb5ff11e7bafa8c42771840e8a788 + sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb" url: "https://pub.dev" source: hosted - version: "2.3.3+2" + version: "2.4.1" + sqflite_android: + dependency: transitive + description: + name: sqflite_android + sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" + url: "https://pub.dev" + source: hosted + version: "2.4.0" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "2d8e607db72e9cb7748c9c6e739e2c9618320a5517de693d5a24609c4671b1a4" + sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709" url: "https://pub.dev" source: hosted - version: "2.5.4+4" + version: "2.5.4+6" sqflite_common_ffi: dependency: "direct main" description: name: sqflite_common_ffi - sha256: a6057d4c87e9260ba1ec436ebac24760a110589b9c0a859e128842eb69a7ef04 + sha256: "883dd810b2b49e6e8c3b980df1829ef550a94e3f87deab5d864917d27ca6bf36" url: "https://pub.dev" source: hosted - version: "2.3.3+1" + version: "2.3.4+4" + sqflite_darwin: + dependency: transitive + description: + name: sqflite_darwin + sha256: "22adfd9a2c7d634041e96d6241e6e1c8138ca6817018afc5d443fef91dcefa9c" + url: "https://pub.dev" + source: hosted + version: "2.4.1+1" + sqflite_platform_interface: + dependency: transitive + description: + name: sqflite_platform_interface + sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + url: "https://pub.dev" + source: hosted + version: "2.4.0" sqlite3: dependency: transitive description: name: sqlite3 - sha256: "45f168ae2213201b54e09429ed0c593dc2c88c924a1488d6f9c523a255d567cb" + sha256: "35d3726fe18ab1463403a5cc8d97dbc81f2a0b08082e8173851363fcc97b6627" url: "https://pub.dev" source: hosted - version: "2.4.6" + version: "2.7.2" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: "62bbb4073edbcdf53f40c80775f33eea01d301b7b81417e5b3fb7395416258c1" + sha256: "50a7e3f294c741d3142eed0ff228e38498334e11e0ccb9d73e0496e005949e44" url: "https://pub.dev" source: hosted - version: "0.5.24" + version: "0.5.29" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" stream_channel: dependency: transitive description: @@ -742,10 +806,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" synchronized: dependency: transitive description: @@ -766,26 +830,26 @@ packages: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.3" timezone: dependency: "direct main" description: name: timezone - sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" + sha256: ffc9d5f4d1193534ef051f9254063fa53d588609418c84299956c3db9383587d url: "https://pub.dev" source: hosted - version: "0.9.4" + version: "0.10.0" typed_data: dependency: transitive description: name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" universal_io: dependency: transitive description: @@ -798,42 +862,42 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab + sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" url: "https://pub.dev" source: hosted - version: "6.3.10" + version: "6.3.14" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e + sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.2" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" + sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" url_launcher_platform_interface: dependency: transitive description: @@ -846,18 +910,18 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.0" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.4" uuid: dependency: "direct main" description: @@ -870,26 +934,26 @@ packages: dependency: transitive description: name: vector_graphics - sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + sha256: "27d5fefe86fb9aace4a9f8375b56b3c292b64d8c04510df230f849850d912cb7" url: "https://pub.dev" source: hosted - version: "1.1.11+1" + version: "1.1.15" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" url: "https://pub.dev" source: hosted - version: "1.1.11+1" + version: "1.1.13" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" url: "https://pub.dev" source: hosted - version: "1.1.11+1" + version: "1.1.16" vector_math: dependency: transitive description: @@ -902,10 +966,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "14.3.0" web: dependency: transitive description: @@ -918,10 +982,10 @@ packages: dependency: transitive description: name: win32 - sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a" + sha256: "154360849a56b7b67331c21f09a386562d88903f90a1099c5987afc1912e1f29" url: "https://pub.dev" source: hosted - version: "5.5.4" + version: "5.10.0" win32_registry: dependency: transitive description: @@ -934,18 +998,18 @@ packages: dependency: "direct main" description: name: window_manager - sha256: ab8b2a7f97543d3db2b506c9d875e637149d48ee0c6a5cb5f5fd6e0dac463792 + sha256: "732896e1416297c63c9e3fb95aea72d0355f61390263982a47fd519169dc5059" url: "https://pub.dev" source: hosted - version: "0.4.2" + version: "0.4.3" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" xml: dependency: transitive description: @@ -958,10 +1022,10 @@ packages: dependency: transitive description: name: yaml - sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" sdks: - dart: ">=3.5.0 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.6.0 <4.0.0" + flutter: ">=3.27.0" diff --git a/pubspec.yaml b/pubspec.yaml index e1bb529..eb0a3f8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -45,10 +45,10 @@ dependencies: flutter_displaymode: ^0.6.0 dynamic_color: ^1.7.0 animations: ^2.0.10 - device_info_plus: ^10.1.0 + device_info_plus: ^11.2.1 uuid: ^4.2.1 expandable: ^5.0.1 - fl_chart: ^0.69.0 + fl_chart: ^0.70.2 flutter_svg: ^2.0.9 percent_indicator: ^4.2.3 flutter_markdown: ^0.7.1 @@ -65,7 +65,7 @@ dependencies: pie_chart: ^5.4.0 segmented_button_slide: ^2.0.0 http: ^1.1.2 - timezone: ^0.9.2 + timezone: ^0.10.0 flutter_custom_tabs: ^2.0.0+1 url_launcher: ^6.2.4 shared_preferences: ^2.2.2 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index e79e36b..b0ea5ac 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,7 +7,8 @@ #include "generated_plugin_registrant.h" #include -#include +#include +#include #include #include #include @@ -15,8 +16,10 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { DynamicColorPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); - ScreenRetrieverPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); + ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi")); + SentryFlutterPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SentryFlutterPlugin")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 38558c8..5ab1216 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,14 +4,14 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color - screen_retriever + screen_retriever_windows + sentry_flutter sqlite3_flutter_libs url_launcher_windows window_manager ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - sentry_flutter ) set(PLUGIN_BUNDLED_LIBRARIES) From 06c9f7c771bedf6f1ef80b0095b1482b7c5c32eb Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Jan 2025 20:47:24 +0100 Subject: [PATCH 652/676] Added support for custom time in logs settings --- .../logs_settings/config_widgets.dart | 37 +++++++++-- .../settings/logs_settings/logs_settings.dart | 61 ++++++++++++++----- 2 files changed, 78 insertions(+), 20 deletions(-) diff --git a/lib/screens/settings/logs_settings/config_widgets.dart b/lib/screens/settings/logs_settings/config_widgets.dart index 002fd96..16700a9 100644 --- a/lib/screens/settings/logs_settings/config_widgets.dart +++ b/lib/screens/settings/logs_settings/config_widgets.dart @@ -12,13 +12,16 @@ class LogsConfigOptions extends StatelessWidget { final void Function(bool) updateGeneralSwitch; final bool anonymizeClientIp; final void Function(bool) updateAnonymizeClientIp; - final List retentionItems; - final double? retentionTime; - final void Function(double?) updateRetentionTime; + final List retentionItems; + final String? retentionTime; + final void Function(String?) updateRetentionTime; final void Function() onClear; final void Function() onConfirm; final List ignoredDomainsControllers; final void Function(List) updateIgnoredDomainsControllers; + final TextEditingController customTimeController; + final String? customTimeError; + final void Function(String) validateCustomTime; const LogsConfigOptions({ super.key, @@ -32,7 +35,10 @@ class LogsConfigOptions extends StatelessWidget { required this.onClear, required this.onConfirm, required this.ignoredDomainsControllers, - required this.updateIgnoredDomainsControllers + required this.updateIgnoredDomainsControllers, + required this.customTimeController, + required this.customTimeError, + required this.validateCustomTime, }); @override @@ -40,6 +46,7 @@ class LogsConfigOptions extends StatelessWidget { const Uuid uuid = Uuid(); final List dropdownItemTranslation = [ + AppLocalizations.of(context)!.custom, AppLocalizations.of(context)!.hours6, AppLocalizations.of(context)!.hours24, AppLocalizations.of(context)!.days7, @@ -67,7 +74,7 @@ class LogsConfigOptions extends StatelessWidget { }).toList() ); } - +print(retentionTime); return ListView( children: [ const SizedBox(height: 16), @@ -92,7 +99,7 @@ class LogsConfigOptions extends StatelessWidget { child: Text(dropdownItemTranslation[item.key]), )).toList(), value: retentionTime, - onChanged: (value) => updateRetentionTime(double.tryParse(value.toString())), + onChanged: (value) => updateRetentionTime(value.toString()), decoration: InputDecoration( border: const OutlineInputBorder( borderRadius: BorderRadius.all( @@ -104,6 +111,24 @@ class LogsConfigOptions extends StatelessWidget { borderRadius: BorderRadius.circular(20), ), ), + if (retentionTime == "custom") Padding( + padding: const EdgeInsets.only(top: 24, left: 16, right: 16), + child: TextFormField( + controller: customTimeController, + onChanged: validateCustomTime, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.schedule_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.customTimeInHours, + errorText: customTimeError + ), + keyboardType: TextInputType.number, + ), + ), Padding( padding: const EdgeInsets.only(top: 24, bottom: 8), child: Row( diff --git a/lib/screens/settings/logs_settings/logs_settings.dart b/lib/screens/settings/logs_settings/logs_settings.dart index 0d55ce5..c31304f 100644 --- a/lib/screens/settings/logs_settings/logs_settings.dart +++ b/lib/screens/settings/logs_settings/logs_settings.dart @@ -37,15 +37,18 @@ class _LogsSettingsState extends State { bool generalSwitch = false; bool anonymizeClientIp = false; - double? retentionTime; + String? retentionTime; List _ignoredDomainsControllers = []; + final _customTimeController = TextEditingController(); + String? _customTimeError = null; - List retentionItems = [ - 21600000, - 86400000, - 604800000, - 2592000000, - 7776000000 + List retentionItems = [ + "custom", + "21600000", + "86400000", + "604800000", + "2592000000", + "7776000000" ]; LoadStatus loadStatus = LoadStatus.loading; @@ -61,9 +64,10 @@ class _LogsSettingsState extends State { setState(() { generalSwitch = data.enabled ?? false; anonymizeClientIp = data.anonymizeClientIp ?? false; - retentionTime = data.interval != null - ? double.parse(data.interval.toString()) - : null; + retentionTime = retentionItems.contains(data.interval.toString()) ? data.interval.toString() : "custom"; + if (data.interval != null && !retentionItems.contains(data.interval.toString())) { + _customTimeController.text = (data.interval!/3.6e+6).toInt().toString(); + } if (data.ignored != null) { _ignoredDomainsControllers = data.ignored!.map((e) => DomainListItemController( id: uuid.v4(), @@ -79,6 +83,34 @@ class _LogsSettingsState extends State { } } + void validateCustomTime(String value) { + try { + final regex = RegExp(r'^\d+$'); + final parsed = int.parse(value); + if (!regex.hasMatch(value)) { + setState(() => _customTimeError = AppLocalizations.of(context)!.invalidTime); + } + else if (parsed < 1) { + setState(() => _customTimeError = AppLocalizations.of(context)!.notLess1Hour); + } + else { + setState(() => _customTimeError = null); + } + } catch (_) { + setState(() => _customTimeError = AppLocalizations.of(context)!.invalidTime); + } + } + + bool checkValidValues() { + if (_ignoredDomainsControllers.where((d) => d.controller.text == "" || d.error == true).isNotEmpty) { + return false; + } + if (retentionTime == "custom" && (_customTimeError != null || _customTimeController.text == "")) { + return false; + } + return true; + } + @override void initState() { loadData(); @@ -90,9 +122,7 @@ class _LogsSettingsState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - final validValues = _ignoredDomainsControllers.where( - (d) => d.controller.text == "" || d.error == true - ).isEmpty; + final validValues = checkValidValues(); void clearQueries() async { ProcessModal processModal = ProcessModal(); @@ -127,7 +157,7 @@ class _LogsSettingsState extends State { final result = await serversProvider.apiClient2!.updateQueryLogParameters( data: { "enabled": generalSwitch, - "interval": retentionTime, + "interval": retentionTime == "custom" ? int.parse(_customTimeController.text)*3.6e+6 : int.parse(retentionTime!) , "anonymize_client_ip": anonymizeClientIp, "ignored": _ignoredDomainsControllers.map((e) => e.controller.text).toList() } @@ -198,6 +228,9 @@ class _LogsSettingsState extends State { onConfirm: updateConfig, ignoredDomainsControllers: _ignoredDomainsControllers, updateIgnoredDomainsControllers: (v) => setState(() => _ignoredDomainsControllers = v), + customTimeController: _customTimeController, + customTimeError: _customTimeError, + validateCustomTime: validateCustomTime, ); case LoadStatus.error: From 791400f5655eb5c387787f7d37912bc44c77e04e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Jan 2025 20:55:54 +0100 Subject: [PATCH 653/676] Added settings links --- lib/constants/urls.dart | 2 ++ lib/l10n/app_en.arb | 6 ++++- lib/l10n/app_es.arb | 6 ++++- lib/screens/settings/settings.dart | 41 ++++++++---------------------- 4 files changed, 23 insertions(+), 32 deletions(-) diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart index b7eb069..0a8ece3 100644 --- a/lib/constants/urls.dart +++ b/lib/constants/urls.dart @@ -7,4 +7,6 @@ class Urls { static const String adGuardHomeReleasesTags = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/tags"; static const String googleSearchUrl = "https://www.google.com/search"; static const String connectionInstructions = "https://github.com/JGeek00/adguard-home-manager/wiki/Create-a-connection"; + static const String appDetailsWebpage = "https://apps.jgeek00.com/jlfed8mcgyz6laf"; + static const String jgeek00AppsWebpage = "https://apps.jgeek00.com"; } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 609c616..d72a148 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -797,5 +797,9 @@ "dnsServerAddressCopied": "DNS server address copied to the clipboard", "select": "Select", "liveLogs": "Live logs", - "hereWillAppearRealtimeLogs": "Here there will appear the logs on realtime." + "hereWillAppearRealtimeLogs": "Here there will appear the logs on realtime.", + "applicationDetails": "Application details", + "applicationDetailsDescription": "App repository, stores where it's available, and more", + "myOtherApps": "Check my other apps", + "myOtherAppsDescription": "Created by JGeek00" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 231eeaf..952104a 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -797,5 +797,9 @@ "dnsServerAddressCopied": "Dirección del servidor DNS copiada al portapapeles", "select": "Seleccionar", "liveLogs": "Registros en directo", - "hereWillAppearRealtimeLogs": "Aquí aparecerán los registros en tiempo real." + "hereWillAppearRealtimeLogs": "Aquí aparecerán los registros en tiempo real.", + "applicationDetails": "Detalles de la aplicación", + "applicationDetailsDescription": "Repositorio de la app, tiendas donde está disponible, y más", + "myOtherApps": "Comprueba mis otras apps", + "myOtherAppsDescription": "Creadas por JGeek00" } \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 0f55b89..d38d9d7 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -273,37 +273,18 @@ class _SettingsWidgetState extends State<_SettingsWidget> { subtitle: appConfigProvider.getAppInfo!.version, ), CustomListTile( - title: AppLocalizations.of(context)!.createdBy, - subtitle: Strings.createdBy, + title: AppLocalizations.of(context)!.applicationDetails, + subtitle: AppLocalizations.of(context)!.applicationDetailsDescription, + trailing: Icon(Icons.open_in_new_rounded), + onTap: () => openUrl(Urls.appDetailsWebpage), ), - Padding( - padding: const EdgeInsets.all(15), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - if (Platform.isAndroid) IconButton( - onPressed: () => openUrl(Urls.playStore), - icon: SvgPicture.asset( - 'assets/resources/google-play.svg', - color: Theme.of(context).colorScheme.onSurfaceVariant, - width: 30, - height: 30, - ), - tooltip: AppLocalizations.of(context)!.visitGooglePlay, - ), - IconButton( - onPressed: () => openUrl(Urls.gitHub), - icon: SvgPicture.asset( - 'assets/resources/github.svg', - color: Theme.of(context).colorScheme.onSurfaceVariant, - width: 30, - height: 30, - ), - tooltip: AppLocalizations.of(context)!.gitHub, - ), - ], - ), - ) + CustomListTile( + title: AppLocalizations.of(context)!.myOtherApps, + subtitle: AppLocalizations.of(context)!.myOtherAppsDescription, + trailing: Icon(Icons.open_in_new_rounded), + onTap: () => openUrl(Urls.jgeek00AppsWebpage), + ), + SizedBox(height: 16) ], ) ], From 47b5313bf36fb8f913139ffce383c52d5dc72ca6 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Jan 2025 20:56:56 +0100 Subject: [PATCH 654/676] Removed unused imports --- lib/screens/settings/settings.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index d38d9d7..6c388cf 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -1,8 +1,6 @@ -import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/server_info/server_info.dart'; @@ -25,7 +23,6 @@ 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/desktop_mode.dart'; -import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; From 10ff5183f14453fdbaa6f55a968d172831feeb5c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Jan 2025 21:54:04 +0100 Subject: [PATCH 655/676] Added sorting options custom rules --- lib/constants/enums.dart | 3 +- lib/l10n/app_en.arb | 4 +- lib/l10n/app_es.arb | 4 +- lib/screens/filters/custom_rules_list.dart | 30 +++- .../modals/custom_rules/sort_rules.dart | 128 ++++++++++++++++++ 5 files changed, 161 insertions(+), 8 deletions(-) create mode 100644 lib/screens/filters/modals/custom_rules/sort_rules.dart diff --git a/lib/constants/enums.dart b/lib/constants/enums.dart index f54e665..569db37 100644 --- a/lib/constants/enums.dart +++ b/lib/constants/enums.dart @@ -1,2 +1,3 @@ enum LoadStatus { loading, loaded, error } -enum HomeTopItems { queriedDomains, blockedDomains, recurrentClients, topUpstreams, avgUpstreamResponseTime } \ No newline at end of file +enum HomeTopItems { queriedDomains, blockedDomains, recurrentClients, topUpstreams, avgUpstreamResponseTime } +enum CustomRulesSorting { topBottom, bottomTop } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index d72a148..4602c27 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -801,5 +801,7 @@ "applicationDetails": "Application details", "applicationDetailsDescription": "App repository, stores where it's available, and more", "myOtherApps": "Check my other apps", - "myOtherAppsDescription": "Created by JGeek00" + "myOtherAppsDescription": "Created by JGeek00", + "topToBottom": "From top to bottom", + "bottomToTop": "From bottom to top" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 952104a..862e375 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -801,5 +801,7 @@ "applicationDetails": "Detalles de la aplicación", "applicationDetailsDescription": "Repositorio de la app, tiendas donde está disponible, y más", "myOtherApps": "Comprueba mis otras apps", - "myOtherAppsDescription": "Creadas por JGeek00" + "myOtherAppsDescription": "Creadas por JGeek00", + "topToBottom": "Desde arriba hacia abajo", + "bottomToTop": "Desde abajo hacia arriba" } \ No newline at end of file diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 4cd5bde..284e15f 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -6,6 +6,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_button.dart'; +import 'package:adguard_home_manager/screens/filters/modals/custom_rules/sort_rules.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -34,6 +35,8 @@ class CustomRulesList extends StatefulWidget { class _CustomRulesListState extends State { late bool isVisible; + CustomRulesSorting _sortingMethod = CustomRulesSorting.topBottom; + @override initState(){ super.initState(); @@ -60,6 +63,8 @@ class _CustomRulesListState extends State { final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final renderData = _sortingMethod == CustomRulesSorting.bottomTop ? widget.data.reversed.toList() : widget.data.toList(); + bool checkIfComment(String value) { final regex = RegExp(r'^(!|#).*$'); if (regex.hasMatch(value)) { @@ -104,6 +109,16 @@ class _CustomRulesListState extends State { } } + void showSortingMethodModal() { + showDialog( + context: context, + builder: (ctx) => SortCustomRulesModal( + sortingMethod: _sortingMethod, + onSelect: (value) => setState(() => _sortingMethod = value), + ), + ); + } + return CustomTabContentList( loadingGenerator: () => SizedBox( width: double.maxFinite, @@ -124,10 +139,10 @@ class _CustomRulesListState extends State { ], ), ), - itemsCount: widget.data.length, + itemsCount: renderData.length, contentWidget: (index) => ListTile( title: Text( - widget.data[index], + renderData[index], style: TextStyle( color: checkIfComment(widget.data[index]) == true ? Theme.of(context).colorScheme.onSurface.withOpacity(0.6) @@ -135,9 +150,9 @@ class _CustomRulesListState extends State { fontWeight: FontWeight.normal, ), ), - subtitle: generateSubtitle(widget.data[index]), + subtitle: generateSubtitle(renderData[index]), trailing: IconButton( - onPressed: () => widget.onRemoveCustomRule(widget.data[index]), + onPressed: () => widget.onRemoveCustomRule(renderData[index]), icon: const Icon(Icons.delete) ), ), @@ -212,6 +227,11 @@ class _CustomRulesListState extends State { }, fab: Column( children: [ + FloatingActionButton.small( + onPressed: showSortingMethodModal, + child: Icon(Icons.sort_rounded), + ), + const SizedBox(height: 16), AddFiltersButton( type: 'edit_custom_rule', widget: (fn) => FloatingActionButton.small( @@ -229,7 +249,7 @@ class _CustomRulesListState extends State { ), ], ), - heightFabHidden: -120, + heightFabHidden: -180, fabVisible: isVisible, ); } diff --git a/lib/screens/filters/modals/custom_rules/sort_rules.dart b/lib/screens/filters/modals/custom_rules/sort_rules.dart new file mode 100644 index 0000000..7ae0870 --- /dev/null +++ b/lib/screens/filters/modals/custom_rules/sort_rules.dart @@ -0,0 +1,128 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; + +class SortCustomRulesModal extends StatelessWidget { + final CustomRulesSorting sortingMethod; + final void Function(CustomRulesSorting) onSelect; + + const SortCustomRulesModal({ + super.key, + required this.sortingMethod, + required this.onSelect, + }); + + @override + Widget build(BuildContext context) { + return AlertDialog( + contentPadding: const EdgeInsets.symmetric(vertical: 16), + scrollable: true, + title: Column( + children: [ + Icon( + Icons.sort_rounded, + size: 24, + color: Theme.of(context).listTileTheme.iconColor + ), + const SizedBox(height: 16), + Text( + AppLocalizations.of(context)!.sortingOptions, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface + ), + ) + ], + ), + content: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 500 + ), + child: Column( + children: [ + _CustomListTileDialog( + title: AppLocalizations.of(context)!.topToBottom, + icon: Icons.arrow_downward_rounded, + onTap: () { + Navigator.pop(context); + onSelect(CustomRulesSorting.topBottom); + }, + isSelected: sortingMethod == CustomRulesSorting.topBottom + ), + _CustomListTileDialog( + title: AppLocalizations.of(context)!.bottomToTop, + icon: Icons.arrow_upward_rounded, + onTap: () { + Navigator.pop(context); + onSelect(CustomRulesSorting.bottomTop); + }, + isSelected: sortingMethod == CustomRulesSorting.bottomTop + ), + ] + ), + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.close) + ) + ], + ) + ], + ); + } +} + +class _CustomListTileDialog extends StatelessWidget { + final String title; + final IconData? icon; + final void Function()? onTap; + final bool isSelected; + + const _CustomListTileDialog({ + required this.title, + required this.icon, + required this.onTap, + required this.isSelected, + }); + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: Row( + children: [ + Icon( + icon, + color: Theme.of(context).colorScheme.onSurface, + ), + const SizedBox(width: 24), + Flexible( + child: Text( + title, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ), + const SizedBox(width: 24), + Icon( + isSelected == true ? Icons.radio_button_checked_rounded : Icons.radio_button_unchecked_rounded, + color: Theme.of(context).colorScheme.primary, + ) + ], + ), + ), + ), + ); + } +} \ No newline at end of file From 28034d4b7452cb17974950a9836e05943e535abd Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Tue, 21 Jan 2025 22:00:06 +0100 Subject: [PATCH 656/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index eb0a3f8..02b1c09 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.19.2+145 +version: 2.20.0-beta.1+146 environment: sdk: '>=2.18.1 <3.0.0' From 51b8a6b610b0acd9224a40b806613585fa2b6fe0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 22 Jan 2025 00:00:26 +0100 Subject: [PATCH 657/676] Updated app version --- .github/workflows/release-beta.yaml | 121 ----------- .github/workflows/release-stable.yaml | 300 -------------------------- debian/debian.yaml | 2 +- pubspec.yaml | 2 +- 4 files changed, 2 insertions(+), 423 deletions(-) delete mode 100644 .github/workflows/release-beta.yaml delete mode 100644 .github/workflows/release-stable.yaml diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml deleted file mode 100644 index 854ee28..0000000 --- a/.github/workflows/release-beta.yaml +++ /dev/null @@ -1,121 +0,0 @@ -name: Compile and release beta build - -on: - workflow_dispatch: - -jobs: - build-android: - name: Build Android .apk and .aab - runs-on: ubuntu-latest - env: - ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release - ANDROID_APK_RELEASE_PATH: build/app/outputs/apk/release - outputs: - VERSION_NAME: ${{ steps.save_version.outputs.version_name }} - VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} - steps: - - uses: actions/checkout@v3 - with: - ref: beta - - name: Decode android/app/keystore.jks - run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/app/keystore.jks - - name: Decode android/key.properties - run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - - name: Decode .env - run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Read pubspec.yaml - uses: JGeek00/read-yaml-files@2.0.0 - id: read_pubspec - with: - file: './pubspec.yaml' # File to read from - key-path: '["version"]' - - name: Save version on env variable - id: save_version - run: | - version=${{ steps.read_pubspec.outputs.data }} - IFS='+' - read -r -a split <<< "$version" - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "version_name=${split[0]}" >> $GITHUB_OUTPUT - echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - - name: Update KeyStore password in gradle properties - run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - - name: Update KeyStore key password in gradle properties - run: sed -i 's/#{KEYSTORE_KEY_PASS}#/${{ secrets.KEYSTORE_KEY_PASS }}/g' android/key.properties - - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: '18.x' - - uses: subosito/flutter-action@v2 - with: - channel: "stable" - - run: flutter clean - - run: flutter pub get - - run: flutter build apk --release - - run: flutter build appbundle --release - - name: Rename apk - run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - - name: Rename aab - run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - - name: Copy apk to project root - run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - - name: Copy aab to project root - run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: android - path: | - AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - release-builds-github: - name: Release beta build to GitHub - runs-on: ubuntu-latest - needs: [build-android] - env: - VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} - VERSION_NUMBER: ${{ needs.build-android.outputs.VERSION_NUMBER }} - steps: - - uses: actions/checkout@v3 - with: - ref: beta - - name: Create builds directory - run: mkdir releases - - name: Download Android artifacts - uses: actions/download-artifact@v3 - with: - name: android - path: releases/ - - name: Release to GitHub - uses: ncipollo/release-action@v1 - with: - artifacts: "releases/*" - token: ${{ secrets.GH_TOKEN }} - tag: '${{ env.VERSION_NAME }}_(${{ env.VERSION_NUMBER }})' - name: v${{ env.VERSION_NAME }} - draft: true - prerelease: true - commit: ${{ github.sha }} - release-build-google-play: - name: Release Android beta build to the Google Play Store - runs-on: ubuntu-latest - needs: [build-android] - env: - VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} - steps: - - uses: actions/checkout@v3 - with: - ref: beta - - name: Download Android artifacts - uses: actions/download-artifact@v3 - with: - name: android - - name: Release app to Google Play - uses: r0adkll/upload-google-play@v1 - with: - serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} - packageName: com.jgeek00.adguard_home_manager - releaseFiles: AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - track: beta - status: draft - releaseName: ${{ env.VERSION_NAME }} \ No newline at end of file diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml deleted file mode 100644 index 0b0ae0c..0000000 --- a/.github/workflows/release-stable.yaml +++ /dev/null @@ -1,300 +0,0 @@ -name: Compile and release production build - -on: - workflow_dispatch: - -jobs: - build-android: - name: Build Android .apk and .aab - runs-on: ubuntu-latest - env: - ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release - ANDROID_APK_RELEASE_PATH: build/app/outputs/apk/release - outputs: - VERSION_NAME: ${{ steps.save_version.outputs.version_name }} - VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} - steps: - - uses: actions/checkout@v3 - - name: Decode android/app/keystore.jks - run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/app/keystore.jks - - name: Decode android/key.properties - run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - - name: Decode .env - run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Read pubspec.yaml - uses: JGeek00/read-yaml-files@2.0.0 - id: read_pubspec - with: - file: './pubspec.yaml' # File to read from - key-path: '["version"]' - - name: Save version on env variable - id: save_version - run: | - version=${{ steps.read_pubspec.outputs.data }} - IFS='+' - read -r -a split <<< "$version" - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "version_name=${split[0]}" >> $GITHUB_OUTPUT - echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - - name: Update KeyStore password in gradle properties - run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties - - name: Update KeyStore key password in gradle properties - run: sed -i 's/#{KEYSTORE_KEY_PASS}#/${{ secrets.KEYSTORE_KEY_PASS }}/g' android/key.properties - - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: '18.x' - - uses: subosito/flutter-action@v2 - with: - channel: "stable" - - run: flutter clean - - run: flutter pub get - - run: flutter build apk --release - - run: flutter build appbundle --release - - name: Rename apk - run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - - name: Rename aab - run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - - name: Copy apk to project root - run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - - name: Copy aab to project root - run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: android - path: | - AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk - build-macos: - name: Build macOS .dmg - runs-on: macos-latest - env: - MACOS_APP_RELEASE_PATH: build/macos/Build/Products/Release - outputs: - VERSION_NAME: ${{ steps.save_version.outputs.version_name }} - VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} - steps: - - uses: actions/checkout@v3 - - name: Decode .env - run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Read pubspec.yaml - uses: JGeek00/read-yaml-files@2.0.0 - id: read_pubspec - with: - file: './pubspec.yaml' - key-path: '["version"]' - - name: Save version on env variable - id: save_version - run: | - version=${{ steps.read_pubspec.outputs.data }} - IFS='+' - read -r -a split <<< "$version" - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "version_name=${split[0]}" >> $GITHUB_OUTPUT - echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - - uses: subosito/flutter-action@v2 - with: - channel: "stable" - - run: flutter clean - - run: flutter pub get - - run: flutter build macos --release - - name: Install the Apple certificate and sign the application - env: - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PWD: ${{ secrets.APPLE_CERTIFICATE_PWD }} - APPLE_KEYCHAIN_PWD: ${{ secrets.APPLE_KEYCHAIN_PWD }} - APPLE_IDENTITY_ID: ${{ secrets.APPLE_IDENTITY_ID }} - run: | - echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12 - security create-keychain -p $APPLE_KEYCHAIN_PWD build.keychain - security default-keychain -s build.keychain - security unlock-keychain -p $APPLE_KEYCHAIN_PWD build.keychain - security import certificate.p12 -k build.keychain -P $APPLE_CERTIFICATE_PWD -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $APPLE_KEYCHAIN_PWD build.keychain - /usr/bin/codesign --force -s "$APPLE_IDENTITY_ID" $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager.app -v - - name: Create folder to build dmg - run: mkdir $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager - - name: Copy app into folder - run: cp -r $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager.app $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app - - name: Generate symbolic link to Applications dir - run: ln -s /Applications $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager - - name: Generate dmg - run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg - - name: Copy dmg to project root - run: cp $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: macos - path: AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg - build-linux: - name: Build Linux .tar.gz and .deb - runs-on: ubuntu-latest - outputs: - VERSION_NAME: ${{ steps.save_version.outputs.version_name }} - VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} - steps: - - uses: actions/checkout@v3 - - name: Decode .env - run: echo "${{ secrets.ENV }}" | base64 --decode > .env - - name: Read pubspec.yaml - uses: JGeek00/read-yaml-files@2.0.0 - id: read_pubspec - with: - file: './pubspec.yaml' - key-path: '["version"]' - - name: Save version on env variable - id: save_version - run: | - version=${{ steps.read_pubspec.outputs.data }} - IFS='+' - read -r -a split <<< "$version" - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "version_name=${split[0]}" >> $GITHUB_OUTPUT - echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - - name: Update version in debian.yaml - run: sed -i 's//${{ env.VERSION_NAME }}/g' debian/debian.yaml - - name: Update dependencies list - run: sudo apt-get update - - name: Install dependencies - run: sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev - - uses: subosito/flutter-action@v2 - with: - channel: "stable" - - run: flutter clean - - run: flutter pub get - - run: flutter build linux --release - - name: Install flutter_to_debian - run: dart pub global activate flutter_to_debian - - name: Generate .deb package - run: flutter_to_debian - - name: Move .deb package to project root - run: mv build/linux/x64/release/debian/AdGuardHomeManager_${{ env.VERSION_NAME }}_amd64.deb AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux_amd64.deb - - name: Generate .tar.gz package - uses: a7ul/tar-action@v1.1.3 - id: compress - with: - command: c - cwd: build/linux/x64/release/bundle - files: | - ./data - ./lib - ./AdGuardHomeManager - outPath: AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux.tar.gz - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: linux - path: | - AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux_amd64.deb - AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux.tar.gz - build-windows: - name: Build Windows installer - runs-on: windows-latest - outputs: - VERSION_NAME: ${{ steps.save_version.outputs.version_name }} - VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} - steps: - - uses: actions/checkout@v3 - - name: Decode .env - shell: pwsh - run: | - [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) - - name: Read pubspec.yaml - uses: JGeek00/read-yaml-files@2.0.0 - id: read_pubspec - with: - file: './pubspec.yaml' - key-path: '["version"]' - - name: Save version on env variable - shell: bash - id: save_version - run: | - version=${{ steps.read_pubspec.outputs.data }} - IFS='+' - read -r -a split <<< "$version" - echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV - echo "version_name=${split[0]}" >> $GITHUB_OUTPUT - echo "version_number=${split[1]}" >> $GITHUB_OUTPUT - - name: Update version in innosetup config file - shell: pwsh - run: | - (Get-Content windows/innosetup_installer_builder.iss) -replace '', '${{ env.VERSION_NAME }}' | Out-File -encoding ASCII windows/innosetup_installer_builder.iss - - uses: subosito/flutter-action@v2 - with: - channel: "stable" - - run: flutter clean - - run: flutter pub get - - run: flutter build windows --release - - name: Build installer witn innosetup - run: iscc /Q windows/innosetup_installer_builder.iss - - name: Move installer file to root directory - run: move build/windows/aghm_installer.exe AdGuardHomeManager_${{ env.VERSION_NAME }}_Windows_x64.exe - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: windows - path: AdGuardHomeManager_${{ env.VERSION_NAME }}_Windows_x64.exe - release-builds-github: - name: Release builds to GitHub - runs-on: ubuntu-latest - needs: [build-android, build-macos, build-linux, build-windows] - env: - VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} - VERSION_NUMBER: ${{ needs.build-android.outputs.VERSION_NUMBER }} - steps: - - uses: actions/checkout@v3 - - name: Create builds directory - run: mkdir releases - - name: Download Android artifacts - uses: actions/download-artifact@v3 - with: - name: android - path: releases/ - - name: Download macOS artifacts - uses: actions/download-artifact@v3 - with: - name: macos - path: releases/ - - name: Download Linux artifacts - uses: actions/download-artifact@v3 - with: - name: linux - path: releases/ - - name: Download Windows artifacts - uses: actions/download-artifact@v3 - with: - name: windows - path: releases/ - - name: Release to GitHub - uses: ncipollo/release-action@v1 - with: - artifacts: "releases/*" - token: ${{ secrets.GH_TOKEN }} - tag: '${{ env.VERSION_NAME }}_(${{ env.VERSION_NUMBER }})' - name: v${{ env.VERSION_NAME }} - draft: true - prerelease: false - commit: ${{ github.sha }} - release-build-google-play: - name: Release Android build to the Google Play Store - runs-on: ubuntu-latest - needs: [build-android, build-macos, build-linux, build-windows] - env: - VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} - steps: - - uses: actions/checkout@v3 - - name: Download Android artifacts - uses: actions/download-artifact@v3 - with: - name: android - - name: Release app to Google Play - uses: r0adkll/upload-google-play@v1 - with: - serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} - packageName: com.jgeek00.adguard_home_manager - releaseFiles: AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab - track: production - status: draft - releaseName: ${{ env.VERSION_NAME }} \ No newline at end of file diff --git a/debian/debian.yaml b/debian/debian.yaml index 876c66e..046659c 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: + Version: 2.20.0 Architecture: amd64 Essential: no Priority: optional diff --git a/pubspec.yaml b/pubspec.yaml index 02b1c09..489dfa0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.20.0-beta.1+146 +version: 2.20.0+147 environment: sdk: '>=2.18.1 <3.0.0' From a666d109d9bc3ddbdcaa0e8a9c10360450cb36ad Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 22 Jan 2025 14:40:39 +0100 Subject: [PATCH 658/676] Bug fixes --- lib/functions/open_url.dart | 10 ++++++ lib/main.dart | 13 +++++++- lib/models/dns_statistics.dart | 6 ++-- lib/screens/clients/fab.dart | 4 +++ lib/screens/filters/add_button.dart | 4 +++ lib/screens/logs/log_tile.dart | 2 ++ lib/screens/logs/logs_list_appbar.dart | 1 + lib/widgets/add_server/add_server_modal.dart | 34 +++++++++++--------- 8 files changed, 54 insertions(+), 20 deletions(-) diff --git a/lib/functions/open_url.dart b/lib/functions/open_url.dart index 00cfc17..599eea0 100644 --- a/lib/functions/open_url.dart +++ b/lib/functions/open_url.dart @@ -5,6 +5,15 @@ import 'package:url_launcher/url_launcher.dart' as url_launcher; import 'package:sentry_flutter/sentry_flutter.dart'; void openUrl(String url) async { + if (!(url.startsWith("http") || url.startsWith("https"))) { + try { + url_launcher.launchUrl(Uri.parse(url)); + } catch (e, stackTrace) { + Sentry.captureException(e, stackTrace: stackTrace); + } + return; + } + if (Platform.isAndroid || Platform.isIOS) { try { await flutter_custom_tabs.launchUrl( @@ -20,6 +29,7 @@ void openUrl(String url) async { ), ); } catch (e, stackTrace) { + url_launcher.launchUrl(Uri.parse(url)); Sentry.captureException(e, stackTrace: stackTrace); } } diff --git a/lib/main.dart b/lib/main.dart index 10b1862..61126da 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -168,11 +168,22 @@ void main() async { return null; } + if (event.message?.formatted.contains("HttpException") == true) { + return null; + } + if ( event.message?.formatted.contains("Unexpected character") ?? false || (event.throwable != null && event.throwable!.toString().contains("Unexpected character")) ) { - return null; // Exclude this event + return null; + } + + if ( + event.message?.formatted.contains("Unexpected end of input") ?? false || + (event.throwable != null && event.throwable!.toString().contains("Unexpected end of input")) + ) { + return null; } return event; diff --git a/lib/models/dns_statistics.dart b/lib/models/dns_statistics.dart index ca6c247..ed787ce 100644 --- a/lib/models/dns_statistics.dart +++ b/lib/models/dns_statistics.dart @@ -43,9 +43,9 @@ class DnsStatistics { factory DnsStatistics.fromJson(Map json) => DnsStatistics( timeUnits: json["time_units"], - topQueriedDomains: List>.from(json["top_queried_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), - topClients: List>.from(json["top_clients"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), - topBlockedDomains: List>.from(json["top_blocked_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), + topQueriedDomains: json["top_queried_domains"] != null ? List>.from(json["top_queried_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : [], + topClients: json["top_clients"] != null ? List>.from(json["top_clients"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : [], + topBlockedDomains: json["top_blocked_domains"] != null ? List>.from(json["top_blocked_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))): [], topUpstreamResponses: json["top_upstreams_responses"] != null ? List>.from(json["top_upstreams_responses"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : null, topUpstreamsAvgTime: json["top_upstreams_avg_time"] != null ? List>.from(json["top_upstreams_avg_time"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : null, dnsQueries: List.from(json["dns_queries"].map((x) => x)), diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 383a2f3..9571ae3 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -25,10 +25,14 @@ class ClientsFab extends StatelessWidget { final width = MediaQuery.of(context).size.width; void confirmAddClient(Client client) async { + if (!context.mounted) return; + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingClient); final result = await clientsProvider.addClient(client); + + if (!context.mounted) return; processModal.close(); diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 1621b68..e2de2ff 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -33,6 +33,8 @@ class AddFiltersButton extends StatelessWidget { final width = MediaQuery.of(context).size.width; void confirmAddRule(String rule) async { + if (!context.mounted) return; + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingRule); @@ -58,6 +60,8 @@ class AddFiltersButton extends StatelessWidget { } void confirmEditCustomRules(List rules) async { + if (!context.mounted) return; + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingCustomRules); diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index 342817f..dc33048 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -154,6 +154,8 @@ class LogTile extends StatelessWidget { } void blockUnblockRuleClient() async { + if (!context.mounted) return; + ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingRule); diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 2a052f6..21e03b1 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -89,6 +89,7 @@ class LogsListAppBar extends StatelessWidget { } void openLiveLogsScreen() { + if (!context.mounted) return; Navigator.of(context).push( MaterialPageRoute( builder: (context) => MultiProvider( diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index 7164ba0..a7fc768 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -175,6 +175,8 @@ class _AddServerModalState extends State { final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); final serverStatus = await apiClient2.getServerStatus(); + if (!context.mounted) return; + // If something goes wrong when fetching server status if (serverStatus.successful == false) { statusProvider.setServerStatusLoad(LoadStatus.error); @@ -203,16 +205,16 @@ class _AddServerModalState extends State { final serverCreated = await serversProvider.createServer(serverObj); + if (!context.mounted) return; + // If something goes wrong when saving the connection on the db if (serverCreated != null) { - if (mounted) setState(() => isConnecting = false); - if (mounted) { - showSnackbar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionNotCreated, - color: Colors.red - ); - } + setState(() => isConnecting = false); + showSnackbar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionNotCreated, + color: Colors.red + ); return; } @@ -295,10 +297,12 @@ class _AddServerModalState extends State { } final serverSaved = await serversProvider.editServer(serverObj); + + if (!mounted) return; // If something goes wrong when saving the connection on the db if (serverSaved != null) { - if (mounted) setState(() => isConnecting = false); + setState(() => isConnecting = false); appConfigProvider.addLog( AppLog( type: 'save_connection_db', @@ -306,13 +310,11 @@ class _AddServerModalState extends State { message: serverSaved.toString() ) ); - if (mounted) { - showSnackbar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionNotCreated, - color: Colors.red - ); - } + showSnackbar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionNotCreated, + color: Colors.red + ); return; } From db6e63c4aaa9264bf964df294f3e2049549010ef Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 22 Jan 2025 14:41:04 +0100 Subject: [PATCH 659/676] Fix bad performance debug mode --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 769a50d..553928e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,5 +16,6 @@ "cSpell.ignorePaths": [ "/pubspec.yaml", "/.github/workflows" - ] + ], + "dart.flutterRunAdditionalArgs": [ "--no-enable-impeller" ] } \ No newline at end of file From 02b659c1bcf3cb4dfe71608468866105fba8a2bf Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 22 Jan 2025 14:43:20 +0100 Subject: [PATCH 660/676] Changed my other apps text --- lib/l10n/app_en.arb | 4 ++-- lib/l10n/app_es.arb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 4602c27..fa952aa 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -800,8 +800,8 @@ "hereWillAppearRealtimeLogs": "Here there will appear the logs on realtime.", "applicationDetails": "Application details", "applicationDetailsDescription": "App repository, stores where it's available, and more", - "myOtherApps": "Check my other apps", - "myOtherAppsDescription": "Created by JGeek00", + "myOtherApps": "My other apps", + "myOtherAppsDescription": "Check my other apps, make a donation, contact support, and more", "topToBottom": "From top to bottom", "bottomToTop": "From bottom to top" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 862e375..d18f8a9 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -800,8 +800,8 @@ "hereWillAppearRealtimeLogs": "Aquí aparecerán los registros en tiempo real.", "applicationDetails": "Detalles de la aplicación", "applicationDetailsDescription": "Repositorio de la app, tiendas donde está disponible, y más", - "myOtherApps": "Comprueba mis otras apps", - "myOtherAppsDescription": "Creadas por JGeek00", + "myOtherApps": "Mis otras apps", + "myOtherAppsDescription": "Comprueba mis otras apps, hacer una donación, contactar al soporte, y más", "topToBottom": "Desde arriba hacia abajo", "bottomToTop": "Desde abajo hacia arriba" } \ No newline at end of file From 7f6f686b2b34e38d8e8d8e8afc7a84c2ebc8ab8e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 22 Jan 2025 14:45:38 +0100 Subject: [PATCH 661/676] Updated app version --- debian/debian.yaml | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/debian.yaml b/debian/debian.yaml index 046659c..43a90f9 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.20.0 + Version: 2.20.1 Architecture: amd64 Essential: no Priority: optional diff --git a/pubspec.yaml b/pubspec.yaml index 489dfa0..4222db1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.20.0+147 +version: 2.20.1+148 environment: sdk: '>=2.18.1 <3.0.0' From 4282792ebd74f477823bd67fc8dbb3dea3ce0ce2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 9 Mar 2025 19:45:37 +0100 Subject: [PATCH 662/676] Updated stuff --- .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-d7ea1a46fca8a951bac1.json | 1391 +++++++++++++++++ .../cmakeFiles-v1-25067417d59f0d26c931.json | 799 ++++++++++ .../codemodel-v2-aa70310decf347f6cbdc.json | 43 + ...irectory-.-Debug-f5ebdc15457944623624.json | 14 + .../reply/index-2025-03-09T18-26-01-0152.json | 92 ++ .../Debug/4s676p3c/arm64-v8a/CMakeCache.txt | 405 +++++ .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 + .../3.22.1-g37088a8/CMakeCXXCompiler.cmake | 83 + .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 7992 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 8136 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 803 ++++++++++ .../CompilerIdC/CMakeCCompilerId.o | Bin 0 -> 6048 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 791 ++++++++++ .../CompilerIdCXX/CMakeCXXCompilerId.o | Bin 0 -> 6064 bytes .../CMakeFiles/TargetDirectories.txt | 2 + .../arm64-v8a/CMakeFiles/cmake.check_cache | 1 + .../4s676p3c/arm64-v8a/CMakeFiles/rules.ninja | 45 + .../arm64-v8a/additional_project_files.txt | 0 .../arm64-v8a/android_gradle_build.json | 28 + .../arm64-v8a/android_gradle_build_mini.json | 20 + .../.cxx/Debug/4s676p3c/arm64-v8a/build.ninja | 112 ++ .../4s676p3c/arm64-v8a/build_file_index.txt | 1 + .../4s676p3c/arm64-v8a/cmake_install.cmake | 54 + .../arm64-v8a/configure_fingerprint.bin | 28 + .../arm64-v8a/metadata_generation_command.txt | 20 + .../4s676p3c/arm64-v8a/prefab_config.json | 4 + .../arm64-v8a/symbol_folder_index.txt | 1 + .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-6573c0656e67becaeff1.json | 1391 +++++++++++++++++ .../cmakeFiles-v1-161e4284e257b7dbcee8.json | 799 ++++++++++ .../codemodel-v2-769fcb1eb528b5a1f77c.json | 43 + ...irectory-.-Debug-f5ebdc15457944623624.json | 14 + .../reply/index-2025-03-09T18-26-01-0543.json | 92 ++ .../Debug/4s676p3c/armeabi-v7a/CMakeCache.txt | 405 +++++ .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 + .../3.22.1-g37088a8/CMakeCXXCompiler.cmake | 83 + .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 5896 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 6036 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 803 ++++++++++ .../CompilerIdC/CMakeCCompilerId.o | Bin 0 -> 4148 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 791 ++++++++++ .../CompilerIdCXX/CMakeCXXCompilerId.o | Bin 0 -> 4184 bytes .../CMakeFiles/TargetDirectories.txt | 2 + .../armeabi-v7a/CMakeFiles/cmake.check_cache | 1 + .../armeabi-v7a/CMakeFiles/rules.ninja | 45 + .../armeabi-v7a/additional_project_files.txt | 0 .../armeabi-v7a/android_gradle_build.json | 28 + .../android_gradle_build_mini.json | 20 + .../Debug/4s676p3c/armeabi-v7a/build.ninja | 112 ++ .../4s676p3c/armeabi-v7a/build_file_index.txt | 1 + .../4s676p3c/armeabi-v7a/cmake_install.cmake | 54 + .../armeabi-v7a/configure_fingerprint.bin | 28 + .../metadata_generation_command.txt | 20 + .../4s676p3c/armeabi-v7a/prefab_config.json | 4 + .../armeabi-v7a/symbol_folder_index.txt | 1 + android/app/.cxx/Debug/4s676p3c/hash_key.txt | 27 + .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-920dacdb871097de2130.json | 1391 +++++++++++++++++ .../cmakeFiles-v1-f1661dab2653e3c04b8e.json | 799 ++++++++++ .../codemodel-v2-95b6204aa3712c2f8293.json | 43 + ...irectory-.-Debug-f5ebdc15457944623624.json | 14 + .../reply/index-2025-03-09T18-26-01-0932.json | 92 ++ .../.cxx/Debug/4s676p3c/x86/CMakeCache.txt | 405 +++++ .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 + .../3.22.1-g37088a8/CMakeCXXCompiler.cmake | 83 + .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 5828 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 5984 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 803 ++++++++++ .../CompilerIdC/CMakeCCompilerId.o | Bin 0 -> 3924 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 791 ++++++++++ .../CompilerIdCXX/CMakeCXXCompilerId.o | Bin 0 -> 3960 bytes .../x86/CMakeFiles/TargetDirectories.txt | 2 + .../4s676p3c/x86/CMakeFiles/cmake.check_cache | 1 + .../Debug/4s676p3c/x86/CMakeFiles/rules.ninja | 45 + .../4s676p3c/x86/additional_project_files.txt | 0 .../4s676p3c/x86/android_gradle_build.json | 28 + .../x86/android_gradle_build_mini.json | 20 + .../app/.cxx/Debug/4s676p3c/x86/build.ninja | 112 ++ .../Debug/4s676p3c/x86/build_file_index.txt | 1 + .../Debug/4s676p3c/x86/cmake_install.cmake | 54 + .../4s676p3c/x86/configure_fingerprint.bin | 28 + .../x86/metadata_generation_command.txt | 20 + .../Debug/4s676p3c/x86/prefab_config.json | 4 + .../4s676p3c/x86/symbol_folder_index.txt | 1 + .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-2b5d080db4293a9c0f40.json | 1391 +++++++++++++++++ .../cmakeFiles-v1-9a2bf79ff0a2a89eb505.json | 799 ++++++++++ .../codemodel-v2-852402f1316f6f65a056.json | 43 + ...irectory-.-Debug-f5ebdc15457944623624.json | 14 + .../reply/index-2025-03-09T18-26-02-0299.json | 92 ++ .../.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt | 405 +++++ .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 + .../3.22.1-g37088a8/CMakeCXXCompiler.cmake | 83 + .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 7008 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 7176 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 803 ++++++++++ .../CompilerIdC/CMakeCCompilerId.o | Bin 0 -> 5424 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 791 ++++++++++ .../CompilerIdCXX/CMakeCXXCompilerId.o | Bin 0 -> 5480 bytes .../x86_64/CMakeFiles/TargetDirectories.txt | 2 + .../x86_64/CMakeFiles/cmake.check_cache | 1 + .../4s676p3c/x86_64/CMakeFiles/rules.ninja | 45 + .../x86_64/additional_project_files.txt | 0 .../4s676p3c/x86_64/android_gradle_build.json | 28 + .../x86_64/android_gradle_build_mini.json | 20 + .../.cxx/Debug/4s676p3c/x86_64/build.ninja | 112 ++ .../4s676p3c/x86_64/build_file_index.txt | 1 + .../Debug/4s676p3c/x86_64/cmake_install.cmake | 54 + .../4s676p3c/x86_64/configure_fingerprint.bin | 28 + .../x86_64/metadata_generation_command.txt | 20 + .../Debug/4s676p3c/x86_64/prefab_config.json | 4 + .../4s676p3c/x86_64/symbol_folder_index.txt | 1 + pubspec.lock | 178 +-- 126 files changed, 19412 insertions(+), 89 deletions(-) create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cache-v2-d7ea1a46fca8a951bac1.json create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-25067417d59f0d26c931.json create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-aa70310decf347f6cbdc.json create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0152.json create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeCache.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake create mode 100755 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin create mode 100755 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/TargetDirectories.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/cmake.check_cache create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rules.ninja create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/additional_project_files.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/cmake_install.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json create mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cache-v2 create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/codemodel-v2 create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cache-v2-6573c0656e67becaeff1.json create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-161e4284e257b7dbcee8.json create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-769fcb1eb528b5a1f77c.json create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0543.json create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeCache.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake create mode 100755 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin create mode 100755 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/TargetDirectories.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/cmake.check_cache create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rules.ninja create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/additional_project_files.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/cmake_install.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json create mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/hash_key.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cache-v2 create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cmakeFiles-v1 create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/codemodel-v2 create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cache-v2-920dacdb871097de2130.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cmakeFiles-v1-f1661dab2653e3c04b8e.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/codemodel-v2-95b6204aa3712c2f8293.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0932.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeCache.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake create mode 100755 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin create mode 100755 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/TargetDirectories.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/cmake.check_cache create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rules.ninja create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/additional_project_files.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/build.ninja create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/cmake_install.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cache-v2 create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cmakeFiles-v1 create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/codemodel-v2 create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cache-v2-2b5d080db4293a9c0f40.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-9a2bf79ff0a2a89eb505.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/codemodel-v2-852402f1316f6f65a056.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T18-26-02-0299.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake create mode 100755 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin create mode 100755 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/TargetDirectories.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/cmake.check_cache create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/rules.ninja create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/additional_project_files.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/android_gradle_build.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/android_gradle_build_mini.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/build.ninja create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/build_file_index.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/cmake_install.cmake create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/configure_fingerprint.bin create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/metadata_generation_command.txt create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/prefab_config.json create mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/symbol_folder_index.txt diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cache-v2-d7ea1a46fca8a951bac1.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cache-v2-d7ea1a46fca8a951bac1.json new file mode 100644 index 0000000..50ecf16 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cache-v2-d7ea1a46fca8a951bac1.json @@ -0,0 +1,1391 @@ +{ + "entries" : + [ + { + "name" : "ANDROID_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "arm64-v8a" + }, + { + "name" : "ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" + }, + { + "name" : "ANDROID_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "android-26" + }, + { + "name" : "CMAKE_ADDR2LINE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line" + }, + { + "name" : "CMAKE_ANDROID_ARCH_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "arm64-v8a" + }, + { + "name" : "CMAKE_ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" + }, + { + "name" : "CMAKE_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_ASM_FLAGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_BUILD_TYPE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." + } + ], + "type" : "STRING", + "value" : "Debug" + }, + { + "name" : "CMAKE_CACHEFILE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "This is the directory where this CMakeCache.txt was created" + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a" + }, + { + "name" : "CMAKE_CACHE_MAJOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Major version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "3" + }, + { + "name" : "CMAKE_CACHE_MINOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Minor version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "22" + }, + { + "name" : "CMAKE_CACHE_PATCH_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Patch version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake" + }, + { + "name" : "CMAKE_CPACK_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cpack program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack" + }, + { + "name" : "CMAKE_CTEST_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to ctest program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest" + }, + { + "name" : "CMAKE_CXX_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "(This variable does not exist and should not be used)" + } + ], + "type" : "UNINITIALIZED", + "value" : "" + }, + { + "name" : "CMAKE_CXX_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_CXX_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_CXX_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_CXX_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C++ applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_C_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "(This variable does not exist and should not be used)" + } + ], + "type" : "UNINITIALIZED", + "value" : "" + }, + { + "name" : "CMAKE_C_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_C_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_C_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_C_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_C_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_DLLTOOL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "CMAKE_DLLTOOL-NOTFOUND" + }, + { + "name" : "CMAKE_EDIT_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cache edit program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake" + }, + { + "name" : "CMAKE_ERROR_DEPRECATED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Whether to issue deprecation errors for macros and functions." + } + ], + "type" : "INTERNAL", + "value" : "FALSE" + }, + { + "name" : "CMAKE_EXECUTABLE_FORMAT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Executable file format" + } + ], + "type" : "INTERNAL", + "value" : "ELF" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "ON" + }, + { + "name" : "CMAKE_EXTRA_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of external makefile project generator." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator." + } + ], + "type" : "INTERNAL", + "value" : "Ninja" + }, + { + "name" : "CMAKE_GENERATOR_INSTANCE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Generator instance identifier." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator platform." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_TOOLSET", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator toolset." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_HOME_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Source directory with the top level CMakeLists.txt file for this project" + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + { + "name" : "CMAKE_INSTALL_PREFIX", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install path prefix, prepended onto install directories." + } + ], + "type" : "PATH", + "value" : "/usr/local" + }, + { + "name" : "CMAKE_INSTALL_SO_NO_EXE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install .so files without execute permission." + } + ], + "type" : "INTERNAL", + "value" : "0" + }, + { + "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a" + }, + { + "name" : "CMAKE_LINKER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" + }, + { + "name" : "CMAKE_MAKE_PROGRAM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_NM", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm" + }, + { + "name" : "CMAKE_NUMBER_OF_MAKEFILES", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "number of local generators" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_OBJCOPY", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy" + }, + { + "name" : "CMAKE_OBJDUMP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump" + }, + { + "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Platform information initialized" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_PROJECT_DESCRIPTION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_HOMEPAGE_URL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "Project" + }, + { + "name" : "CMAKE_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Ranlib" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_READELF", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf" + }, + { + "name" : "CMAKE_ROOT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake installation." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" + }, + { + "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of dll's." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SKIP_INSTALL_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_SKIP_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when using shared libraries." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STRIP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Strip" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip" + }, + { + "name" : "CMAKE_SUPPRESS_DEVELOPER_ERRORS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Suppress errors that are meant for the author of the CMakeLists.txt files." + } + ], + "type" : "INTERNAL", + "value" : "TRUE" + }, + { + "name" : "CMAKE_SUPPRESS_DEVELOPER_WARNINGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Suppress Warnings that are meant for the author of the CMakeLists.txt files." + } + ], + "type" : "INTERNAL", + "value" : "TRUE" + }, + { + "name" : "CMAKE_SYSTEM_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "Android" + }, + { + "name" : "CMAKE_SYSTEM_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "26" + }, + { + "name" : "CMAKE_TOOLCHAIN_FILE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "The CMake toolchain file" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "name" : "CMAKE_UNAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "uname command" + } + ], + "type" : "INTERNAL", + "value" : "/usr/bin/uname" + }, + { + "name" : "CMAKE_VERBOSE_MAKEFILE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." + } + ], + "type" : "BOOL", + "value" : "FALSE" + }, + { + "name" : "CMAKE_WARN_DEPRECATED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Whether to issue warnings for deprecated functionality." + } + ], + "type" : "INTERNAL", + "value" : "FALSE" + }, + { + "name" : "Project_BINARY_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a" + }, + { + "name" : "Project_IS_TOP_LEVEL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "ON" + }, + { + "name" : "Project_SOURCE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + } + ], + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-25067417d59f0d26c931.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-25067417d59f0d26c931.json new file mode 100644 index 0000000..5a3733f --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-25067417d59f0d26c931.json @@ -0,0 +1,799 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", + "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-aa70310decf347f6cbdc.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-aa70310decf347f6cbdc.json new file mode 100644 index 0000000..421c157 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-aa70310decf347f6cbdc.json @@ -0,0 +1,43 @@ +{ + "configurations" : + [ + { + "directories" : + [ + { + "build" : ".", + "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", + "minimumCMakeVersion" : + { + "string" : "3.6.0" + }, + "projectIndex" : 0, + "source" : "." + } + ], + "name" : "Debug", + "projects" : + [ + { + "directoryIndexes" : + [ + 0 + ], + "name" : "Project" + } + ], + "targets" : [] + } + ], + "kind" : "codemodel", + "paths" : + { + "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", + "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + "version" : + { + "major" : 2, + "minor" : 3 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json new file mode 100644 index 0000000..3a67af9 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json @@ -0,0 +1,14 @@ +{ + "backtraceGraph" : + { + "commands" : [], + "files" : [], + "nodes" : [] + }, + "installers" : [], + "paths" : + { + "build" : ".", + "source" : "." + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0152.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0152.json new file mode 100644 index 0000000..7f77f77 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0152.json @@ -0,0 +1,92 @@ +{ + "cmake" : + { + "generator" : + { + "multiConfig" : false, + "name" : "Ninja" + }, + "paths" : + { + "cmake" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake", + "cpack" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack", + "ctest" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest", + "root" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" + }, + "version" : + { + "isDirty" : false, + "major" : 3, + "minor" : 22, + "patch" : 1, + "string" : "3.22.1-g37088a8", + "suffix" : "g37088a8" + } + }, + "objects" : + [ + { + "jsonFile" : "codemodel-v2-aa70310decf347f6cbdc.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + }, + { + "jsonFile" : "cache-v2-d7ea1a46fca8a951bac1.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + { + "jsonFile" : "cmakeFiles-v1-25067417d59f0d26c931.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + } + ], + "reply" : + { + "client-agp" : + { + "cache-v2" : + { + "jsonFile" : "cache-v2-d7ea1a46fca8a951bac1.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + "cmakeFiles-v1" : + { + "jsonFile" : "cmakeFiles-v1-25067417d59f0d26c931.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + }, + "codemodel-v2" : + { + "jsonFile" : "codemodel-v2-aa70310decf347f6cbdc.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + } + } + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeCache.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeCache.txt new file mode 100644 index 0000000..5701b44 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeCache.txt @@ -0,0 +1,405 @@ +# This is the CMakeCache file. +# For build in directory: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a +# It was generated by CMake: /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//No help, variable specified on the command line. +ANDROID_ABI:UNINITIALIZED=arm64-v8a + +//No help, variable specified on the command line. +ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 + +//No help, variable specified on the command line. +ANDROID_PLATFORM:UNINITIALIZED=android-26 + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line + +//No help, variable specified on the command line. +CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=arm64-v8a + +//No help, variable specified on the command line. +CMAKE_ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 + +//Archiver +CMAKE_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Flags used by the compiler during all build types. +CMAKE_ASM_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_ASM_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_ASM_FLAGS_RELEASE:STRING= + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING=Debug + +//LLVM archiver +CMAKE_CXX_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING= + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_CXX_FLAGS_RELEASE:STRING= + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C++ applications. +CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm + +//LLVM archiver +CMAKE_C_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_C_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING= + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_C_FLAGS_RELEASE:STRING= + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C applications. +CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//No help, variable specified on the command line. +CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//No help, variable specified on the command line. +CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a + +//Path to a program. +CMAKE_LINKER:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld + +//No help, variable specified on the command line. +CMAKE_MAKE_PROGRAM:UNINITIALIZED=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Project + +//Ranlib +CMAKE_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf + +//No help, variable specified on the command line. +CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Strip +CMAKE_STRIP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip + +//No help, variable specified on the command line. +CMAKE_SYSTEM_NAME:UNINITIALIZED=Android + +//No help, variable specified on the command line. +CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 + +//The CMake toolchain file +CMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +Project_BINARY_DIR:STATIC=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a + +//Value Computed by CMake +Project_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +Project_SOURCE_DIR:STATIC=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES +CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES +CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake +//Whether to issue deprecation errors for macros and functions. +CMAKE_ERROR_DEPRECATED:INTERNAL=FALSE +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Ninja +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//Suppress errors that are meant for the author of the CMakeLists.txt +// files. +CMAKE_SUPPRESS_DEVELOPER_ERRORS:INTERNAL=TRUE +//Suppress Warnings that are meant for the author of the CMakeLists.txt +// files. +CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=TRUE +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Whether to issue warnings for deprecated functionality. +CMAKE_WARN_DEPRECATED:INTERNAL=FALSE + diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake new file mode 100644 index 0000000..1fc1c84 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "Clang") +set(CMAKE_C_COMPILER_VERSION "17.0.2") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_C_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_C_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/aarch64;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..8d1017c --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake @@ -0,0 +1,83 @@ +set(CMAKE_CXX_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "Clang") +set(CMAKE_CXX_COMPILER_VERSION "17.0.2") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_CXX_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX ) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/aarch64;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..ecf7dc0ff0f4d29d1711e9eb64606718d80eaa08 GIT binary patch literal 7992 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 literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000000000000000000000000000000000000..b47dc244f44818d5bcfd2bcd35740eef4d9b6946 GIT binary patch literal 8136 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 xElPw})rO<*o!b$4{Q3O34f;HHB+uamlAT literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake new file mode 100644 index 0000000..43edff4 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Darwin-24.3.0") +set(CMAKE_HOST_SYSTEM_NAME "Darwin") +set(CMAKE_HOST_SYSTEM_VERSION "24.3.0") +set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64") + +include("/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake") + +set(CMAKE_SYSTEM "Android-1") +set(CMAKE_SYSTEM_NAME "Android") +set(CMAKE_SYSTEM_VERSION "1") +set(CMAKE_SYSTEM_PROCESSOR "aarch64") + +set(CMAKE_CROSSCOMPILING "TRUE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..41b99d7 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,803 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..644f7767da3c033867802fd2410539172e92a3b5 GIT binary patch literal 6048 zcmdT|Z){sv6+h38T_?`mrJ=N2y3RlcD=g1{V><4)2_T{Ukr0!H=)ORa5E4uXCJ^PE`|k0( zzJ5U!@P%9X-gAHVch5QZ+&}N6j~zLFG-4RQ#eg3|&|?(f(#?T9C&W3}hs^7b!&}#H zhs~=~u=#!xKD@pYHWL6(Cycode?N78bF|T@T-!OfnJ`9^*Zzw!(&g)g3;!#fSJ5x@ z|H74M^_L4LjxHXmxvfs4>3B=?O{-l$3j*vkt=@|3wU&-I+G`sUw7lBtl9anWt8H7J zUA3JRYpvN^%9Z7av(alnLG1dnz^qs4{UZ;B~lffHA+ReJ_)|*b(UGr*=iPtgHbKPcb)oQde&E|S* zy5qSIIkjHeo?WTTt`zNDsZ=W1Gud3;nW<%Gi?cH;h2=ulsW}BZUnu1d!u%JkbI$y{ zyx9x3S%b{!F5a`uLu*z$bJBAkL4|HNW7+jJyv5V2Zp)c&S#7KCcU1(@ZDS*I zud}>X&lJ0*a;a0OWh}2%Do(FgtcoX|KIKA&y?}#DKNgi-Z}TUbO^5r96vQ$`Le)o(oldi0^d1= z6A*=oA^ZWsAI292zH5l@>-oqK{+!?sI5docOm&nVN4& znfy`lOA;skl$5D?QOd+uai-8!_LCn*{FZV3Br#4elv)@ssUXUXb6og@(Ef`ryyUY? zc(9vv*8IZwYqHOKN;u|p{lYO}{?Fyee%X>g{nrvP-e2~U6)i}C_1uT^sPH-%KQ8eH z{b6AID-yRQPWstrg1)Np+mg@wPJH#8Jg?}X{o;MOtm*lh)WdNiJ?gprnWl&L@i&?t z|D6T+gThzO^FI}w{Na74^GAi_@Qm!IWlR3>9uY6E;G~D+%kgGCl%!Mf-%tNsspt8u zqDS4|a}sAg@5uh68vdT_^SYV;zQiwT{NKv{cQyQ1vcJ!F7h>2~{V7YF;-KPS+LXyv zt>tCUSqHO+`4LdY*>W%;GCikhnYPulOp%xMldO;|YFqA5LMBaid)|)Ur zf8N}K`yQ6<{LN4Q;3au}*n-v-ZzEy+jxukK1+Aq!rIw#y=iklWQpqUm^WTuzoW{F< z%m?_M)7_+X^7okEj;GK#+2`-NKa2iu_9gyKGA>~;hp;E`N0=T%Kfej=5tj@3 zp+IYzV?eg6G8JJz$$yG5&u9E)#K``@-NpWS>8QRg_8%#tyn}U^|F20R+mrOZeeVAP zg)slmhxkuf7wcpH|AAPT{VO+U|F7HFzZhblAl?4rHukq}(EhP)?7tFXpRz^W{wKDv z|K<(ar#vDo{#zmTDUZ?ZlNo6WrJ(S4f3NJ_E%Q8UP0ZYggGo4-dsXq!SyQ1Lu&e<$Y$3}1Rve-I^s z=Q01|2oR>&-|GXuK)$MF gd>i{$L+n%jsN1K!N?$wae@WWEBnQbZ?Ug?NU#KI5*Z=?k literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..25c62a8 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,791 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..388b75b4cb13f57f4bb096dcff3e4e8f3e045eec GIT binary patch literal 6064 zcmdT|Yit}>6+W}$b?mIOiDS}++Df+~MG0kRA71aS6BHb!33bTB3W=1~jke?6@p{|c zoz3jna#2M?sl-Dd5q?0C%0GkxL~1}4)B&XatPl_Jqg6pj1O!rfNVGg8BBYvg?%cC; z_wKk2{NqNx_nhy3=W(BNH%}iwbs}aMz{P;?L#QzdaAQ{}&k1o3rjWV$Dfq?ay|8g> z5;lIDfZLlpVPgc~izCL|?LSUl*%)m!%5UtP+ZZuM6K}jrAMpcQxccANy;Hnf7#nlE z`m$MhZT`%Ovxll~tJ7#Y-r}*Q-L78(0d|_UzwCOg#Z!&;>beANue!1*<*skHYqnRb z)SP8|wdpVBO0vgU_nmgP;kLWIzO!d8g_HFzQeRG$HOC`Yi&;@}B`XlJSr+n_z!*2~ zPfob}UixQ=M-Ls%Kl8lxst%!g1KI*-*Jh@Zv=hl%ML+eEVsmmJ_S{`DD+l2PF6 zr?JpiNLJC<4Kn|k!V6=LL1?2gV!tPw-$mNoqu8j7*j^mG@wZ5uDaA%*Y{xKgp6s4i z>p| zN82^eZPZc+a@m=gd^TVHVCsQR-NkyzZTi?WeN@t|CSgl<*Qur4cFHT1OQk}ob}&_? zvz3y&IYs-}%BK#j_(-l2*Io6hj)mtkZ^F9(<^SvNw@5_U3WarEn{~&8LPU! zo_Ww&TCHaa-D0WOnXYDRuT?Ch*UENA#5#djNjEcXW8GpBA{dtov-961cck`|!&G7x!Hs-W0gF zruy)@z=JjG>p;a+^5?!K!ROt;XwaH4-VdO5N$>~pivr(0z$d_j_YC0Q5d1;>^8(*9 z!2hJc?;gMjFaf`{T3HkPLHrNM+pVm-*yo6S4*$l3n_hV0mH4N?S;H@^=moeS@NoVa zKPd2U{u$qg`HVxjj*RmROkh8sJqp1x*|AJ`mMSd7S4UR}U?9GVFG!sDVYc}3l=vPE zUs3q?NST_Zl*zw}KPz$aKPhEuJ|kt~t2k5W&<>ssx?KWX-vNw&fE~z|@!}RZkDpIm z4E=|z6V3_Y>aOOU%=k;v|6Q^rT+NZ^g!w<0ynV8zJbO1GV!U3Qzofw#DX^c@Xh((i z8x_XSN&L|O?%~T4Z%CZ{tNZ7Qg46u-7(Od;_U}tSUsm|)zPhI1pRv*&Rj@irqw3~auTmkHE^@hb|lML zsVsYT3soGAZ!cl{WQ*GUHEWitGF2t2id4-|RiG+2O|__Uc@jmH%Za|;u+VGH3a~8f zU$^+PAXoE$Z)l$nzJ37yB`?kI$o<3-G!=GY2Vs2QGH;Frtqp$vhTv~dd?)+sAyr7a z{jU%uY)rmSKoJJ@)xSG@OLoK0xrp9LxsMFBnC%(=D`HXcACn0(A8DfK`kxSuioX&OpKRHl z-$>5$OsDQIz~O;mEgAmTCdi*FJh055&2P>&`qsV zQ{e^VMvea!Iey+)wEyXirjOr8jC|@B;$7qv%dj>v9G_cy4@KEe$qQ{mcnK@E(X8y7muG~&7yte{K@;9&ne9x{hDHX#?vxB`{Q;*{Kq1| l*BFqkp8tU@;@^shPwz=RKE0>(u~VpPGX6`llj26@{~tJ_iIV^T literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..67bfb70 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,2 @@ +/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/edit_cache.dir +/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rules.ninja b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rules.ninja new file mode 100644 index 0000000..28085d5 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rules.ninja @@ -0,0 +1,45 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the rules used to get the outputs files +# built from the input files. +# It is included in the main 'build.ninja'. + +# ============================================================================= +# Project: Project +# Configurations: Debug +# ============================================================================= +# ============================================================================= + +############################################# +# Rule for running custom commands. + +rule CUSTOM_COMMAND + command = $COMMAND + description = $DESC + + +############################################# +# Rule for re-running cmake. + +rule RERUN_CMAKE + command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a + description = Re-running CMake... + generator = 1 + + +############################################# +# Rule for cleaning all built files. + +rule CLEAN + command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja $FILE_ARG -t clean $TARGETS + description = Cleaning all built files... + + +############################################# +# Rule for printing all primary targets available. + +rule HELP + command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja -t targets + description = All primary targets available: + diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/additional_project_files.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/additional_project_files.txt new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json new file mode 100644 index 0000000..0677eb2 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json @@ -0,0 +1,28 @@ +{ + "buildFiles": [ + "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": {}, + "toolchains": { + "toolchain": { + "cCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang.lld", + "cppCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++.lld" + } + }, + "cFileExtensions": [], + "cppFileExtensions": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json new file mode 100644 index 0000000..84dea41 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json @@ -0,0 +1,20 @@ +{ + "buildFiles": [ + "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": {} +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja new file mode 100644 index 0000000..b54a2e4 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the build statements describing the +# compilation DAG. + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# +# Which is the root file. +# ============================================================================= + +# ============================================================================= +# Project: Project +# Configurations: Debug +# ============================================================================= + +############################################# +# Minimal version of Ninja required by this file + +ninja_required_version = 1.5 + + +############################################# +# Set configuration variable for custom commands. + +CONFIGURATION = Debug +# ============================================================================= +# Include auxiliary files. + + +############################################# +# Include rules file. + +include CMakeFiles/rules.ninja + +# ============================================================================= + +############################################# +# Logical path to working directory; prefix for absolute paths. + +cmake_ninja_workdir = /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/ + +############################################# +# Utility command for edit_cache + +build CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a + DESC = Running CMake cache editor... + pool = console + restat = 1 + +build edit_cache: phony CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build rebuild_cache: phony CMakeFiles/rebuild_cache.util + +# ============================================================================= +# Target aliases. + +# ============================================================================= +# Folder targets. + +# ============================================================================= + +############################################# +# Folder: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a + +build all: phony + +# ============================================================================= +# Built-in targets + + +############################################# +# Re-run CMake if any of its inputs changed. + +build build.ninja: RERUN_CMAKE | /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake + pool = console + + +############################################# +# A missing CMake input file is not an error. + +build /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake: phony + + +############################################# +# Clean all the built files. + +build clean: CLEAN + + +############################################# +# Print all primary targets available. + +build help: HELP + + +############################################# +# Make the all target the default. + +default all diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt new file mode 100644 index 0000000..ec6a72a --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt @@ -0,0 +1 @@ +/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/cmake_install.cmake b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/cmake_install.cmake new file mode 100644 index 0000000..27069b4 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/cmake_install.cmake @@ -0,0 +1,54 @@ +# Install script for directory: /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Debug") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "0") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "TRUE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin new file mode 100644 index 0000000..72e381e --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin @@ -0,0 +1,28 @@ +C/C++ Structured Logu +s +q/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/additional_project_files.txtC +A +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ßΠá×2  ÏΠá×2r +p +n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json  àΠá×2Ï ÒΠá×2w +u +s/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json  àΠá×2Ú ØÎ á×2d +b +`/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja  àΠá×2”Ä »Î á×2h +f +d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja.txt  àΠá×2m +k +i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt  àΠá×2 P ØÎ á×2n +l +j/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/compile_commands.json  àΠá×2r +p +n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/compile_commands.json.bin  àΠá×2 x +v +t/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt  àΠá×2 +¾ ØÎ á×2k +i +g/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json  àΠá×2  ( ØÎ á×2p +n +l/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt  àΠá×2  c ØÎ á×2T +R +P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  àΠá×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt new file mode 100644 index 0000000..df24dc1 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt @@ -0,0 +1,20 @@ + -H/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy +-DCMAKE_SYSTEM_NAME=Android +-DCMAKE_EXPORT_COMPILE_COMMANDS=ON +-DCMAKE_SYSTEM_VERSION=26 +-DANDROID_PLATFORM=android-26 +-DANDROID_ABI=arm64-v8a +-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a +-DANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 +-DCMAKE_ANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 +-DCMAKE_TOOLCHAIN_FILE=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake +-DCMAKE_MAKE_PROGRAM=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja +-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a +-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a +-DCMAKE_BUILD_TYPE=Debug +-B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a +-GNinja +-Wno-dev +--no-warn-unused-cli + Build command args: [] + Version: 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json new file mode 100644 index 0000000..e799de8 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json @@ -0,0 +1,4 @@ +{ + "enabled": false, + "packages": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt new file mode 100644 index 0000000..44c632a --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt @@ -0,0 +1 @@ +/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cache-v2 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/codemodel-v2 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cache-v2-6573c0656e67becaeff1.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cache-v2-6573c0656e67becaeff1.json new file mode 100644 index 0000000..12ec5a0 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cache-v2-6573c0656e67becaeff1.json @@ -0,0 +1,1391 @@ +{ + "entries" : + [ + { + "name" : "ANDROID_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "armeabi-v7a" + }, + { + "name" : "ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" + }, + { + "name" : "ANDROID_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "android-26" + }, + { + "name" : "CMAKE_ADDR2LINE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line" + }, + { + "name" : "CMAKE_ANDROID_ARCH_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "armeabi-v7a" + }, + { + "name" : "CMAKE_ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" + }, + { + "name" : "CMAKE_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_ASM_FLAGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_BUILD_TYPE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." + } + ], + "type" : "STRING", + "value" : "Debug" + }, + { + "name" : "CMAKE_CACHEFILE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "This is the directory where this CMakeCache.txt was created" + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a" + }, + { + "name" : "CMAKE_CACHE_MAJOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Major version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "3" + }, + { + "name" : "CMAKE_CACHE_MINOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Minor version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "22" + }, + { + "name" : "CMAKE_CACHE_PATCH_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Patch version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake" + }, + { + "name" : "CMAKE_CPACK_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cpack program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack" + }, + { + "name" : "CMAKE_CTEST_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to ctest program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest" + }, + { + "name" : "CMAKE_CXX_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "(This variable does not exist and should not be used)" + } + ], + "type" : "UNINITIALIZED", + "value" : "" + }, + { + "name" : "CMAKE_CXX_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_CXX_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_CXX_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_CXX_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C++ applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_C_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "(This variable does not exist and should not be used)" + } + ], + "type" : "UNINITIALIZED", + "value" : "" + }, + { + "name" : "CMAKE_C_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_C_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_C_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_C_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_C_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_DLLTOOL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "CMAKE_DLLTOOL-NOTFOUND" + }, + { + "name" : "CMAKE_EDIT_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cache edit program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake" + }, + { + "name" : "CMAKE_ERROR_DEPRECATED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Whether to issue deprecation errors for macros and functions." + } + ], + "type" : "INTERNAL", + "value" : "FALSE" + }, + { + "name" : "CMAKE_EXECUTABLE_FORMAT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Executable file format" + } + ], + "type" : "INTERNAL", + "value" : "ELF" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "ON" + }, + { + "name" : "CMAKE_EXTRA_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of external makefile project generator." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator." + } + ], + "type" : "INTERNAL", + "value" : "Ninja" + }, + { + "name" : "CMAKE_GENERATOR_INSTANCE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Generator instance identifier." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator platform." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_TOOLSET", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator toolset." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_HOME_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Source directory with the top level CMakeLists.txt file for this project" + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + { + "name" : "CMAKE_INSTALL_PREFIX", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install path prefix, prepended onto install directories." + } + ], + "type" : "PATH", + "value" : "/usr/local" + }, + { + "name" : "CMAKE_INSTALL_SO_NO_EXE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install .so files without execute permission." + } + ], + "type" : "INTERNAL", + "value" : "0" + }, + { + "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a" + }, + { + "name" : "CMAKE_LINKER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" + }, + { + "name" : "CMAKE_MAKE_PROGRAM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_NM", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm" + }, + { + "name" : "CMAKE_NUMBER_OF_MAKEFILES", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "number of local generators" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_OBJCOPY", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy" + }, + { + "name" : "CMAKE_OBJDUMP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump" + }, + { + "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Platform information initialized" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_PROJECT_DESCRIPTION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_HOMEPAGE_URL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "Project" + }, + { + "name" : "CMAKE_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Ranlib" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_READELF", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf" + }, + { + "name" : "CMAKE_ROOT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake installation." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" + }, + { + "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of dll's." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SKIP_INSTALL_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_SKIP_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when using shared libraries." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STRIP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Strip" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip" + }, + { + "name" : "CMAKE_SUPPRESS_DEVELOPER_ERRORS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Suppress errors that are meant for the author of the CMakeLists.txt files." + } + ], + "type" : "INTERNAL", + "value" : "TRUE" + }, + { + "name" : "CMAKE_SUPPRESS_DEVELOPER_WARNINGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Suppress Warnings that are meant for the author of the CMakeLists.txt files." + } + ], + "type" : "INTERNAL", + "value" : "TRUE" + }, + { + "name" : "CMAKE_SYSTEM_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "Android" + }, + { + "name" : "CMAKE_SYSTEM_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "26" + }, + { + "name" : "CMAKE_TOOLCHAIN_FILE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "The CMake toolchain file" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "name" : "CMAKE_UNAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "uname command" + } + ], + "type" : "INTERNAL", + "value" : "/usr/bin/uname" + }, + { + "name" : "CMAKE_VERBOSE_MAKEFILE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." + } + ], + "type" : "BOOL", + "value" : "FALSE" + }, + { + "name" : "CMAKE_WARN_DEPRECATED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Whether to issue warnings for deprecated functionality." + } + ], + "type" : "INTERNAL", + "value" : "FALSE" + }, + { + "name" : "Project_BINARY_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a" + }, + { + "name" : "Project_IS_TOP_LEVEL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "ON" + }, + { + "name" : "Project_SOURCE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + } + ], + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-161e4284e257b7dbcee8.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-161e4284e257b7dbcee8.json new file mode 100644 index 0000000..ad14735 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-161e4284e257b7dbcee8.json @@ -0,0 +1,799 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", + "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-769fcb1eb528b5a1f77c.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-769fcb1eb528b5a1f77c.json new file mode 100644 index 0000000..35467aa --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-769fcb1eb528b5a1f77c.json @@ -0,0 +1,43 @@ +{ + "configurations" : + [ + { + "directories" : + [ + { + "build" : ".", + "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", + "minimumCMakeVersion" : + { + "string" : "3.6.0" + }, + "projectIndex" : 0, + "source" : "." + } + ], + "name" : "Debug", + "projects" : + [ + { + "directoryIndexes" : + [ + 0 + ], + "name" : "Project" + } + ], + "targets" : [] + } + ], + "kind" : "codemodel", + "paths" : + { + "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", + "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + "version" : + { + "major" : 2, + "minor" : 3 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json new file mode 100644 index 0000000..3a67af9 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json @@ -0,0 +1,14 @@ +{ + "backtraceGraph" : + { + "commands" : [], + "files" : [], + "nodes" : [] + }, + "installers" : [], + "paths" : + { + "build" : ".", + "source" : "." + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0543.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0543.json new file mode 100644 index 0000000..70ff0c6 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0543.json @@ -0,0 +1,92 @@ +{ + "cmake" : + { + "generator" : + { + "multiConfig" : false, + "name" : "Ninja" + }, + "paths" : + { + "cmake" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake", + "cpack" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack", + "ctest" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest", + "root" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" + }, + "version" : + { + "isDirty" : false, + "major" : 3, + "minor" : 22, + "patch" : 1, + "string" : "3.22.1-g37088a8", + "suffix" : "g37088a8" + } + }, + "objects" : + [ + { + "jsonFile" : "codemodel-v2-769fcb1eb528b5a1f77c.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + }, + { + "jsonFile" : "cache-v2-6573c0656e67becaeff1.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + { + "jsonFile" : "cmakeFiles-v1-161e4284e257b7dbcee8.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + } + ], + "reply" : + { + "client-agp" : + { + "cache-v2" : + { + "jsonFile" : "cache-v2-6573c0656e67becaeff1.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + "cmakeFiles-v1" : + { + "jsonFile" : "cmakeFiles-v1-161e4284e257b7dbcee8.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + }, + "codemodel-v2" : + { + "jsonFile" : "codemodel-v2-769fcb1eb528b5a1f77c.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + } + } + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeCache.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeCache.txt new file mode 100644 index 0000000..4f7a9db --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeCache.txt @@ -0,0 +1,405 @@ +# This is the CMakeCache file. +# For build in directory: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a +# It was generated by CMake: /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//No help, variable specified on the command line. +ANDROID_ABI:UNINITIALIZED=armeabi-v7a + +//No help, variable specified on the command line. +ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 + +//No help, variable specified on the command line. +ANDROID_PLATFORM:UNINITIALIZED=android-26 + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line + +//No help, variable specified on the command line. +CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=armeabi-v7a + +//No help, variable specified on the command line. +CMAKE_ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 + +//Archiver +CMAKE_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Flags used by the compiler during all build types. +CMAKE_ASM_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_ASM_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_ASM_FLAGS_RELEASE:STRING= + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING=Debug + +//LLVM archiver +CMAKE_CXX_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING= + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_CXX_FLAGS_RELEASE:STRING= + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C++ applications. +CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm + +//LLVM archiver +CMAKE_C_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_C_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING= + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_C_FLAGS_RELEASE:STRING= + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C applications. +CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//No help, variable specified on the command line. +CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//No help, variable specified on the command line. +CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a + +//Path to a program. +CMAKE_LINKER:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld + +//No help, variable specified on the command line. +CMAKE_MAKE_PROGRAM:UNINITIALIZED=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Project + +//Ranlib +CMAKE_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf + +//No help, variable specified on the command line. +CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Strip +CMAKE_STRIP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip + +//No help, variable specified on the command line. +CMAKE_SYSTEM_NAME:UNINITIALIZED=Android + +//No help, variable specified on the command line. +CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 + +//The CMake toolchain file +CMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +Project_BINARY_DIR:STATIC=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a + +//Value Computed by CMake +Project_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +Project_SOURCE_DIR:STATIC=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES +CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES +CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake +//Whether to issue deprecation errors for macros and functions. +CMAKE_ERROR_DEPRECATED:INTERNAL=FALSE +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Ninja +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//Suppress errors that are meant for the author of the CMakeLists.txt +// files. +CMAKE_SUPPRESS_DEVELOPER_ERRORS:INTERNAL=TRUE +//Suppress Warnings that are meant for the author of the CMakeLists.txt +// files. +CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=TRUE +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Whether to issue warnings for deprecated functionality. +CMAKE_WARN_DEPRECATED:INTERNAL=FALSE + diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake new file mode 100644 index 0000000..802edf5 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "Clang") +set(CMAKE_C_COMPILER_VERSION "17.0.2") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_C_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_C_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "4") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/arm-linux-androideabi;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/arm;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/arm-linux-androideabi/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/arm-linux-androideabi;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..2193dfd --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake @@ -0,0 +1,83 @@ +set(CMAKE_CXX_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "Clang") +set(CMAKE_CXX_COMPILER_VERSION "17.0.2") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_CXX_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX ) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "4") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/arm-linux-androideabi;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/arm;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/arm-linux-androideabi/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/arm-linux-androideabi;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..3f1c03f0c432c32e4e2cfcdb062fe1e43751825d GIT binary patch literal 5896 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 Nu$x8UUr1%h?mq}<`*{EW literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000000000000000000000000000000000000..1f893f66cb6e585cdf4f0e709db8d25249c8967a GIT binary patch literal 6036 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 literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake new file mode 100644 index 0000000..72a079f --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Darwin-24.3.0") +set(CMAKE_HOST_SYSTEM_NAME "Darwin") +set(CMAKE_HOST_SYSTEM_VERSION "24.3.0") +set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64") + +include("/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake") + +set(CMAKE_SYSTEM "Android-1") +set(CMAKE_SYSTEM_NAME "Android") +set(CMAKE_SYSTEM_VERSION "1") +set(CMAKE_SYSTEM_PROCESSOR "armv7-a") + +set(CMAKE_CROSSCOMPILING "TRUE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..41b99d7 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,803 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..c4b399f47492347c701418e5762a811923832d9f GIT binary patch literal 4148 zcmdT{U5p#m6+ScLv7PnC`$xzx)I}j(Xgy?iyN64E6<8+yrhJBG5+x; zG4feY{1wQsdXYY7F%dYE{x=AEBz^%TKF@#)P1|#8c4{)4nV!yNasJd>o z?zG*GS9T0sAJcc;dU@5VHO+c`t&whd?pdeor|h}P>|7;pXJ=++rtIlVHs?&2GjsX5 z>B>}TD&v%$DLXecle>c!k6P!P#YJ%wmu;g==BYOBhk3SRHO&*Admeyp+qCRz2e&T0 z>NcEo!)jVp$CG)PR;y(i#Q-#dztTk(HgkL1A#-n0!;pEAMhl=+v|MGD0frm~UE*7cQthhy4GJ2BOuAU$Z zM^EC4(c^eyJIJ;;SU3jE->)9jz{bMMC(Emrc~~RQd8AYGaOD4AANayuIIR{x6;iTb z7js5tj-o@cg}Aas9nyxCB#kJe%9uJHxk=eZ+qE6aPGy&Ro3amweH1gkMT?-^C>N5$ zTOqSfHojK}lcV%1Xe6kfcw7B1xs^aLozRu*ow;DXt}@Y{jw*U==q){I>U*LUJ!$9( zLr+Gl1JaJZZFh7PcDTVgswFFWx^LoXW?veDqZUmV+9&5LsMw+RXb>O6aZXaS2>tV0 z$urgPdopBajR)E9I|cP6B*pqXGa8|Chnhw=ha|S|8j$zU7tnA>-q&$>yd*rh*pE@1 zzS$%vXs^hxXWvS13p>Am$58t2-{e1nuZLdi`Hux_(eRe)Lahz=D!qn>e2L{G(GyHZ zh@N699{iobV?)8#p+x&3igzZd7ywNwwr5;W-U)RJ1v|j{TUiEfhAD6tgdcxTu>H88 zrrOL8eg&al67-aywxEv)iq8X5<3xLy@;pJwu(@Iuty0Nz*2wTtg@`MA!$H|GJg08h zmTwtB@#|Nz>y)Y+xqh$c84D+m8kX;SwNl4-+A@K*?+u3Q*V-O-kSFH>KX)T3S%U*7 z#&)_jyBjRT2jp_ZWZ8TlqF^(KNl}5_tbA!nQ^*oeFz1DPuPmox}vl`Cz zDvN=Y`BsUH_W1_Wy|$60z#J#@32kl2T{yGZZ^bc`v`RheC$>R6~cbCsRx865- zkLQu^9Jha<^PI3B-*?%h-)B%D6wM368Js6ho9_ze!+ucFU(kWqdK{G7yXdT!IZM0` zpbO(&h7Qvo z;29U!C1|q{WDcxg8@K$3iWvMShy6H@?*RE!T(|%L literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..25c62a8 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,791 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..ec6bab69ee4d78ac0747a374e943316816171846 GIT binary patch literal 4184 zcmdT{O>7&-6@I(Rr6^KfOS0W4j?prP8z^bCOH!05*+nWR0=X6FAqa8^5+KQ;mmqMyH=LoC zbXD})5oW)6?|t*;&EFg9r>9P@Ynn!?Xf#W^64CXHu$V;wv-B-kZ`{?_DQn!+f2qAj zHxK<_=Ok_EcUE7Z+o_Xub9zM9?^w_%>%@q4d_<<(iMySr>96N8-bvI&R2%guDwn%= zjq4j{*UufV2CYt`>4%$ZO}AaYLPFVTx=}3%TbrjF?cR=5x?y!|Q?|R2+xFbhD|>#; z?KPv#d`VjToyc!@8$r7}u$?=5MT~g}-zQKx7LIFZ{PMORa<|Q#DEX4zZ{%{SQMf|d zl=f}wfN5Bh4?SW{Y12s}y+|7ej%QAo`V5hwX&VQK5|2Vx!it-Zp+S^9MuzoNCIihF zH#3>1&`cH4+&J*PhgI+K{eqqD>-*ZaMU=5I?sRfx#;{n)U5F-3(gzBneZ?V>Ucu%k zFh_jFF?f{zBqXB0OWXk>cp~kFW*V$CR`5xj#^(^3rvS-w=$q2UE;5Xzwg5iVgAU^> zkorFUrke(@Z)#hSSOW#=xAD>5gT!lZtl%TYn4r`R#bqn>q`!lY_5mc`qh0P{O8s1M z*($i7G4~5dyqCM&Bb54s;Gz;HhN}HWYW@kqSb<5zQXuRH5ig1M+^5XDuSb9h z{pHlZhs4B}eeoxNefrA?8D!01G9|yj*G!CG2aNOj(Q4ZZgNB!#&F2;t3c144liBZd z>H)r$pcw(05rnx`lXVrh>wDRtoehgirBbovJ)W)doyf|QndLKS7qYWkQPk-kcN|;+ z_HNgMpx*SmK`*TOHtv%X1wpgAx99Jel^N^%eAHDTG7idE-ub{3%Pv3 zU#RAmi^~hO`O19Guln;|VScgjIIW#=ulj4xKffj~=Z0rjI~{VK?c$O+FZSHFb3P2N z!D-NST(924Rh-)jTK-(iZM$_pRIxd3r{mbwogL?-U+LAIVt28$*qN_7ZrJkON@H%j zSnnFg*59X0RL2d?>FQ3jA#JEb+!h(YnksH>l{Mn|^ z|8cJo;?DfP9)#5sIK?jS6lr-h*9vxSnUd+T)s!}_r;Q2CqW#*WHlkXfe+U$^gDlXM4|5U&GXurIBBxKQFH!!^?OI*P)F ziOYv;eBac}vGiX|%Q256Yo=wJ8QZjy^_cWXatj(5U``rV&72z|Is+*UqLIwl#>dxc z`awh@1{(gn9upJv`Tdwk2L66A)X5;u72bek(EGAo0BSTnuyDhmu@QOHj`t*14Ejb) z;{Jz6cv}MNc6MGmev3DMp^Lj)cuKW%-+o@S9^qr*)}6 zBk`g{ml1JtJj}Z$^{+A_?pspN`^$d+$T&sxw$%Sa>i@-vd3_@FUrBu$>!M?x`x(*y z2qU&LE9E>R;yfYcA46MD*ONHIe$(*7$o(Xe?Qt?KyOm1lZ<8G%R}m-vmXGXX zhkn!c+{m>>b{gcn|B%r3qCSus?bQosY&VL+Mx__|T@^q#3P*<=&p9UU&UcXa?RF6P_S0vdox^mhS4RUCFG4JuW~1#( zj)<-nx-BR$#mKDyueBJDd3JsfGi-T?$0D0g-v3svVsFJy5=s9A`+W;KRa6tl3%LQm zDWsvO2om`&axp*}<#AqBMe#UEVJKRWhL>=!_+Inf;dqz_6@82ff1Ou=T;4=wy^2}+ z`v|(Yzu$wzJobmHKk#>5#>csi%Uh_NA5`JkxxOY*jgy5^jm2Em{u$cwao>!M%j2tg zOv`bVKmPHje8l}((8v9~74wIyH}H3S#NX^5{uW34-HZ9-Jf`B~+yv@iU7y^;-v&7G z_}+>6L&_TXJ38Vow}(I8pSZtwWBxcrtN7lP{*ZP=DZ-!HLsoF?To_fGIeZJ=6zQQK*jsfh`(Fl&Bl1@EM5k0Xuc45A9%j} wzNz`19r1S${(c+tr^e+sCGPJ-2)u;skKYmHuM1vmx#$J?PO%?#PC1UR0n?*oDgXcg literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..ca4b484 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,2 @@ +/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/edit_cache.dir +/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rules.ninja b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rules.ninja new file mode 100644 index 0000000..6a55d4f --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rules.ninja @@ -0,0 +1,45 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the rules used to get the outputs files +# built from the input files. +# It is included in the main 'build.ninja'. + +# ============================================================================= +# Project: Project +# Configurations: Debug +# ============================================================================= +# ============================================================================= + +############################################# +# Rule for running custom commands. + +rule CUSTOM_COMMAND + command = $COMMAND + description = $DESC + + +############################################# +# Rule for re-running cmake. + +rule RERUN_CMAKE + command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a + description = Re-running CMake... + generator = 1 + + +############################################# +# Rule for cleaning all built files. + +rule CLEAN + command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja $FILE_ARG -t clean $TARGETS + description = Cleaning all built files... + + +############################################# +# Rule for printing all primary targets available. + +rule HELP + command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja -t targets + description = All primary targets available: + diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/additional_project_files.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/additional_project_files.txt new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json new file mode 100644 index 0000000..f074409 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json @@ -0,0 +1,28 @@ +{ + "buildFiles": [ + "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": {}, + "toolchains": { + "toolchain": { + "cCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang.lld", + "cppCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++.lld" + } + }, + "cFileExtensions": [], + "cppFileExtensions": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json new file mode 100644 index 0000000..c404902 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json @@ -0,0 +1,20 @@ +{ + "buildFiles": [ + "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": {} +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja new file mode 100644 index 0000000..cda47cd --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the build statements describing the +# compilation DAG. + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# +# Which is the root file. +# ============================================================================= + +# ============================================================================= +# Project: Project +# Configurations: Debug +# ============================================================================= + +############################################# +# Minimal version of Ninja required by this file + +ninja_required_version = 1.5 + + +############################################# +# Set configuration variable for custom commands. + +CONFIGURATION = Debug +# ============================================================================= +# Include auxiliary files. + + +############################################# +# Include rules file. + +include CMakeFiles/rules.ninja + +# ============================================================================= + +############################################# +# Logical path to working directory; prefix for absolute paths. + +cmake_ninja_workdir = /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/ + +############################################# +# Utility command for edit_cache + +build CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a + DESC = Running CMake cache editor... + pool = console + restat = 1 + +build edit_cache: phony CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build rebuild_cache: phony CMakeFiles/rebuild_cache.util + +# ============================================================================= +# Target aliases. + +# ============================================================================= +# Folder targets. + +# ============================================================================= + +############################################# +# Folder: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a + +build all: phony + +# ============================================================================= +# Built-in targets + + +############################################# +# Re-run CMake if any of its inputs changed. + +build build.ninja: RERUN_CMAKE | /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake + pool = console + + +############################################# +# A missing CMake input file is not an error. + +build /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake: phony + + +############################################# +# Clean all the built files. + +build clean: CLEAN + + +############################################# +# Print all primary targets available. + +build help: HELP + + +############################################# +# Make the all target the default. + +default all diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt new file mode 100644 index 0000000..ec6a72a --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt @@ -0,0 +1 @@ +/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/cmake_install.cmake b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/cmake_install.cmake new file mode 100644 index 0000000..05e628b --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/cmake_install.cmake @@ -0,0 +1,54 @@ +# Install script for directory: /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Debug") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "0") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "TRUE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin new file mode 100644 index 0000000..064663e --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin @@ -0,0 +1,28 @@ +C/C++ Structured Logw +u +s/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/additional_project_files.txtC +A +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ÍÑ á×2  ËÑ á×2t +r +p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json  ÍÑ á×2Ó ÌÑ á×2y +w +u/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json  ÍÑ á×2Þ ÌÑ á×2f +d +b/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja  ÍÑ á×2 Ä ÁÑ á×2j +h +f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja.txt  ÍÑ á×2o +m +k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt  ÍÑ á×2 P ÍÑ á×2p +n +l/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/compile_commands.json  ÍÑ á×2t +r +p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/compile_commands.json.bin  ÍÑ á×2 z +x +v/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt  ÍÑ á×2 +È ÍÑ á×2m +k +i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json  ÍÑ á×2  ( ÍÑ á×2r +p +n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt  ÍÑ á×2  e ÍÑ á×2T +R +P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  ÍÑ á×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt new file mode 100644 index 0000000..b418b0d --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt @@ -0,0 +1,20 @@ + -H/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy +-DCMAKE_SYSTEM_NAME=Android +-DCMAKE_EXPORT_COMPILE_COMMANDS=ON +-DCMAKE_SYSTEM_VERSION=26 +-DANDROID_PLATFORM=android-26 +-DANDROID_ABI=armeabi-v7a +-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a +-DANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 +-DCMAKE_ANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 +-DCMAKE_TOOLCHAIN_FILE=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake +-DCMAKE_MAKE_PROGRAM=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja +-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a +-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a +-DCMAKE_BUILD_TYPE=Debug +-B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a +-GNinja +-Wno-dev +--no-warn-unused-cli + Build command args: [] + Version: 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json new file mode 100644 index 0000000..e799de8 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json @@ -0,0 +1,4 @@ +{ + "enabled": false, + "packages": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt new file mode 100644 index 0000000..ac80ab6 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt @@ -0,0 +1 @@ +/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/hash_key.txt b/android/app/.cxx/Debug/4s676p3c/hash_key.txt new file mode 100644 index 0000000..aff771b --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/hash_key.txt @@ -0,0 +1,27 @@ +# Values used to calculate the hash in this folder name. +# Should not depend on the absolute path of the project itself. +# - AGP: 8.6.0. +# - $NDK is the path to NDK 26.1.10909125. +# - $PROJECT is the path to the parent folder of the root Gradle build file. +# - $ABI is the ABI to be built with. The specific value doesn't contribute to the value of the hash. +# - $HASH is the hash value computed from this text. +# - $CMAKE is the path to CMake 3.22.1. +# - $NINJA is the path to Ninja. +-H/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy +-DCMAKE_SYSTEM_NAME=Android +-DCMAKE_EXPORT_COMPILE_COMMANDS=ON +-DCMAKE_SYSTEM_VERSION=26 +-DANDROID_PLATFORM=android-26 +-DANDROID_ABI=$ABI +-DCMAKE_ANDROID_ARCH_ABI=$ABI +-DANDROID_NDK=$NDK +-DCMAKE_ANDROID_NDK=$NDK +-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake +-DCMAKE_MAKE_PROGRAM=$NINJA +-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/$HASH/obj/$ABI +-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/$HASH/obj/$ABI +-DCMAKE_BUILD_TYPE=Debug +-B$PROJECT/app/.cxx/Debug/$HASH/$ABI +-GNinja +-Wno-dev +--no-warn-unused-cli \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cache-v2 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cmakeFiles-v1 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/codemodel-v2 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cache-v2-920dacdb871097de2130.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cache-v2-920dacdb871097de2130.json new file mode 100644 index 0000000..04a71c8 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cache-v2-920dacdb871097de2130.json @@ -0,0 +1,1391 @@ +{ + "entries" : + [ + { + "name" : "ANDROID_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "x86" + }, + { + "name" : "ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" + }, + { + "name" : "ANDROID_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "android-26" + }, + { + "name" : "CMAKE_ADDR2LINE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line" + }, + { + "name" : "CMAKE_ANDROID_ARCH_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "x86" + }, + { + "name" : "CMAKE_ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" + }, + { + "name" : "CMAKE_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_ASM_FLAGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_BUILD_TYPE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." + } + ], + "type" : "STRING", + "value" : "Debug" + }, + { + "name" : "CMAKE_CACHEFILE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "This is the directory where this CMakeCache.txt was created" + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86" + }, + { + "name" : "CMAKE_CACHE_MAJOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Major version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "3" + }, + { + "name" : "CMAKE_CACHE_MINOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Minor version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "22" + }, + { + "name" : "CMAKE_CACHE_PATCH_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Patch version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake" + }, + { + "name" : "CMAKE_CPACK_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cpack program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack" + }, + { + "name" : "CMAKE_CTEST_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to ctest program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest" + }, + { + "name" : "CMAKE_CXX_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "(This variable does not exist and should not be used)" + } + ], + "type" : "UNINITIALIZED", + "value" : "" + }, + { + "name" : "CMAKE_CXX_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_CXX_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_CXX_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_CXX_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C++ applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_C_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "(This variable does not exist and should not be used)" + } + ], + "type" : "UNINITIALIZED", + "value" : "" + }, + { + "name" : "CMAKE_C_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_C_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_C_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_C_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_C_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_DLLTOOL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "CMAKE_DLLTOOL-NOTFOUND" + }, + { + "name" : "CMAKE_EDIT_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cache edit program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake" + }, + { + "name" : "CMAKE_ERROR_DEPRECATED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Whether to issue deprecation errors for macros and functions." + } + ], + "type" : "INTERNAL", + "value" : "FALSE" + }, + { + "name" : "CMAKE_EXECUTABLE_FORMAT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Executable file format" + } + ], + "type" : "INTERNAL", + "value" : "ELF" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "ON" + }, + { + "name" : "CMAKE_EXTRA_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of external makefile project generator." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator." + } + ], + "type" : "INTERNAL", + "value" : "Ninja" + }, + { + "name" : "CMAKE_GENERATOR_INSTANCE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Generator instance identifier." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator platform." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_TOOLSET", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator toolset." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_HOME_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Source directory with the top level CMakeLists.txt file for this project" + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + { + "name" : "CMAKE_INSTALL_PREFIX", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install path prefix, prepended onto install directories." + } + ], + "type" : "PATH", + "value" : "/usr/local" + }, + { + "name" : "CMAKE_INSTALL_SO_NO_EXE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install .so files without execute permission." + } + ], + "type" : "INTERNAL", + "value" : "0" + }, + { + "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86" + }, + { + "name" : "CMAKE_LINKER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" + }, + { + "name" : "CMAKE_MAKE_PROGRAM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_NM", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm" + }, + { + "name" : "CMAKE_NUMBER_OF_MAKEFILES", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "number of local generators" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_OBJCOPY", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy" + }, + { + "name" : "CMAKE_OBJDUMP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump" + }, + { + "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Platform information initialized" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_PROJECT_DESCRIPTION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_HOMEPAGE_URL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "Project" + }, + { + "name" : "CMAKE_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Ranlib" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_READELF", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf" + }, + { + "name" : "CMAKE_ROOT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake installation." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" + }, + { + "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of dll's." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SKIP_INSTALL_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_SKIP_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when using shared libraries." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STRIP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Strip" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip" + }, + { + "name" : "CMAKE_SUPPRESS_DEVELOPER_ERRORS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Suppress errors that are meant for the author of the CMakeLists.txt files." + } + ], + "type" : "INTERNAL", + "value" : "TRUE" + }, + { + "name" : "CMAKE_SUPPRESS_DEVELOPER_WARNINGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Suppress Warnings that are meant for the author of the CMakeLists.txt files." + } + ], + "type" : "INTERNAL", + "value" : "TRUE" + }, + { + "name" : "CMAKE_SYSTEM_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "Android" + }, + { + "name" : "CMAKE_SYSTEM_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "26" + }, + { + "name" : "CMAKE_TOOLCHAIN_FILE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "The CMake toolchain file" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "name" : "CMAKE_UNAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "uname command" + } + ], + "type" : "INTERNAL", + "value" : "/usr/bin/uname" + }, + { + "name" : "CMAKE_VERBOSE_MAKEFILE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." + } + ], + "type" : "BOOL", + "value" : "FALSE" + }, + { + "name" : "CMAKE_WARN_DEPRECATED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Whether to issue warnings for deprecated functionality." + } + ], + "type" : "INTERNAL", + "value" : "FALSE" + }, + { + "name" : "Project_BINARY_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86" + }, + { + "name" : "Project_IS_TOP_LEVEL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "ON" + }, + { + "name" : "Project_SOURCE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + } + ], + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cmakeFiles-v1-f1661dab2653e3c04b8e.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cmakeFiles-v1-f1661dab2653e3c04b8e.json new file mode 100644 index 0000000..73685b0 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cmakeFiles-v1-f1661dab2653e3c04b8e.json @@ -0,0 +1,799 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", + "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/codemodel-v2-95b6204aa3712c2f8293.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/codemodel-v2-95b6204aa3712c2f8293.json new file mode 100644 index 0000000..996721e --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/codemodel-v2-95b6204aa3712c2f8293.json @@ -0,0 +1,43 @@ +{ + "configurations" : + [ + { + "directories" : + [ + { + "build" : ".", + "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", + "minimumCMakeVersion" : + { + "string" : "3.6.0" + }, + "projectIndex" : 0, + "source" : "." + } + ], + "name" : "Debug", + "projects" : + [ + { + "directoryIndexes" : + [ + 0 + ], + "name" : "Project" + } + ], + "targets" : [] + } + ], + "kind" : "codemodel", + "paths" : + { + "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", + "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + "version" : + { + "major" : 2, + "minor" : 3 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json new file mode 100644 index 0000000..3a67af9 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json @@ -0,0 +1,14 @@ +{ + "backtraceGraph" : + { + "commands" : [], + "files" : [], + "nodes" : [] + }, + "installers" : [], + "paths" : + { + "build" : ".", + "source" : "." + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0932.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0932.json new file mode 100644 index 0000000..b8f0a1d --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0932.json @@ -0,0 +1,92 @@ +{ + "cmake" : + { + "generator" : + { + "multiConfig" : false, + "name" : "Ninja" + }, + "paths" : + { + "cmake" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake", + "cpack" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack", + "ctest" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest", + "root" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" + }, + "version" : + { + "isDirty" : false, + "major" : 3, + "minor" : 22, + "patch" : 1, + "string" : "3.22.1-g37088a8", + "suffix" : "g37088a8" + } + }, + "objects" : + [ + { + "jsonFile" : "codemodel-v2-95b6204aa3712c2f8293.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + }, + { + "jsonFile" : "cache-v2-920dacdb871097de2130.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + { + "jsonFile" : "cmakeFiles-v1-f1661dab2653e3c04b8e.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + } + ], + "reply" : + { + "client-agp" : + { + "cache-v2" : + { + "jsonFile" : "cache-v2-920dacdb871097de2130.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + "cmakeFiles-v1" : + { + "jsonFile" : "cmakeFiles-v1-f1661dab2653e3c04b8e.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + }, + "codemodel-v2" : + { + "jsonFile" : "codemodel-v2-95b6204aa3712c2f8293.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + } + } + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeCache.txt b/android/app/.cxx/Debug/4s676p3c/x86/CMakeCache.txt new file mode 100644 index 0000000..5de09a9 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/CMakeCache.txt @@ -0,0 +1,405 @@ +# This is the CMakeCache file. +# For build in directory: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 +# It was generated by CMake: /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//No help, variable specified on the command line. +ANDROID_ABI:UNINITIALIZED=x86 + +//No help, variable specified on the command line. +ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 + +//No help, variable specified on the command line. +ANDROID_PLATFORM:UNINITIALIZED=android-26 + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line + +//No help, variable specified on the command line. +CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=x86 + +//No help, variable specified on the command line. +CMAKE_ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 + +//Archiver +CMAKE_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Flags used by the compiler during all build types. +CMAKE_ASM_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_ASM_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_ASM_FLAGS_RELEASE:STRING= + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING=Debug + +//LLVM archiver +CMAKE_CXX_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING= + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_CXX_FLAGS_RELEASE:STRING= + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C++ applications. +CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm + +//LLVM archiver +CMAKE_C_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_C_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING= + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_C_FLAGS_RELEASE:STRING= + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C applications. +CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//No help, variable specified on the command line. +CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//No help, variable specified on the command line. +CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 + +//Path to a program. +CMAKE_LINKER:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld + +//No help, variable specified on the command line. +CMAKE_MAKE_PROGRAM:UNINITIALIZED=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Project + +//Ranlib +CMAKE_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf + +//No help, variable specified on the command line. +CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Strip +CMAKE_STRIP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip + +//No help, variable specified on the command line. +CMAKE_SYSTEM_NAME:UNINITIALIZED=Android + +//No help, variable specified on the command line. +CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 + +//The CMake toolchain file +CMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +Project_BINARY_DIR:STATIC=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 + +//Value Computed by CMake +Project_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +Project_SOURCE_DIR:STATIC=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES +CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES +CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake +//Whether to issue deprecation errors for macros and functions. +CMAKE_ERROR_DEPRECATED:INTERNAL=FALSE +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Ninja +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//Suppress errors that are meant for the author of the CMakeLists.txt +// files. +CMAKE_SUPPRESS_DEVELOPER_ERRORS:INTERNAL=TRUE +//Suppress Warnings that are meant for the author of the CMakeLists.txt +// files. +CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=TRUE +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Whether to issue warnings for deprecated functionality. +CMAKE_WARN_DEPRECATED:INTERNAL=FALSE + diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake new file mode 100644 index 0000000..53c7c7c --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "Clang") +set(CMAKE_C_COMPILER_VERSION "17.0.2") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_C_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_C_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "4") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/i686-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/i386;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/i686-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/i686-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..7940e01 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake @@ -0,0 +1,83 @@ +set(CMAKE_CXX_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "Clang") +set(CMAKE_CXX_COMPILER_VERSION "17.0.2") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_CXX_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX ) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "4") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/i686-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/i386;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/i686-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/i686-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..edd4a3647d3c06d5d28cfcaf11bf082fdb0551c1 GIT binary patch literal 5828 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 S2qoFQ&Tbr)zbBP-cK-p;S0)+& literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000000000000000000000000000000000000..efba7088e248e7f7580ccc43f66c20c16bb89891 GIT binary patch literal 5984 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 literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake new file mode 100644 index 0000000..46bf291 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Darwin-24.3.0") +set(CMAKE_HOST_SYSTEM_NAME "Darwin") +set(CMAKE_HOST_SYSTEM_VERSION "24.3.0") +set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64") + +include("/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake") + +set(CMAKE_SYSTEM "Android-1") +set(CMAKE_SYSTEM_NAME "Android") +set(CMAKE_SYSTEM_VERSION "1") +set(CMAKE_SYSTEM_PROCESSOR "i686") + +set(CMAKE_CROSSCOMPILING "TRUE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..41b99d7 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,803 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..9310552de2220fe57f8bc45400db0b4e002fad4c GIT binary patch literal 3924 zcmdT{ZD?Cn7=CY(o7^^CW;^FTIwgMBkKUW6Y0_;n+tqYd+I4Iz=(>^JCO2ufBsaTB zW+qdoQ{31DKM@tgANouEp+7|ZF@y;sB8Y8O-sUsKH9L%N;Grw$KyX~=h%ApL+|?mr>442 zO=%ydFR<>z^diHl6Ye~ttvu7!?VnmaIkos7Ra01UTI1E1UUtk4&Yl6ypI$tfUObgv zJpO^U@9f0(@##%jyHr^yTF&fP(JUACk*ll}&05}eO0$y-<$6OXO(#1)EBI>7Eayxo zm&sXqvtF#t4y1&|YSgT9b-^xITej)#`?v< zHppx^yajA10d`{5?d#++Z6*API&N^GQ%9Pf;K*8kgdJ{N$F4+Sm3%_Q&RvORB0Ye+ z5kQHU-CJ@cz2izm9}9d5h-$Hmrxlg&1NlcV1-4;YP3kC?1(o19KnsQT0QSSs^3^Oz z9V3`R^ROLd+iN}%hiz`0xXAD|EPQyOx{SjbD9HCVCgmGQe6aozOzz4q3LTfeY=xeD zKVVXRhr}OX$#*@49+$qqN#6)G%Ab(mFBMi!oDZ9 zFP4d2Up2*h0bRZ)8{e@QcAZK641yZajsmn1jyhV-Irc&>+BXmz8j8o_!?#9nsT6F? zb9S)?DApkKmx`>LGpklEYL}xzD%;ZlFau@6|;S~RyYKfE!Y$PFZu$-&%EY#?q8 zWn&u?8;A0PbAvG}YYpb&gUR?!G&W@(w8qB7Tb#)0Su$p-cpt`rx>+`MIQ9_)w5x`h zE7bAs`seME)n78pX2Eh~U4~hy7<#tRFz&GC>IEZFO{S8S!K~33P8x28alG`ZF{sDm z`apkSFcljfHiwO+v}1%_IF!kZ?%X+gPiEJ|o^)pSJv-8w3@w!Nc1AXfrX-H3Dae-5 zl(<(kIX=)js?4;vj5hN>`v#S8pzx}Z=@ha&9VW**R9|p#)&H*_n&@)Ary%9NounMq zl-{mD-~=x42IzP&@w=eWi1w&&>k8HP0z8ObhAQB8Li{3~kE|d7mJx<>vHJrP9*2)- z|H+`DhB~z`)kt045X`HQ+tlz~Y9v@_lh(Fuy}^0d;r1}VAIYozEfX&@T2dz*{lV~U zJ{1LVGA~{0(FEw%zq~d-eoMXNC)F#$+TAA0lWVH|w2nRy9(-OsSiy}`(q&*C69PBo zZVJ-p%j6C^zf2C(8$yn|{u=FCW?w;l%jA_5f!vATU)FbY5N&2eXWPz*Uzt2(7m>rb zg6L63UIbFa_Wup>+eQkCM+j1IJUs%hV1#kKkgsCIr;afq?x@h;DR5fgUPjb;P{<8N z1b>PV>z)((R~WI6w}k$z(0|H^eSItRKMVZ@M(nQ>=g)C^8BuQ^Blg?Ri271O&)GjG1kd(_2R;Gt=YayVAQeyGOT9rZcUw z;XI%Z;H>{6CGoBBsate{?-g{CB)bv{=J_r&HUCy_@;vj~WIBW4^&5fA?^+VSXQuZs zkcvhyn4)-p!@yn)u7~46MSBs9!U-V+Z`yA^K=yf@zIOT?RKi&yc)LrZAIyQVGP6PJj0Ra?AeK+q2-k=W+~r7op?t+k+wVI^cOZ_gbbm@d3}Z#bc5G z^!EBakAC+qFA&5w9^VTTYT79uicqi*(>gHB%X_sOethpG$#19<2U>_!#q$K literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..25c62a8 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,791 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..76432df37b6b61f70c2e6d975b1be0efd7bd1acd GIT binary patch literal 3960 zcmdT{U1%Fu7CxiV$YV=Z>SWubjVa2KE^c={BgwL@B&M~K$XN$F4oM72O_&`^BiXH_ zQAeZTwCVp(65N+STguXhJ~S^&31y#lVOa`WwhyJdltLHwp_GL{yOjNXG3+kc@66n* zjGUVGwHNOF&fk3Z+&lN4k)AEh&nk*SvMHp}ZH;J8GV~Mz7@^@FFVWJ~n=gK?f63mn z&%dt%HWpGF3;Ktp|FZ4F(k8>km0(=bclKwX#%yR(~N5*xv zw0X6(xl!7D@dN$*@8(X-E*>nqjn-P-@s^L&?Pl#f1;$q0_N%VfSe{>NcGiW__R6cv zLT>wZvtoM{tKwAcPTgP5O$v{*?mNx)n%iu5eTyf~a}Gpzqd$Z`fqoLbCjsk%FvdY7iA@7ldLJ*4bR5XA~Kx9ec?kQUp6ZBUfCT}1JHuubAk zXg`8Ll-N&d`r%{}mOd7f$%i581&DLI9=TUO-M=G<9tiEBwV5VL8kl!yVtS97W+OjB zl+q~HH4qIJdQ^G=ha!$OVhoPQKKfOl5&co%1`x>;DK9A+9|TgTF~sLF+)Y{ukT`~C z6H4DaK=0Fk25?~RKF~i6E#&w(rm4KYdQ%3m1qO<}i9z`TG~Ro48bdHgiu6k|mc6i3 z>;nwSU!d_jx*dBT>95FG_6D*4;Mjjb<9B&Gc9`_*GM2p@JMep0_Mba zT=InXfn$%ZEZyX|TQMJyie1zH)}yBW9jZ?O24mOOH(6Cw4yMFkF>3Mt=K%e@e>Bsq zcA4p{>b6b0QtRL@j;^{5XS88A?V97s+)TUGGL7>3x_Q)D z>D0_Zdt!2;HC8s)ixXxr%Pekx+Z;3Uc_TMk8=K4)i+0hxJu$K%ti>bCnmKi9=A3nU z?$MHU=G@7WWzkx*>RPgdgqo}!p~giclz1mQNX^<>JGQv*EFfWkcnM@ZI-ko2^GZtt z8;uyBY_C@4;R1Qi6P+~=cjfzf0O$vNe9@FAPmyv-SN5jj@hdpj!?1DZ#@B^r()!D> z!-HDvG9rlHfGJJ}Mtr6IlOAN?yMeB3cdX#Xy@~Ot-qIAUZ$ST(mhNc7iK>>K(vruu zbfOl~_9j+gf#U^$nyzZ2J%MId8$h6%NKVBxq`~yP?e&Nnr+?mxsQ9X?#KnkP9$lfk z0$C0!X;KVOy~97W#V>a>G^=zkeIX)vA9rHD#Ym1k+hyVBIzB`R`g@PA)9D^PMI$|W znsy7m@c9A4r-TLuD2VGv!8-)KKScpgKbB*$K1k#-axj|04}S~dD@Y0kP?6HdYYFil zM*KXuPw4kE;x%U(!8B0~&xp8-!u|>)CV5TRuM7Jx8Fvu9FYKQP`{#^U z&)35KKVcuhz9?AV4o2iV%!u`8gq~wWo`-~fT;Mr@s{%U$GvJMJJoEE0HY!}~EPG|e zb1snKqoxoS=7xhRVR%m6sMx-31XZM4m%gF!Y!`Y*2@?~xeQzs$w>WN7(!(i&bU7V7 z?gqKtS>}RBUWySEye+wP%dXLMeaARF^ceiDfAclvS8V3SRX zI8M0p_@)a-K?VpE*Mj~GJsLL+J*bN!PF9W2pkpeU7WOIJ3%&wy#w?Bo8tK)IG8j4~&Vl=9P%qx04=3D3jx^4jFQUqNPG$v3qP-%Z3s`TPhU z^Gd!UJRjwo-iB`w_9)+_2p>vSmoKOhk^GKs!#B4jzn3C>T%TlqKZG33@2A`Fam|Y6 z$A5QtoxFcsA|>B%ATu9de{TGfS-wNo*~g7h%B(*Fa<&{teH_XOr6v)Wu(iVlc9gdr(Uw_L{sX z!p1S&#v!mQr&>i^G4O-~=f{m}ZqGWP$bH@ozg))yf-iUo!`tBdxm18W7q@*|_}+@} c;ono2kN@Gw-1xaEd=Hp}c{m@Qm+$cZ0ohYm6951J literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..15fd9a6 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,2 @@ +/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/edit_cache.dir +/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rules.ninja b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rules.ninja new file mode 100644 index 0000000..fd37716 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rules.ninja @@ -0,0 +1,45 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the rules used to get the outputs files +# built from the input files. +# It is included in the main 'build.ninja'. + +# ============================================================================= +# Project: Project +# Configurations: Debug +# ============================================================================= +# ============================================================================= + +############################################# +# Rule for running custom commands. + +rule CUSTOM_COMMAND + command = $COMMAND + description = $DESC + + +############################################# +# Rule for re-running cmake. + +rule RERUN_CMAKE + command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 + description = Re-running CMake... + generator = 1 + + +############################################# +# Rule for cleaning all built files. + +rule CLEAN + command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja $FILE_ARG -t clean $TARGETS + description = Cleaning all built files... + + +############################################# +# Rule for printing all primary targets available. + +rule HELP + command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja -t targets + description = All primary targets available: + diff --git a/android/app/.cxx/Debug/4s676p3c/x86/additional_project_files.txt b/android/app/.cxx/Debug/4s676p3c/x86/additional_project_files.txt new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json b/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json new file mode 100644 index 0000000..5e59a91 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json @@ -0,0 +1,28 @@ +{ + "buildFiles": [ + "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": {}, + "toolchains": { + "toolchain": { + "cCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang.lld", + "cppCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++.lld" + } + }, + "cFileExtensions": [], + "cppFileExtensions": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json b/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json new file mode 100644 index 0000000..984990b --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json @@ -0,0 +1,20 @@ +{ + "buildFiles": [ + "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", + "-C", + "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": {} +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/build.ninja b/android/app/.cxx/Debug/4s676p3c/x86/build.ninja new file mode 100644 index 0000000..908e700 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/build.ninja @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the build statements describing the +# compilation DAG. + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# +# Which is the root file. +# ============================================================================= + +# ============================================================================= +# Project: Project +# Configurations: Debug +# ============================================================================= + +############################################# +# Minimal version of Ninja required by this file + +ninja_required_version = 1.5 + + +############################################# +# Set configuration variable for custom commands. + +CONFIGURATION = Debug +# ============================================================================= +# Include auxiliary files. + + +############################################# +# Include rules file. + +include CMakeFiles/rules.ninja + +# ============================================================================= + +############################################# +# Logical path to working directory; prefix for absolute paths. + +cmake_ninja_workdir = /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/ + +############################################# +# Utility command for edit_cache + +build CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 + DESC = Running CMake cache editor... + pool = console + restat = 1 + +build edit_cache: phony CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build rebuild_cache: phony CMakeFiles/rebuild_cache.util + +# ============================================================================= +# Target aliases. + +# ============================================================================= +# Folder targets. + +# ============================================================================= + +############################################# +# Folder: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 + +build all: phony + +# ============================================================================= +# Built-in targets + + +############################################# +# Re-run CMake if any of its inputs changed. + +build build.ninja: RERUN_CMAKE | /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake + pool = console + + +############################################# +# A missing CMake input file is not an error. + +build /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake: phony + + +############################################# +# Clean all the built files. + +build clean: CLEAN + + +############################################# +# Print all primary targets available. + +build help: HELP + + +############################################# +# Make the all target the default. + +default all diff --git a/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt b/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt new file mode 100644 index 0000000..ec6a72a --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt @@ -0,0 +1 @@ +/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/cmake_install.cmake b/android/app/.cxx/Debug/4s676p3c/x86/cmake_install.cmake new file mode 100644 index 0000000..3ec8b80 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/cmake_install.cmake @@ -0,0 +1,54 @@ +# Install script for directory: /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Debug") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "0") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "TRUE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin new file mode 100644 index 0000000..f93955d --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin @@ -0,0 +1,28 @@ +C/C++ Structured Logo +m +k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/additional_project_files.txtC +A +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ÒÔ á×2  ÐÔ á×2l +j +h/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json  ÒÔ á×2à ÑÔ á×2q +o +m/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json  ÒÔ á×2Î ÒÔ á×2^ +\ +Z/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build.ninja  ÒÔ á×2ðà ÄÔ á×2b +` +^/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build.ninja.txt  ÒÔ á×2g +e +c/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt  ÒÔ á×2 P ÒÔ á×2h +f +d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/compile_commands.json  ÒÔ á×2l +j +h/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/compile_commands.json.bin  ÒÔ á×2 r +p +n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt  ÒÔ á×2 +  ÒÔ á×2e +c +a/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json  ÒÔ á×2  ( ÒÔ á×2j +h +f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt  ÒÔ á×2  ] ÒÔ á×2T +R +P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  ÒÔ á×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt b/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt new file mode 100644 index 0000000..2aed5c8 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt @@ -0,0 +1,20 @@ + -H/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy +-DCMAKE_SYSTEM_NAME=Android +-DCMAKE_EXPORT_COMPILE_COMMANDS=ON +-DCMAKE_SYSTEM_VERSION=26 +-DANDROID_PLATFORM=android-26 +-DANDROID_ABI=x86 +-DCMAKE_ANDROID_ARCH_ABI=x86 +-DANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 +-DCMAKE_ANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 +-DCMAKE_TOOLCHAIN_FILE=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake +-DCMAKE_MAKE_PROGRAM=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja +-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 +-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 +-DCMAKE_BUILD_TYPE=Debug +-B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 +-GNinja +-Wno-dev +--no-warn-unused-cli + Build command args: [] + Version: 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json b/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json new file mode 100644 index 0000000..e799de8 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json @@ -0,0 +1,4 @@ +{ + "enabled": false, + "packages": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt b/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt new file mode 100644 index 0000000..ec94a09 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt @@ -0,0 +1 @@ +/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cache-v2 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cmakeFiles-v1 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/codemodel-v2 new file mode 100644 index 0000000..e69de29 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cache-v2-2b5d080db4293a9c0f40.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cache-v2-2b5d080db4293a9c0f40.json new file mode 100644 index 0000000..54f6d66 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cache-v2-2b5d080db4293a9c0f40.json @@ -0,0 +1,1391 @@ +{ + "entries" : + [ + { + "name" : "ANDROID_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "x86_64" + }, + { + "name" : "ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" + }, + { + "name" : "ANDROID_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "android-26" + }, + { + "name" : "CMAKE_ADDR2LINE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line" + }, + { + "name" : "CMAKE_ANDROID_ARCH_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "x86_64" + }, + { + "name" : "CMAKE_ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" + }, + { + "name" : "CMAKE_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_ASM_FLAGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_BUILD_TYPE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." + } + ], + "type" : "STRING", + "value" : "Debug" + }, + { + "name" : "CMAKE_CACHEFILE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "This is the directory where this CMakeCache.txt was created" + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64" + }, + { + "name" : "CMAKE_CACHE_MAJOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Major version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "3" + }, + { + "name" : "CMAKE_CACHE_MINOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Minor version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "22" + }, + { + "name" : "CMAKE_CACHE_PATCH_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Patch version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake" + }, + { + "name" : "CMAKE_CPACK_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cpack program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack" + }, + { + "name" : "CMAKE_CTEST_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to ctest program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest" + }, + { + "name" : "CMAKE_CXX_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "(This variable does not exist and should not be used)" + } + ], + "type" : "UNINITIALIZED", + "value" : "" + }, + { + "name" : "CMAKE_CXX_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_CXX_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_CXX_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_CXX_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C++ applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_C_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "(This variable does not exist and should not be used)" + } + ], + "type" : "UNINITIALIZED", + "value" : "" + }, + { + "name" : "CMAKE_C_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_C_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_C_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_C_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_C_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_DLLTOOL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "CMAKE_DLLTOOL-NOTFOUND" + }, + { + "name" : "CMAKE_EDIT_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cache edit program executable." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake" + }, + { + "name" : "CMAKE_ERROR_DEPRECATED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Whether to issue deprecation errors for macros and functions." + } + ], + "type" : "INTERNAL", + "value" : "FALSE" + }, + { + "name" : "CMAKE_EXECUTABLE_FORMAT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Executable file format" + } + ], + "type" : "INTERNAL", + "value" : "ELF" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "ON" + }, + { + "name" : "CMAKE_EXTRA_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of external makefile project generator." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator." + } + ], + "type" : "INTERNAL", + "value" : "Ninja" + }, + { + "name" : "CMAKE_GENERATOR_INSTANCE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Generator instance identifier." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator platform." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_TOOLSET", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator toolset." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_HOME_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Source directory with the top level CMakeLists.txt file for this project" + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + { + "name" : "CMAKE_INSTALL_PREFIX", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install path prefix, prepended onto install directories." + } + ], + "type" : "PATH", + "value" : "/usr/local" + }, + { + "name" : "CMAKE_INSTALL_SO_NO_EXE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install .so files without execute permission." + } + ], + "type" : "INTERNAL", + "value" : "0" + }, + { + "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86_64" + }, + { + "name" : "CMAKE_LINKER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" + }, + { + "name" : "CMAKE_MAKE_PROGRAM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_NM", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm" + }, + { + "name" : "CMAKE_NUMBER_OF_MAKEFILES", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "number of local generators" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_OBJCOPY", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy" + }, + { + "name" : "CMAKE_OBJDUMP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump" + }, + { + "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Platform information initialized" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_PROJECT_DESCRIPTION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_HOMEPAGE_URL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "Project" + }, + { + "name" : "CMAKE_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Ranlib" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_READELF", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf" + }, + { + "name" : "CMAKE_ROOT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake installation." + } + ], + "type" : "INTERNAL", + "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" + }, + { + "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86_64" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of dll's." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SKIP_INSTALL_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_SKIP_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when using shared libraries." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STRIP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Strip" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip" + }, + { + "name" : "CMAKE_SUPPRESS_DEVELOPER_ERRORS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Suppress errors that are meant for the author of the CMakeLists.txt files." + } + ], + "type" : "INTERNAL", + "value" : "TRUE" + }, + { + "name" : "CMAKE_SUPPRESS_DEVELOPER_WARNINGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Suppress Warnings that are meant for the author of the CMakeLists.txt files." + } + ], + "type" : "INTERNAL", + "value" : "TRUE" + }, + { + "name" : "CMAKE_SYSTEM_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "Android" + }, + { + "name" : "CMAKE_SYSTEM_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "26" + }, + { + "name" : "CMAKE_TOOLCHAIN_FILE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "The CMake toolchain file" + } + ], + "type" : "FILEPATH", + "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "name" : "CMAKE_UNAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "uname command" + } + ], + "type" : "INTERNAL", + "value" : "/usr/bin/uname" + }, + { + "name" : "CMAKE_VERBOSE_MAKEFILE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." + } + ], + "type" : "BOOL", + "value" : "FALSE" + }, + { + "name" : "CMAKE_WARN_DEPRECATED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Whether to issue warnings for deprecated functionality." + } + ], + "type" : "INTERNAL", + "value" : "FALSE" + }, + { + "name" : "Project_BINARY_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64" + }, + { + "name" : "Project_IS_TOP_LEVEL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "ON" + }, + { + "name" : "Project_SOURCE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + } + ], + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-9a2bf79ff0a2a89eb505.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-9a2bf79ff0a2a89eb505.json new file mode 100644 index 0000000..bc82f99 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-9a2bf79ff0a2a89eb505.json @@ -0,0 +1,799 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64", + "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/codemodel-v2-852402f1316f6f65a056.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/codemodel-v2-852402f1316f6f65a056.json new file mode 100644 index 0000000..29446e0 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/codemodel-v2-852402f1316f6f65a056.json @@ -0,0 +1,43 @@ +{ + "configurations" : + [ + { + "directories" : + [ + { + "build" : ".", + "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", + "minimumCMakeVersion" : + { + "string" : "3.6.0" + }, + "projectIndex" : 0, + "source" : "." + } + ], + "name" : "Debug", + "projects" : + [ + { + "directoryIndexes" : + [ + 0 + ], + "name" : "Project" + } + ], + "targets" : [] + } + ], + "kind" : "codemodel", + "paths" : + { + "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64", + "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" + }, + "version" : + { + "major" : 2, + "minor" : 3 + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json new file mode 100644 index 0000000..3a67af9 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json @@ -0,0 +1,14 @@ +{ + "backtraceGraph" : + { + "commands" : [], + "files" : [], + "nodes" : [] + }, + "installers" : [], + "paths" : + { + "build" : ".", + "source" : "." + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T18-26-02-0299.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T18-26-02-0299.json new file mode 100644 index 0000000..0148bde --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T18-26-02-0299.json @@ -0,0 +1,92 @@ +{ + "cmake" : + { + "generator" : + { + "multiConfig" : false, + "name" : "Ninja" + }, + "paths" : + { + "cmake" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake", + "cpack" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack", + "ctest" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest", + "root" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" + }, + "version" : + { + "isDirty" : false, + "major" : 3, + "minor" : 22, + "patch" : 1, + "string" : "3.22.1-g37088a8", + "suffix" : "g37088a8" + } + }, + "objects" : + [ + { + "jsonFile" : "codemodel-v2-852402f1316f6f65a056.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + }, + { + "jsonFile" : "cache-v2-2b5d080db4293a9c0f40.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + { + "jsonFile" : "cmakeFiles-v1-9a2bf79ff0a2a89eb505.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + } + ], + "reply" : + { + "client-agp" : + { + "cache-v2" : + { + "jsonFile" : "cache-v2-2b5d080db4293a9c0f40.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + "cmakeFiles-v1" : + { + "jsonFile" : "cmakeFiles-v1-9a2bf79ff0a2a89eb505.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + }, + "codemodel-v2" : + { + "jsonFile" : "codemodel-v2-852402f1316f6f65a056.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + } + } + } +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt new file mode 100644 index 0000000..63f4eca --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt @@ -0,0 +1,405 @@ +# This is the CMakeCache file. +# For build in directory: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64 +# It was generated by CMake: /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//No help, variable specified on the command line. +ANDROID_ABI:UNINITIALIZED=x86_64 + +//No help, variable specified on the command line. +ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 + +//No help, variable specified on the command line. +ANDROID_PLATFORM:UNINITIALIZED=android-26 + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line + +//No help, variable specified on the command line. +CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=x86_64 + +//No help, variable specified on the command line. +CMAKE_ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 + +//Archiver +CMAKE_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Flags used by the compiler during all build types. +CMAKE_ASM_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_ASM_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_ASM_FLAGS_RELEASE:STRING= + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING=Debug + +//LLVM archiver +CMAKE_CXX_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING= + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_CXX_FLAGS_RELEASE:STRING= + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C++ applications. +CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm + +//LLVM archiver +CMAKE_C_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_C_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING= + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_C_FLAGS_RELEASE:STRING= + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C applications. +CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//No help, variable specified on the command line. +CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//No help, variable specified on the command line. +CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86_64 + +//Path to a program. +CMAKE_LINKER:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld + +//No help, variable specified on the command line. +CMAKE_MAKE_PROGRAM:UNINITIALIZED=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Project + +//Ranlib +CMAKE_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf + +//No help, variable specified on the command line. +CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86_64 + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Strip +CMAKE_STRIP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip + +//No help, variable specified on the command line. +CMAKE_SYSTEM_NAME:UNINITIALIZED=Android + +//No help, variable specified on the command line. +CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 + +//The CMake toolchain file +CMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +Project_BINARY_DIR:STATIC=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64 + +//Value Computed by CMake +Project_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +Project_SOURCE_DIR:STATIC=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64 +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES +CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES +CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake +//Whether to issue deprecation errors for macros and functions. +CMAKE_ERROR_DEPRECATED:INTERNAL=FALSE +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Ninja +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//Suppress errors that are meant for the author of the CMakeLists.txt +// files. +CMAKE_SUPPRESS_DEVELOPER_ERRORS:INTERNAL=TRUE +//Suppress Warnings that are meant for the author of the CMakeLists.txt +// files. +CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=TRUE +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Whether to issue warnings for deprecated functionality. +CMAKE_WARN_DEPRECATED:INTERNAL=FALSE + diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake new file mode 100644 index 0000000..f2a3233 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "Clang") +set(CMAKE_C_COMPILER_VERSION "17.0.2") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_C_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_C_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/x86_64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/x86_64;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/x86_64-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/x86_64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..788db59 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake @@ -0,0 +1,83 @@ +set(CMAKE_CXX_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "Clang") +set(CMAKE_CXX_COMPILER_VERSION "17.0.2") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_CXX_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX ) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/x86_64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/x86_64;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/x86_64-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/x86_64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..c64b2be383508ad525bfcfa4c9d967cab98de8d8 GIT binary patch literal 7008 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 literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000000000000000000000000000000000000..b6b339d14b87ec4b8dedb69b779399804a7a134c GIT binary patch literal 7176 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 literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake new file mode 100644 index 0000000..1f4f5dd --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Darwin-24.3.0") +set(CMAKE_HOST_SYSTEM_NAME "Darwin") +set(CMAKE_HOST_SYSTEM_VERSION "24.3.0") +set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64") + +include("/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake") + +set(CMAKE_SYSTEM "Android-1") +set(CMAKE_SYSTEM_NAME "Android") +set(CMAKE_SYSTEM_VERSION "1") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "TRUE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..41b99d7 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,803 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..86331b4288bfd131e78c6da1fb2d30554f35ab88 GIT binary patch literal 5424 zcmdT|U5pb|6uvXvb_-n!%ZmJ);x8aO?RLBEf&`W<3%iEDAgH*(I@`{67urslPH`bI zJgCTuCJ-MaQ4(S_(eNPpVDN<(9*CM4qA`&K^+Aj#?t?!uVkF`@cg|^Nr-M=6Jj={I z=ey_c{+&DJ$iS9Os-g%cMXVDIiBTaE(FWfq**>uZGR5*O{+A#WxQOQAW*k*W5dK(ZM~e=t$a3bjOw+bJ=~R{9%I5b%GGhRT&?$Q z-?kTrDrs8G>_Njq)!~Gsu8ig|i3Bsrh9!IOZN-Bm!&**+^s^u&pUzhdS0TWV7&W&=+FH{j!;< zL72Irz6F6ODm<_dRfUKIg-Q@Ax22|u;(gdJEi&t{+&N2qNANnJ>RNayuP8GDtP&Um zu4OyC<_WpjAq7SzM7XsTn<6~Z^uq@LnSn;K|0V1{tGfJQzx0=+Xjfgm4WDjQ{S3W) z<I7?hMZjG6cnk1Y)z3)W6Q^EyHZ^fkHhIf z?^?k$3q_-9)~uYN!BLFcrdiC5>Eq>iv3Ri5S+UH0M$V4qSC96t9!=%D(&=<}z9-R@ zGf7cqe=^eON zft15Lg)%WmS=`ndJ^`C}31Ijj;n@%yqH~U_{j);qtDqsovjDY-mGD*+<&)=7V6+yDgsugnp@OF!BRLQqoz^omG!_hmB5PF@VzR%c zb`^BBh@WpZbzpG#^P_-sjGMXwqP+=2AW)yZ>D>VVMcqRmfjrk0SI#M5FT&F4exBqzT{!zhXpsv?KcA3%7qyrV&IMD7 z7|xUNA!0c0MpOXeaWFna_+w6YJ^#Ig=LtuV_Y^`;6V872lm2srquAJuLcHO^alLq5 z&JxakCdd!Z6N-)9F2u(kKPyT8#^dKG`I&O*V+^Lhh(R^Xhu6J>>^L8+c}Ov8vEj8w zJn6#G56|yr!r9NeB=2(RH%^}rJm1*uUSFP9_H&u+4^zwd6_O`C_}3(#^5EZ+{FVp* zg5((FfrPoZ^T|lmITvnRXnDNRv--%0WgHZm4OgYWFOQM|ccW$*MP1A5wyw!5x_;mK zT&TCyZMvH&WYxBs0@S|&$eYX!LxZN-$b&x)94*XQllQqdhx&JeRyJ)z+q`XeCuEb` z-xODVQn+Il$IAw38DrT|OD`FI*PsT2u=Nq4RS%V9OIZTkrE!g=slTmeJ*=x=oxDt& z`AJ%LcJ2`c-Ux`fYZdDD;me2IwGq27!t+n|eDATVIm}Rd0b2CgM>03(s3@HvU@^2f zPOeq(6HU@~2#)dj{v%jiC8o##wWy24E!H*Uy>mE73LFn@ki7B{!2I&>qvFPSV*WVC zY|r>RfMKX0A#eUSZV{jBE9--rB(MBC zpnmZyKJoG1VSAoG{HcpW^^TwGBI|>SB(MB1pnma>`NYS%&h{Mt9>DzKpZS;bkN3Y{ z{4+lB@vM5|V;BkrT!Y>w@U;dcIj`<%K)o0$_S1&^z|-jw#VOGB%l|y({{#8K{g2;F z-u!LA&}RZ3H~m2i`lBZxi`?S(hM)a4`dItW?UZy8V*Br1JmO5Jy#Db;MyneHyjhBK~=w c`1mWw8y~-iyko}zPs#rqYSb}|i;&m;ZvzX2*Z=?k literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..25c62a8 --- /dev/null +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,791 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..8e8b9745e57615780f80d9ddc015a979d1896160 GIT binary patch literal 5480 zcmdT{U2GIp6uvXl?GM{7Efql^WQk$`?d(st+bs|*sl}G?7X$;;W}WU%cNcbdmf2ZS zOcbL;t%O8;Fh20$Bl?0d#Gr}B#0S*GpC=!TiN-)e3`Q`KU?Ac-ckY?Jolceb=1q3a zIo~~h_xIdAF}h=$swj+_!nUxcL?~m$NRuDt>@Zsen)}CQuUs0vgUIZ2x5j20*DsA; zLuu?(h?CsTTZ=zwY1c-t&5m9R20>-)G}rz&%^;trMz2kNHoj}y?u|LCQY)2Bdt#() zR11@ggSE2ZOj~wkVn?akm=U01=ZX`8uRBIHZ`k>4-kdfXWoIHWD0<8p$E?;%R<-W+ z?cOzsqq_GtC$a1?(?)+2ao!Sxy354l#3Uz~(xa@6^oF!Z_p+6d9%V@@V`_?x_ihYt z3aQH((-dXAm$8;LfDMKj3q1@BW33M{EwUvX2BZzyaCi%_?I~c#dmnp%tUDHS?L{u` zqE%SiunuvTv<@%VA_$@hW1S(UdH`cxsW~G105(bspNe+AW!3~v%PWAYo8hCJR5~^A_&9wq1{=@4#8%QNe1iZHk?A`Ddd&A>Nzm$ zRL{)J6>CB~54~OLnKBm@4VB%g4YhP!0HFitnr*G-ZL5@zu1mxR29oh)=F#XQwSooT zDXZ)NDLWwaRmzA>8Fe!swW?7&l^GmN4d&NJb9lg_VmC)|AM45Jx}xLM>KkJ*I8W$Z zFIZNgY}T!YoilYfoH56;%DJLZs>aIYW0k&|Z5=jqPBcF>of(==F=E#8qBjTiw=k;8z#$x;HaIj*B8%8y@$F`1x zQ>z{`@`VPR>%O8@G5ab;)hL)Y{5 z+u$;($NKeTQcv_1`Um5gjFE{oV?!bghGVmAcI)1~TMuTR96vOg-FI-$Xg14A)oCkB zHe7l6>>=8a8;g}WS{N4o_{d7qu*>9PcMM)5jZcSz~fkn$1a*l#CeTH5ZV%#aDBut3i*Bsr@2IE zg@mL2H$q-5DCX~-6yQ@5F3-a*fm1%)(GVK0J2t|13;byp_VAp*O9Dp`ZK%B<7{oCy z&GW3l$^TK|=S@l9tGj@mlW_F2LC7BqN`6iVKVM4v&0Wga4-$@kXdQ3({LBhJe@XhZ zb_jKgekACJ)_twODIZ?=p+70<QE|dLADDSz~I-Hjgpgfg;QBu~IRi zZ0fdIHuSvV7&@=3UZoBw#S7}rtLh?T-LdBd@E!~cymUkmo-$?x4lJJD{MzrT;&^oa z4DjdYy+-t^<(T>tyY}}%rnw{Ya^epaIdHjDHHDU0%ud@z1wa1#m*A z%T}zxe<8Rp=T|@QBsO(HtUvkoiEJ@+ASU05s5^|GfQDyFZa;$XPxe&j$fjA5UF3Tp z=yTW=z3)%ra^=r?Kv%*K$4PhYa-n$uf@6HSzGK%V(O(vn2L|!fBX($=rayKx!n{8Li0@w#V3mImmvE;MUnnc zb}DocB6|%O;$_wM{THI>^y_YM?Q6a?*+pTWk(~lh<0p6s>;vadJZ@;8;QTF<>=^^YAR&EO*#T2TZ=3.6.0 <4.0.0" + dart: ">=3.7.0 <4.0.0" flutter: ">=3.27.0" From ce7a8e8cc5d659aae6301bdd934b7c49bbac52ed Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 9 Mar 2025 19:45:48 +0100 Subject: [PATCH 663/676] Extracted some regexps to external file --- lib/constants/regexps.dart | 12 ++++++++++++ lib/functions/is_ip.dart | 6 +++--- lib/l10n/app_es.arb | 2 +- lib/screens/filters/details/add_list_modal.dart | 4 ++-- lib/screens/filters/details/check_host_modal.dart | 4 ++-- .../modals/custom_rules/add_custom_rule.dart | 4 ++-- .../settings/dhcp/add_static_lease_modal.dart | 7 +++---- lib/screens/settings/dhcp/dhcp.dart | 9 +++++---- lib/screens/settings/dns/bootstrap_dns.dart | 4 ++-- lib/screens/settings/dns/fallback_dns.dart | 5 ++--- .../settings/dns/rate_limit_allowlist_modal.dart | 4 ++-- .../settings/dns_rewrites/dns_rewrite_modal.dart | 4 ++-- .../settings/encryption/encryption_functions.dart | 13 +++++-------- .../settings/logs_settings/config_widgets.dart | 4 ++-- .../statistics_settings/statistics_settings.dart | 4 ++-- lib/widgets/add_server/add_server_functions.dart | 8 +++----- 16 files changed, 50 insertions(+), 44 deletions(-) create mode 100644 lib/constants/regexps.dart diff --git a/lib/constants/regexps.dart b/lib/constants/regexps.dart new file mode 100644 index 0000000..84ea2bc --- /dev/null +++ b/lib/constants/regexps.dart @@ -0,0 +1,12 @@ +class Regexps { + static final wildcardDomain = RegExp(r'^(\*\.)?([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); + static final domain = RegExp(r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$'); + static final ipv4Address = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); + static final ipv6Address = RegExp(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 subroute = RegExp(r'^\/\b([A-Za-z0-9_\-~/]*)[^\/|\.|\:]$'); + static final macAddress = RegExp(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'); + static final url = RegExp(r'^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})$'); + static final certificate = RegExp(r'(-{3,}(\bBEGIN CERTIFICATE\b))|(-{3,}-{3,}(\END CERTIFICATE\b)-{3,})', multiLine: true); + static final privateKey = RegExp(r'(-{3,}(\bBEGIN\b).*(PRIVATE KEY\b))|(-{3,}-{3,}(\bEND\b).*(PRIVATE KEY\b)-{3,})', multiLine: true); + static final path = RegExp(r'^(\/{0,1}(?!\/))[A-Za-z0-9\/\-_]+(\.([a-zA-Z]+))?$'); +} \ No newline at end of file diff --git a/lib/functions/is_ip.dart b/lib/functions/is_ip.dart index 667bf0b..73ee1e9 100644 --- a/lib/functions/is_ip.dart +++ b/lib/functions/is_ip.dart @@ -1,7 +1,7 @@ +import 'package:adguard_home_manager/constants/regexps.dart'; + bool isIpAddress(String value) { - final ipv4Regexp = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$'); - final ipv6Regexp = RegExp(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]))'); - if (ipv4Regexp.hasMatch(value) || ipv6Regexp.hasMatch(value)) { + if (Regexps.ipv4Address.hasMatch(value) || Regexps.ipv6Address.hasMatch(value)) { return true; } else { diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index d18f8a9..19a36cf 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -403,7 +403,7 @@ "dnsRewriteRuleDeleted": "Reescritura DNS eliminada correctamente", "dnsRewriteRuleNotDeleted": "La reescritura DNS no pudo ser eliminada", "addDnsRewrite": "Añadir reescritura DNS", - "addingRewrite": "Añadiend reescritura...", + "addingRewrite": "Añadiendo reescritura...", "dnsRewriteRuleAdded": "Regla de reescritura DNS añadida correctamente", "dnsRewriteRuleNotAdded": "La regla de reescritura DNS no ha podido ser añadida", "logsSettings": "Ajustes de registros", diff --git a/lib/screens/filters/details/add_list_modal.dart b/lib/screens/filters/details/add_list_modal.dart index d5579a6..f153224 100644 --- a/lib/screens/filters/details/add_list_modal.dart +++ b/lib/screens/filters/details/add_list_modal.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -97,8 +98,7 @@ class _ContentState extends State<_Content> { } void validateUrl(String value) { - final urlRegex = RegExp(r'^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})$'); - if (urlRegex.hasMatch(value)) { + if (Regexps.url.hasMatch(value)) { setState(() => urlError = null); } else { diff --git a/lib/screens/filters/details/check_host_modal.dart b/lib/screens/filters/details/check_host_modal.dart index 3065588..be0efce 100644 --- a/lib/screens/filters/details/check_host_modal.dart +++ b/lib/screens/filters/details/check_host_modal.dart @@ -1,5 +1,6 @@ // ignore_for_file: use_build_context_synchronously +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -63,8 +64,7 @@ class _ContentState extends State<_Content> { Widget? resultWidget; void validateDomain(String value) { - final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); - if (domainRegex.hasMatch(value)) { + if (Regexps.domain.hasMatch(value)) { setState(() => domainError = null); } else { diff --git a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart index b528c02..674c200 100644 --- a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart +++ b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:segmented_button_slide/segmented_button_slide.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -41,8 +42,7 @@ class _AddCustomRuleState extends State { } void validateDomain(String value) { - final domainRegex = RegExp(r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$'); - if (domainRegex.hasMatch(value)) { + if (Regexps.domain.hasMatch(value)) { setState(() => _domainError = null); } else { diff --git a/lib/screens/settings/dhcp/add_static_lease_modal.dart b/lib/screens/settings/dhcp/add_static_lease_modal.dart index c80e848..d40c506 100644 --- a/lib/screens/settings/dhcp/add_static_lease_modal.dart +++ b/lib/screens/settings/dhcp/add_static_lease_modal.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -67,8 +68,7 @@ class __ContentState extends State<_Content> { bool validData = false; void validateMac(String value) { - final RegExp macRegex = RegExp(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'); - if (macRegex.hasMatch(value)) { + if (Regexps.macAddress.hasMatch(value)) { setState(() => macError = null); } else { @@ -78,8 +78,7 @@ class __ContentState extends State<_Content> { } void validateIp(String value) { - RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); - if (ipAddress.hasMatch(value) == true) { + if (Regexps.ipv4Address.hasMatch(value) == true) { setState(() => ipError = null); } else { diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 449b063..76867ef 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -2,6 +2,7 @@ import 'dart:io'; +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -100,8 +101,8 @@ class _DhcpScreenState extends State { break; } } - final regex = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$'); - if (regex.hasMatch(value)) { + + if (Regexps.ipv4Address.hasMatch(value)) { setValue(null); } else { @@ -126,8 +127,8 @@ class _DhcpScreenState extends State { break; } } - final regex = RegExp(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]))$'); - if (regex.hasMatch(value)) { + + if (Regexps.ipv6Address.hasMatch(value)) { setValue(null); } else { diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index 833396d..dba929a 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -1,5 +1,6 @@ // ignore_for_file: use_build_context_synchronously +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -23,8 +24,7 @@ class _BootstrapDnsScreenState extends State { bool validValues = false; void validateIp(Map field, String value) { - RegExp ipAddress = RegExp(r'(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$)'); - if (ipAddress.hasMatch(value) == true) { + if (Regexps.ipv4Address.hasMatch(value) == true || Regexps.ipv6Address.hasMatch(value) == true) { setState(() => field['error'] = null); } else { diff --git a/lib/screens/settings/dns/fallback_dns.dart b/lib/screens/settings/dns/fallback_dns.dart index 19040ed..6c8d8ce 100644 --- a/lib/screens/settings/dns/fallback_dns.dart +++ b/lib/screens/settings/dns/fallback_dns.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:adguard_home_manager/screens/settings/dns/comment_modal.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -24,9 +25,7 @@ class _FallbackDnsScreenState extends State { bool validValues = false; void validateIp(Map field, String value) { - RegExp ipAddress = RegExp(r'(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$)'); - RegExp url = RegExp(r'(https?|tls):\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'); - if (ipAddress.hasMatch(value) == true || url.hasMatch(value) == true) { + if (Regexps.ipv4Address.hasMatch(value) == true || Regexps.ipv6Address.hasMatch(value) || Regexps.url.hasMatch(value) == true) { setState(() => field['error'] = null); } else { diff --git a/lib/screens/settings/dns/rate_limit_allowlist_modal.dart b/lib/screens/settings/dns/rate_limit_allowlist_modal.dart index e5b678e..2c2fed8 100644 --- a/lib/screens/settings/dns/rate_limit_allowlist_modal.dart +++ b/lib/screens/settings/dns/rate_limit_allowlist_modal.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -33,8 +34,7 @@ class _RateLimitAllowlistModalState extends State { List<_IpListItemController> _controllersList = []; void _validateIp(String value, _IpListItemController item) { - final regexp = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); - if (regexp.hasMatch(value)) { + if (Regexps.ipv4Address.hasMatch(value)) { setState(() => _controllersList = _controllersList.map((e) { if (e.id == item.id) { return _IpListItemController( diff --git a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart index 439455c..42524fa 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -82,8 +83,7 @@ class _ContentState extends State<_Content> { bool validData = false; void validateDomain(String value) { - final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); - if (domainRegex.hasMatch(value)) { + if (Regexps.wildcardDomain.hasMatch(value)) { setState(() => domainError = null); } else { diff --git a/lib/screens/settings/encryption/encryption_functions.dart b/lib/screens/settings/encryption/encryption_functions.dart index c9c0c4b..c7700e4 100644 --- a/lib/screens/settings/encryption/encryption_functions.dart +++ b/lib/screens/settings/encryption/encryption_functions.dart @@ -1,11 +1,11 @@ +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; String? validateDomain(BuildContext context, String domain) { - RegExp regExp = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); - if (regExp.hasMatch(domain)) { + if (Regexps.domain.hasMatch(domain)) { return null; } else { @@ -23,8 +23,7 @@ String? validatePort(BuildContext context, String value) { } String? validateCertificate(BuildContext context, String cert) { - final regExp = RegExp(r'(-{3,}(\bBEGIN CERTIFICATE\b))|(-{3,}-{3,}(\END CERTIFICATE\b)-{3,})', multiLine: true); - if (regExp.hasMatch(cert.replaceAll('\n', ''))) { + if (Regexps.certificate.hasMatch(cert.replaceAll('\n', ''))) { return null; } else { @@ -33,8 +32,7 @@ String? validateCertificate(BuildContext context, String cert) { } String? validatePrivateKey(BuildContext context, String cert) { - final regExp = RegExp(r'(-{3,}(\bBEGIN\b).*(PRIVATE KEY\b))|(-{3,}-{3,}(\bEND\b).*(PRIVATE KEY\b)-{3,})', multiLine: true); - if (regExp.hasMatch(cert.replaceAll('\n', ''))) { + if (Regexps.privateKey.hasMatch(cert.replaceAll('\n', ''))) { return null; } else { @@ -43,8 +41,7 @@ String? validatePrivateKey(BuildContext context, String cert) { } String? validatePath(BuildContext context, String cert) { - final regExp = RegExp(r'^(\/{0,1}(?!\/))[A-Za-z0-9\/\-_]+(\.([a-zA-Z]+))?$'); - if (regExp.hasMatch(cert)) { + if (Regexps.path.hasMatch(cert)) { return null; } else { diff --git a/lib/screens/settings/logs_settings/config_widgets.dart b/lib/screens/settings/logs_settings/config_widgets.dart index 16700a9..066f779 100644 --- a/lib/screens/settings/logs_settings/config_widgets.dart +++ b/lib/screens/settings/logs_settings/config_widgets.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -55,9 +56,8 @@ class LogsConfigOptions extends StatelessWidget { ]; void validateDomain(String value, String id) { - final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); bool error = false; - if (domainRegex.hasMatch(value)) { + if (Regexps.domain.hasMatch(value)) { error = false; } else { diff --git a/lib/screens/settings/statistics_settings/statistics_settings.dart b/lib/screens/settings/statistics_settings/statistics_settings.dart index 7f58d67..84439b1 100644 --- a/lib/screens/settings/statistics_settings/statistics_settings.dart +++ b/lib/screens/settings/statistics_settings/statistics_settings.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; import 'package:provider/provider.dart'; @@ -91,9 +92,8 @@ class _StatisticsSettingsState extends State { void validateDomain(String value, String id) { - final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); bool error = false; - if (domainRegex.hasMatch(value)) { + if (Regexps.domain.hasMatch(value)) { error = false; } else { diff --git a/lib/widgets/add_server/add_server_functions.dart b/lib/widgets/add_server/add_server_functions.dart index 6dd9c38..bbb88fd 100644 --- a/lib/widgets/add_server/add_server_functions.dart +++ b/lib/widgets/add_server/add_server_functions.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -49,8 +50,7 @@ String? validateSubroute({ required String? value }) { if (value != null && value != '') { - RegExp subrouteRegexp = RegExp(r'^\/\b([A-Za-z0-9_\-~/]*)[^\/|\.|\:]$'); - if (subrouteRegexp.hasMatch(value) == true) { + if (Regexps.subroute.hasMatch(value) == true) { return null; } else { @@ -67,9 +67,7 @@ String? validateAddress({ required String? value }) { if (value != null && value != '') { - RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); - RegExp domain = RegExp(r'^(([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+)$'); - if (ipAddress.hasMatch(value) == true || domain.hasMatch(value) == true) { + if (Regexps.ipv4Address.hasMatch(value) == true || Regexps.domain.hasMatch(value) == true) { return null; } else { From f27b17aad0936099061d7f878ae62b1a07b45839 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 9 Mar 2025 19:58:24 +0100 Subject: [PATCH 664/676] Fix filter logs by added client --- lib/screens/logs/filters/clients_modal.dart | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index ef0e989..05b7213 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -114,10 +114,12 @@ class _ClientsModalState extends State { } void searchAddedClient(_ClientLog client) { - final notIps = client.ids?.where((e) => isIpAddress(e) == false).toList(); - if (notIps == null || notIps.isEmpty) return; - logsProvider.setSearchText('"${notIps[0]}"'); + final ips = client.ids?.where((e) => isIpAddress(e) == true).toList(); + if (ips == null || ips.isEmpty) return; + logsProvider.setSearchText(ips[0]); + logsProvider.filterLogs(); Navigator.of(context).pop(); + Navigator.pop(context); } if (widget.dialog == true) { @@ -302,7 +304,7 @@ class _ClientsModalState extends State { subtitle: _selectedList == 0 ? _filteredClients[index].name : _filteredClients[index].ids?.join(", "), checkboxActive: logsProvider.selectedClients.contains(_filteredClients[index].ip), isAddedClient: _selectedList == 1, - onSearchAddedClient: () => searchAddedClient(_filteredClients[index]), + onSearchAddedClient: _filteredClients[index].ids != null && _filteredClients[index].ids!.where((e) => isIpAddress(e) == true).isNotEmpty ? () => searchAddedClient(_filteredClients[index]) : null, onChanged: (isSelected) { if (isSelected == true) { logsProvider.setSelectedClients([ @@ -376,7 +378,7 @@ class _ListItem extends StatelessWidget { final bool checkboxActive; final void Function(bool) onChanged; final bool isAddedClient; - final void Function() onSearchAddedClient; + final void Function()? onSearchAddedClient; const _ListItem({ required this.title, From e5979edf635448ed91dcf6ad73bcb48704cc1c25 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 9 Mar 2025 20:17:19 +0100 Subject: [PATCH 665/676] Added upstream dns timeout --- lib/l10n/app_en.arb | 5 ++- lib/l10n/app_es.arb | 5 ++- lib/models/dns_info.dart | 4 ++ lib/screens/settings/dns/upstream_dns.dart | 48 ++++++++++++++++++++-- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index fa952aa..f923e8b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -803,5 +803,8 @@ "myOtherApps": "My other apps", "myOtherAppsDescription": "Check my other apps, make a donation, contact support, and more", "topToBottom": "From top to bottom", - "bottomToTop": "From bottom to top" + "bottomToTop": "From bottom to top", + "upstreamTimeout": "Upstream timeout", + "upstreamTimeoutHelper": "Specifies the number of seconds to wait for a response from the upstream server", + "fieldCannotBeEmpty": "This field cannot be empty" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 19a36cf..c93c501 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -803,5 +803,8 @@ "myOtherApps": "Mis otras apps", "myOtherAppsDescription": "Comprueba mis otras apps, hacer una donación, contactar al soporte, y más", "topToBottom": "Desde arriba hacia abajo", - "bottomToTop": "Desde abajo hacia arriba" + "bottomToTop": "Desde abajo hacia arriba", + "upstreamTimeout": "Tiempo de espera del upstream", + "upstreamTimeoutHelper": "Especifica el número de segundos que se debe esperar para recibir una respuesta del servidor upstream", + "fieldCannotBeEmpty": "El campo no puede estar vacío" } \ No newline at end of file diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 5a53023..7007644 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -26,6 +26,7 @@ class DnsInfo { int? ratelimitSubnetLenIpv4; int? ratelimitSubnetLenIpv6; List? ratelimitWhitelist; + int? upstreamTimeout; DnsInfo({ required this.upstreamDns, @@ -55,6 +56,7 @@ class DnsInfo { required this.ratelimitSubnetLenIpv4, required this.ratelimitSubnetLenIpv6, required this.ratelimitWhitelist, + required this.upstreamTimeout, }); factory DnsInfo.fromJson(Map json) => DnsInfo( @@ -85,6 +87,7 @@ class DnsInfo { ratelimitSubnetLenIpv4: json["ratelimit_subnet_len_ipv4"], ratelimitSubnetLenIpv6: json["ratelimit_subnet_len_ipv6"], ratelimitWhitelist: json["ratelimit_whitelist"] != null ? List.from(json["ratelimit_whitelist"].map((x) => x)) : [], + upstreamTimeout: json["upstream_timeout"], ); Map toJson() => { @@ -115,5 +118,6 @@ class DnsInfo { "ratelimit_subnet_len_ipv4": ratelimitSubnetLenIpv4, "ratelimit_subnet_len_ipv6": ratelimitSubnetLenIpv6, "ratelimit_whitelist": ratelimitWhitelist != null ? List.from(ratelimitWhitelist!.map((x) => x)) : null, + "upstream_timeout": upstreamTimeout, }; } diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 33818a1..1ae8c5e 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -1,5 +1,3 @@ -// ignore_for_file: use_build_context_synchronously - import 'dart:io'; import 'package:flutter/material.dart'; @@ -30,6 +28,9 @@ class _UpstreamDnsScreenState extends State { bool validValues = false; + final upstreamTimeoutController = TextEditingController(); + String? upstreamTimeoutError = null; + checkValidValues() { if ( dnsServers.isNotEmpty && @@ -61,6 +62,7 @@ class _UpstreamDnsScreenState extends State { } } upstreamMode = dnsProvider.dnsInfo!.upstreamMode ?? ""; + upstreamTimeoutController.text = dnsProvider.dnsInfo!.upstreamTimeout != null ? dnsProvider.dnsInfo!.upstreamTimeout.toString() : ""; validValues = true; super.initState(); } @@ -72,6 +74,23 @@ class _UpstreamDnsScreenState extends State { final width = MediaQuery.of(context).size.width; + void validateTimeout(String value) { + if (value != '' && int.tryParse(value) != null && int.parse(value) > 0) { + setState(() { + upstreamTimeoutError = null; + validValues = true; + }); + } + else { + setState(() { + upstreamTimeoutError = value == '' + ? AppLocalizations.of(context)!.fieldCannotBeEmpty + : AppLocalizations.of(context)!.invalidValue; + validValues = false; + }); + } + } + void openAddCommentModal() { if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { showDialog( @@ -146,11 +165,13 @@ class _UpstreamDnsScreenState extends State { final result = await dnsProvider.saveUpstreamDnsConfig({ "upstream_dns": dnsServers.map((e) => e['controller'] != null ? e['controller'].text : e['comment']).toList(), - "upstream_mode": upstreamMode + "upstream_mode": upstreamMode, + "upstream_timeout": int.tryParse(upstreamTimeoutController.text) }); processModal.close(); + if (!context.mounted) return; if (result.successful == true) { showSnackbar( appConfigProvider: appConfigProvider, @@ -312,6 +333,27 @@ class _UpstreamDnsScreenState extends State { subtitle: AppLocalizations.of(context)!.fastestIpAddressDescription, onChanged: (value) => setState(() => upstreamMode = value), ), + const SizedBox(height: 16), + SectionLabel(label: AppLocalizations.of(context)!.others), + Padding( + padding: const EdgeInsets.all(16), + child: TextFormField( + controller: upstreamTimeoutController, + onChanged: validateTimeout, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.timer_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + labelText: AppLocalizations.of(context)!.upstreamTimeout, + helperText: AppLocalizations.of(context)!.upstreamTimeoutHelper, + helperMaxLines: 2, + errorText: upstreamTimeoutError + ) + ), + ), ], ), ), From eded494024eae4edc10e6712495af8d4fe3614a5 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 9 Mar 2025 20:28:00 +0100 Subject: [PATCH 666/676] Support TLD greater than 6 characters on domains --- lib/constants/regexps.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/constants/regexps.dart b/lib/constants/regexps.dart index 84ea2bc..c07dee5 100644 --- a/lib/constants/regexps.dart +++ b/lib/constants/regexps.dart @@ -1,6 +1,6 @@ class Regexps { static final wildcardDomain = RegExp(r'^(\*\.)?([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); - static final domain = RegExp(r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$'); + static final domain = RegExp(r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,10}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,10})$'); static final ipv4Address = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); static final ipv6Address = RegExp(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 subroute = RegExp(r'^\/\b([A-Za-z0-9_\-~/]*)[^\/|\.|\:]$'); From 7632d9ef873242be349e0de5a6b8f68bddf27ce2 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 9 Mar 2025 20:36:45 +0100 Subject: [PATCH 667/676] Updated app version --- .gitignore | 2 + ...on => index-2025-03-09T19-31-30-0557.json} | 0 .../arm64-v8a/configure_fingerprint.bin | 26 ++++---- ...on => index-2025-03-09T19-31-30-0871.json} | 0 .../armeabi-v7a/configure_fingerprint.bin | 26 ++++---- ...on => index-2025-03-09T19-31-31-0179.json} | 0 .../4s676p3c/x86/configure_fingerprint.bin | 26 ++++---- ...on => index-2025-03-09T19-31-31-0481.json} | 0 .../4s676p3c/x86_64/configure_fingerprint.bin | 26 ++++---- macos/Podfile.lock | 59 ++++++++++--------- .../xcshareddata/xcschemes/Runner.xcscheme | 1 + macos/Runner/AppDelegate.swift | 4 ++ pubspec.yaml | 2 +- 13 files changed, 90 insertions(+), 82 deletions(-) rename android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/{index-2025-03-09T18-26-01-0152.json => index-2025-03-09T19-31-30-0557.json} (100%) rename android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/{index-2025-03-09T18-26-01-0543.json => index-2025-03-09T19-31-30-0871.json} (100%) rename android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/{index-2025-03-09T18-26-01-0932.json => index-2025-03-09T19-31-31-0179.json} (100%) rename android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/{index-2025-03-09T18-26-02-0299.json => index-2025-03-09T19-31-31-0481.json} (100%) diff --git a/.gitignore b/.gitignore index 6f4a17f..d37570d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # Env diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0152.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0557.json similarity index 100% rename from android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0152.json rename to android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0557.json diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin index 72e381e..6a7dacd 100644 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logu s q/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ßΠá×2  ÏΠá×2r +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  „¹ã×2  ¹ã×2r p -n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json  àΠá×2Ï ÒΠá×2w +n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json  „¹ã×2Ï ‚¹ã×2w u -s/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json  àΠá×2Ú ØÎ á×2d +s/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json  „¹ã×2Ú ƒ¹ã×2d b -`/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja  àΠá×2”Ä »Î á×2h +`/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja  „¹ã×2”Ä ÷¸ã×2h f -d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja.txt  àΠá×2m +d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja.txt  „¹ã×2m k -i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt  àΠá×2 P ØÎ á×2n +i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt  „¹ã×2 P „¹ã×2n l -j/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/compile_commands.json  àΠá×2r +j/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/compile_commands.json  „¹ã×2r p -n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/compile_commands.json.bin  àΠá×2 x +n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/compile_commands.json.bin  „¹ã×2 x v -t/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt  àΠá×2 -¾ ØÎ á×2k +t/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt  „¹ã×2 +¾ „¹ã×2k i -g/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json  àΠá×2  ( ØÎ á×2p +g/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json  „¹ã×2  ( „¹ã×2p n -l/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt  àΠá×2  c ØÎ á×2T +l/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt  „¹ã×2  c „¹ã×2T R -P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  àΠá×2 ¤ Ø„é×Ñ2 \ No newline at end of file +P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  „¹ã×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0543.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0871.json similarity index 100% rename from android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0543.json rename to android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0871.json diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin index 064663e..00da33a 100644 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logw u s/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ÍÑ á×2  ËÑ á×2t +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ¼»ã×2  º»ã×2t r -p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json  ÍÑ á×2Ó ÌÑ á×2y +p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json  ¼»ã×2Ó »»ã×2y w -u/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json  ÍÑ á×2Þ ÌÑ á×2f +u/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json  ¼»ã×2Þ »»ã×2f d -b/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja  ÍÑ á×2 Ä ÁÑ á×2j +b/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja  ¼»ã×2 Ä ±»ã×2j h -f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja.txt  ÍÑ á×2o +f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja.txt  ¼»ã×2o m -k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt  ÍÑ á×2 P ÍÑ á×2p +k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt  ¼»ã×2 P ¼»ã×2p n -l/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/compile_commands.json  ÍÑ á×2t +l/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/compile_commands.json  ¼»ã×2t r -p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/compile_commands.json.bin  ÍÑ á×2 z +p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/compile_commands.json.bin  ¼»ã×2 z x -v/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt  ÍÑ á×2 -È ÍÑ á×2m +v/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt  ¼»ã×2 +È »»ã×2m k -i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json  ÍÑ á×2  ( ÍÑ á×2r +i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json  ¼»ã×2  ( »»ã×2r p -n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt  ÍÑ á×2  e ÍÑ á×2T +n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt  ¼»ã×2  e ¼»ã×2T R -P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  ÍÑ á×2 ¤ Ø„é×Ñ2 \ No newline at end of file +P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  ¼»ã×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0932.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0179.json similarity index 100% rename from android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T18-26-01-0932.json rename to android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0179.json diff --git a/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin index f93955d..aa45397 100644 --- a/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logo m k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ÒÔ á×2  ÐÔ á×2l +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ñ½ã×2  ï½ã×2l j -h/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json  ÒÔ á×2à ÑÔ á×2q +h/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json  ñ½ã×2à ï½ã×2q o -m/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json  ÒÔ á×2Î ÒÔ á×2^ +m/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json  ñ½ã×2Î ð½ã×2^ \ -Z/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build.ninja  ÒÔ á×2ðà ÄÔ á×2b +Z/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build.ninja  ñ½ã×2ðà å½ã×2b ` -^/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build.ninja.txt  ÒÔ á×2g +^/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build.ninja.txt  ñ½ã×2g e -c/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt  ÒÔ á×2 P ÒÔ á×2h +c/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt  ñ½ã×2 P ð½ã×2h f -d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/compile_commands.json  ÒÔ á×2l +d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/compile_commands.json  ñ½ã×2l j -h/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/compile_commands.json.bin  ÒÔ á×2 r +h/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/compile_commands.json.bin  ñ½ã×2 r p -n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt  ÒÔ á×2 -  ÒÔ á×2e +n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt  ñ½ã×2 +  ð½ã×2e c -a/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json  ÒÔ á×2  ( ÒÔ á×2j +a/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json  ñ½ã×2  ( ð½ã×2j h -f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt  ÒÔ á×2  ] ÒÔ á×2T +f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt  ñ½ã×2  ] ð½ã×2T R -P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  ÒÔ á×2 ¤ Ø„é×Ñ2 \ No newline at end of file +P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  ñ½ã×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T18-26-02-0299.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0481.json similarity index 100% rename from android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T18-26-02-0299.json rename to android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0481.json diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/x86_64/configure_fingerprint.bin index 0b39a14..3f4a000 100644 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/4s676p3c/x86_64/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logr p n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  Â× á×2  ¿× á×2o +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ŸÀã×2  Àã×2o m -k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/android_gradle_build.json  Â× á×2É À× á×2t +k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/android_gradle_build.json  ŸÀã×2É žÀã×2t r -p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/android_gradle_build_mini.json  Â× á×2Ô Á× á×2a +p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/android_gradle_build_mini.json  ŸÀã×2Ô ŸÀã×2a _ -]/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/build.ninja  Â× á×2‚Ä µ× á×2e +]/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/build.ninja  ŸÀã×2‚Ä ”Àã×2e c -a/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/build.ninja.txt  Â× á×2j +a/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/build.ninja.txt  ŸÀã×2j h -f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/build_file_index.txt  Â× á×2 P Á× á×2k +f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/build_file_index.txt  ŸÀã×2 P ŸÀã×2k i -g/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/compile_commands.json  Â× á×2o +g/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/compile_commands.json  ŸÀã×2o m -k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/compile_commands.json.bin  Â× á×2 u +k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/compile_commands.json.bin  ŸÀã×2 u s -q/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/metadata_generation_command.txt  Â× á×2 -¯ Á× á×2h +q/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/metadata_generation_command.txt  ŸÀã×2 +¯ ŸÀã×2h f -d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/prefab_config.json  Â× á×2  ( Á× á×2m +d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/prefab_config.json  ŸÀã×2  ( ŸÀã×2m k -i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/symbol_folder_index.txt  Â× á×2  ` Á× á×2T +i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/symbol_folder_index.txt  ŸÀã×2  ` ŸÀã×2T R -P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  Â× á×2 ¤ Ø„é×Ñ2 \ No newline at end of file +P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt   Àã×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/macos/Podfile.lock b/macos/Podfile.lock index e815ee7..ae5c12f 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -6,33 +6,34 @@ PODS: - FlutterMacOS (1.0.0) - package_info_plus (0.0.1): - FlutterMacOS - - screen_retriever (0.0.1): + - screen_retriever_macos (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.36.0) - - sentry_flutter (8.9.0): + - Sentry/HybridSDK (8.44.0) + - sentry_flutter (8.13.2): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.36.0) + - Sentry/HybridSDK (= 8.44.0) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - - sqflite (0.0.3): + - sqflite_darwin (0.0.4): - Flutter - FlutterMacOS - - "sqlite3 (3.46.1+1)": - - "sqlite3/common (= 3.46.1+1)" - - "sqlite3/common (3.46.1+1)" - - "sqlite3/dbstatvtab (3.46.1+1)": + - sqlite3 (3.49.1): + - sqlite3/common (= 3.49.1) + - sqlite3/common (3.49.1) + - sqlite3/dbstatvtab (3.49.1): - sqlite3/common - - "sqlite3/fts5 (3.46.1+1)": + - sqlite3/fts5 (3.49.1): - sqlite3/common - - "sqlite3/perf-threadsafe (3.46.1+1)": + - sqlite3/perf-threadsafe (3.49.1): - sqlite3/common - - "sqlite3/rtree (3.46.1+1)": + - sqlite3/rtree (3.49.1): - sqlite3/common - sqlite3_flutter_libs (0.0.1): + - Flutter - FlutterMacOS - - "sqlite3 (~> 3.46.0+1)" + - sqlite3 (~> 3.49.1) - sqlite3/dbstatvtab - sqlite3/fts5 - sqlite3/perf-threadsafe @@ -47,11 +48,11 @@ DEPENDENCIES: - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) + - screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`) - sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) - - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) + - sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`) + - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) @@ -69,33 +70,33 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral package_info_plus: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos - screen_retriever: - :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos + screen_retriever_macos: + :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos sentry_flutter: :path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos shared_preferences_foundation: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin - sqflite: - :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin + sqflite_darwin: + :path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin sqlite3_flutter_libs: - :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos + :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos window_manager: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: - device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720 + device_info_plus: 1b14eed9bf95428983aed283a8d51cce3d8c4215 dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c - screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 - Sentry: f8374b5415bc38dfb5645941b3ae31230fbeae57 - sentry_flutter: 0eb93e5279eb41e2392212afe1ccd2fecb4f8cbe + package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b + screen_retriever_macos: 776e0fa5d42c6163d2bf772d22478df4b302b161 + Sentry: 0f9bc9adfc0b960e7f3bb5ec67e9a3d8193f3bdb + sentry_flutter: 64a43fb39ab4c7f67d8a4cad52b49e22439e58b7 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec - sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb - sqlite3_flutter_libs: 5ca46c1a04eddfbeeb5b16566164aa7ad1616e7b + sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d + sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983 + sqlite3_flutter_libs: cc304edcb8e1d8c595d1b08c7aeb46a47691d9db url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 6982a10..dcd4e29 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -48,6 +48,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift index 8e02df2..b3c1761 100644 --- a/macos/Runner/AppDelegate.swift +++ b/macos/Runner/AppDelegate.swift @@ -6,4 +6,8 @@ class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/pubspec.yaml b/pubspec.yaml index 4222db1..a9dc55c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.20.1+148 +version: 2.20.2+149 environment: sdk: '>=2.18.1 <3.0.0' From e7aacfbec170b83ebb57c82056c833470ca19ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9D=97=9B=F0=9D=97=BC=F0=9D=97=B9=F0=9D=97=B6?= <75412448+mikropsoft@users.noreply.github.com> Date: Sun, 9 Mar 2025 23:04:45 +0300 Subject: [PATCH 668/676] Update app_tr.arb --- lib/l10n/app_tr.arb | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 423dfa3..7561f74 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -791,5 +791,20 @@ "clientDisallowedSuccessfully": "İstemci baÅŸarıyla reddedildi", "changesNotSaved": "DeÄŸiÅŸiklikler kaydedilemedi", "allowingClient": "İstemciye izin veriliyor...", - "disallowingClient": "İstemci reddediliyor..." -} \ No newline at end of file + "disallowingClient": "İstemci reddediliyor...", + "clientIpCopied": "İstemci IP'si panoya kopyalandı", + "clientNameCopied": "İstemci adı panoya kopyalandı", + "dnsServerAddressCopied": "DNS sunucu adresi panoya kopyalandı", + "select": "Seç", + "liveLogs": "Canlı günlükler", + "hereWillAppearRealtimeLogs": "Burada gerçek zamanlı günlükler görünecek.", + "applicationDetails": "Uygulama detayları", + "applicationDetailsDescription": "Uygulama deposu, mevcut olduÄŸu maÄŸazalar ve daha fazlası", + "myOtherApps": "DiÄŸer uygulamalarım", + "myOtherAppsDescription": "DiÄŸer uygulamalarımı kontrol et, bağış yap, destekle iletiÅŸime geç ve daha fazlası", + "topToBottom": "Yukarıdan aÅŸağıya", + "bottomToTop": "AÅŸağıdan yukarıya", + "upstreamTimeout": "Yukarı akış zaman aşımı", + "upstreamTimeoutHelper": "Yukarı akış sunucusundan yanıt bekleme süresini saniye cinsinden belirtir", + "fieldCannotBeEmpty": "Bu alan boÅŸ olamaz" +} From 88339d1c40245bc6c1e713ce323cb89ab1d7bf78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9D=97=9B=F0=9D=97=BC=F0=9D=97=B9=F0=9D=97=B6?= <75412448+mikropsoft@users.noreply.github.com> Date: Sun, 9 Mar 2025 23:07:05 +0300 Subject: [PATCH 670/676] Update app_tr.arb --- lib/l10n/app_tr.arb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 7561f74..d0f26c5 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -804,7 +804,7 @@ "myOtherAppsDescription": "DiÄŸer uygulamalarımı kontrol et, bağış yap, destekle iletiÅŸime geç ve daha fazlası", "topToBottom": "Yukarıdan aÅŸağıya", "bottomToTop": "AÅŸağıdan yukarıya", - "upstreamTimeout": "Yukarı akış zaman aşımı", - "upstreamTimeoutHelper": "Yukarı akış sunucusundan yanıt bekleme süresini saniye cinsinden belirtir", + "upstreamTimeout": "Üst sunucu zaman aşımı", + "upstreamTimeoutHelper": "Üst DNS sunucusundan yanıt bekleme süresini saniye cinsinden belirtir", "fieldCannotBeEmpty": "Bu alan boÅŸ olamaz" } From ae9d23d4a888e704f5b5ed6d435032830b04c7f9 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Mon, 17 Mar 2025 19:10:06 +0100 Subject: [PATCH 671/676] Support multiple subdomains --- .gitignore | 4 +- .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-d7ea1a46fca8a951bac1.json | 1391 ----------------- .../cmakeFiles-v1-25067417d59f0d26c931.json | 799 ---------- .../codemodel-v2-aa70310decf347f6cbdc.json | 43 - ...irectory-.-Debug-f5ebdc15457944623624.json | 14 - .../reply/index-2025-03-09T19-31-30-0557.json | 92 -- .../Debug/4s676p3c/arm64-v8a/CMakeCache.txt | 405 ----- .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 - .../3.22.1-g37088a8/CMakeCXXCompiler.cmake | 83 - .../CMakeDetermineCompilerABI_C.bin | Bin 7992 -> 0 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 8136 -> 0 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 - .../CompilerIdC/CMakeCCompilerId.c | 803 ---------- .../CompilerIdC/CMakeCCompilerId.o | Bin 6048 -> 0 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 791 ---------- .../CompilerIdCXX/CMakeCXXCompilerId.o | Bin 6064 -> 0 bytes .../CMakeFiles/TargetDirectories.txt | 2 - .../arm64-v8a/CMakeFiles/cmake.check_cache | 1 - .../4s676p3c/arm64-v8a/CMakeFiles/rules.ninja | 45 - .../arm64-v8a/additional_project_files.txt | 0 .../arm64-v8a/android_gradle_build.json | 28 - .../arm64-v8a/android_gradle_build_mini.json | 20 - .../.cxx/Debug/4s676p3c/arm64-v8a/build.ninja | 112 -- .../4s676p3c/arm64-v8a/build_file_index.txt | 1 - .../4s676p3c/arm64-v8a/cmake_install.cmake | 54 - .../arm64-v8a/configure_fingerprint.bin | 28 - .../arm64-v8a/metadata_generation_command.txt | 20 - .../4s676p3c/arm64-v8a/prefab_config.json | 4 - .../arm64-v8a/symbol_folder_index.txt | 1 - .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-6573c0656e67becaeff1.json | 1391 ----------------- .../cmakeFiles-v1-161e4284e257b7dbcee8.json | 799 ---------- .../codemodel-v2-769fcb1eb528b5a1f77c.json | 43 - ...irectory-.-Debug-f5ebdc15457944623624.json | 14 - .../reply/index-2025-03-09T19-31-30-0871.json | 92 -- .../Debug/4s676p3c/armeabi-v7a/CMakeCache.txt | 405 ----- .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 - .../3.22.1-g37088a8/CMakeCXXCompiler.cmake | 83 - .../CMakeDetermineCompilerABI_C.bin | Bin 5896 -> 0 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 6036 -> 0 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 - .../CompilerIdC/CMakeCCompilerId.c | 803 ---------- .../CompilerIdC/CMakeCCompilerId.o | Bin 4148 -> 0 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 791 ---------- .../CompilerIdCXX/CMakeCXXCompilerId.o | Bin 4184 -> 0 bytes .../CMakeFiles/TargetDirectories.txt | 2 - .../armeabi-v7a/CMakeFiles/cmake.check_cache | 1 - .../armeabi-v7a/CMakeFiles/rules.ninja | 45 - .../armeabi-v7a/additional_project_files.txt | 0 .../armeabi-v7a/android_gradle_build.json | 28 - .../android_gradle_build_mini.json | 20 - .../Debug/4s676p3c/armeabi-v7a/build.ninja | 112 -- .../4s676p3c/armeabi-v7a/build_file_index.txt | 1 - .../4s676p3c/armeabi-v7a/cmake_install.cmake | 54 - .../armeabi-v7a/configure_fingerprint.bin | 28 - .../metadata_generation_command.txt | 20 - .../4s676p3c/armeabi-v7a/prefab_config.json | 4 - .../armeabi-v7a/symbol_folder_index.txt | 1 - android/app/.cxx/Debug/4s676p3c/hash_key.txt | 27 - .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-920dacdb871097de2130.json | 1391 ----------------- .../cmakeFiles-v1-f1661dab2653e3c04b8e.json | 799 ---------- .../codemodel-v2-95b6204aa3712c2f8293.json | 43 - ...irectory-.-Debug-f5ebdc15457944623624.json | 14 - .../reply/index-2025-03-09T19-31-31-0179.json | 92 -- .../.cxx/Debug/4s676p3c/x86/CMakeCache.txt | 405 ----- .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 - .../3.22.1-g37088a8/CMakeCXXCompiler.cmake | 83 - .../CMakeDetermineCompilerABI_C.bin | Bin 5828 -> 0 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 5984 -> 0 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 - .../CompilerIdC/CMakeCCompilerId.c | 803 ---------- .../CompilerIdC/CMakeCCompilerId.o | Bin 3924 -> 0 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 791 ---------- .../CompilerIdCXX/CMakeCXXCompilerId.o | Bin 3960 -> 0 bytes .../x86/CMakeFiles/TargetDirectories.txt | 2 - .../4s676p3c/x86/CMakeFiles/cmake.check_cache | 1 - .../Debug/4s676p3c/x86/CMakeFiles/rules.ninja | 45 - .../4s676p3c/x86/additional_project_files.txt | 0 .../4s676p3c/x86/android_gradle_build.json | 28 - .../x86/android_gradle_build_mini.json | 20 - .../app/.cxx/Debug/4s676p3c/x86/build.ninja | 112 -- .../Debug/4s676p3c/x86/build_file_index.txt | 1 - .../Debug/4s676p3c/x86/cmake_install.cmake | 54 - .../4s676p3c/x86/configure_fingerprint.bin | 28 - .../x86/metadata_generation_command.txt | 20 - .../Debug/4s676p3c/x86/prefab_config.json | 4 - .../4s676p3c/x86/symbol_folder_index.txt | 1 - .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-2b5d080db4293a9c0f40.json | 1391 ----------------- .../cmakeFiles-v1-9a2bf79ff0a2a89eb505.json | 799 ---------- .../codemodel-v2-852402f1316f6f65a056.json | 43 - ...irectory-.-Debug-f5ebdc15457944623624.json | 14 - .../reply/index-2025-03-09T19-31-31-0481.json | 92 -- .../.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt | 405 ----- .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 - .../3.22.1-g37088a8/CMakeCXXCompiler.cmake | 83 - .../CMakeDetermineCompilerABI_C.bin | Bin 7008 -> 0 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 7176 -> 0 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 - .../CompilerIdC/CMakeCCompilerId.c | 803 ---------- .../CompilerIdC/CMakeCCompilerId.o | Bin 5424 -> 0 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 791 ---------- .../CompilerIdCXX/CMakeCXXCompilerId.o | Bin 5480 -> 0 bytes .../x86_64/CMakeFiles/TargetDirectories.txt | 2 - .../x86_64/CMakeFiles/cmake.check_cache | 1 - .../4s676p3c/x86_64/CMakeFiles/rules.ninja | 45 - .../x86_64/additional_project_files.txt | 0 .../4s676p3c/x86_64/android_gradle_build.json | 28 - .../x86_64/android_gradle_build_mini.json | 20 - .../.cxx/Debug/4s676p3c/x86_64/build.ninja | 112 -- .../4s676p3c/x86_64/build_file_index.txt | 1 - .../Debug/4s676p3c/x86_64/cmake_install.cmake | 54 - .../4s676p3c/x86_64/configure_fingerprint.bin | 28 - .../x86_64/metadata_generation_command.txt | 20 - .../Debug/4s676p3c/x86_64/prefab_config.json | 4 - .../4s676p3c/x86_64/symbol_folder_index.txt | 1 - lib/constants/regexps.dart | 4 +- pubspec.lock | 32 +- 128 files changed, 21 insertions(+), 19342 deletions(-) delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cache-v2-d7ea1a46fca8a951bac1.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-25067417d59f0d26c931.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-aa70310decf347f6cbdc.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0557.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeCache.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake delete mode 100755 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin delete mode 100755 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/TargetDirectories.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/cmake.check_cache delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rules.ninja delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/additional_project_files.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/cmake_install.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cache-v2 delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/codemodel-v2 delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cache-v2-6573c0656e67becaeff1.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-161e4284e257b7dbcee8.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-769fcb1eb528b5a1f77c.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0871.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeCache.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake delete mode 100755 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin delete mode 100755 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/TargetDirectories.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/cmake.check_cache delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rules.ninja delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/additional_project_files.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/cmake_install.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/hash_key.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cache-v2 delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cmakeFiles-v1 delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/codemodel-v2 delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cache-v2-920dacdb871097de2130.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cmakeFiles-v1-f1661dab2653e3c04b8e.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/codemodel-v2-95b6204aa3712c2f8293.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0179.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeCache.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake delete mode 100755 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin delete mode 100755 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/TargetDirectories.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/cmake.check_cache delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rules.ninja delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/additional_project_files.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/build.ninja delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/cmake_install.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cache-v2 delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cmakeFiles-v1 delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/codemodel-v2 delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cache-v2-2b5d080db4293a9c0f40.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-9a2bf79ff0a2a89eb505.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/codemodel-v2-852402f1316f6f65a056.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0481.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake delete mode 100755 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin delete mode 100755 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/TargetDirectories.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/cmake.check_cache delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/rules.ninja delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/additional_project_files.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/android_gradle_build.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/android_gradle_build_mini.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/build.ninja delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/build_file_index.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/cmake_install.cmake delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/configure_fingerprint.bin delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/metadata_generation_command.txt delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/prefab_config.json delete mode 100644 android/app/.cxx/Debug/4s676p3c/x86_64/symbol_folder_index.txt diff --git a/.gitignore b/.gitignore index d37570d..e9d1504 100644 --- a/.gitignore +++ b/.gitignore @@ -50,4 +50,6 @@ app.*.map.json /debian/packages -untranslated.json \ No newline at end of file +untranslated.json + +android/app/.cxx diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cache-v2-d7ea1a46fca8a951bac1.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cache-v2-d7ea1a46fca8a951bac1.json deleted file mode 100644 index 50ecf16..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cache-v2-d7ea1a46fca8a951bac1.json +++ /dev/null @@ -1,1391 +0,0 @@ -{ - "entries" : - [ - { - "name" : "ANDROID_ABI", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "arm64-v8a" - }, - { - "name" : "ANDROID_NDK", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" - }, - { - "name" : "ANDROID_PLATFORM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "android-26" - }, - { - "name" : "CMAKE_ADDR2LINE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line" - }, - { - "name" : "CMAKE_ANDROID_ARCH_ABI", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "arm64-v8a" - }, - { - "name" : "CMAKE_ANDROID_NDK", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" - }, - { - "name" : "CMAKE_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_ASM_FLAGS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_ASM_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_ASM_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_BUILD_TYPE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." - } - ], - "type" : "STRING", - "value" : "Debug" - }, - { - "name" : "CMAKE_CACHEFILE_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "This is the directory where this CMakeCache.txt was created" - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a" - }, - { - "name" : "CMAKE_CACHE_MAJOR_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Major version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "3" - }, - { - "name" : "CMAKE_CACHE_MINOR_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Minor version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "22" - }, - { - "name" : "CMAKE_CACHE_PATCH_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Patch version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to CMake executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake" - }, - { - "name" : "CMAKE_CPACK_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to cpack program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack" - }, - { - "name" : "CMAKE_CTEST_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to ctest program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest" - }, - { - "name" : "CMAKE_CXX_COMPILER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "(This variable does not exist and should not be used)" - } - ], - "type" : "UNINITIALIZED", - "value" : "" - }, - { - "name" : "CMAKE_CXX_COMPILER_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "LLVM archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_CXX_COMPILER_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Generate index for LLVM archive" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_CXX_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the CXX compiler during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "-Os -DNDEBUG" - }, - { - "name" : "CMAKE_CXX_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "-O2 -g -DNDEBUG" - }, - { - "name" : "CMAKE_CXX_STANDARD_LIBRARIES", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Libraries linked by default with all C++ applications." - } - ], - "type" : "STRING", - "value" : "-latomic -lm" - }, - { - "name" : "CMAKE_C_COMPILER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "(This variable does not exist and should not be used)" - } - ], - "type" : "UNINITIALIZED", - "value" : "" - }, - { - "name" : "CMAKE_C_COMPILER_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "LLVM archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_C_COMPILER_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Generate index for LLVM archive" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_C_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the C compiler during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "-Os -DNDEBUG" - }, - { - "name" : "CMAKE_C_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "-O2 -g -DNDEBUG" - }, - { - "name" : "CMAKE_C_STANDARD_LIBRARIES", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Libraries linked by default with all C applications." - } - ], - "type" : "STRING", - "value" : "-latomic -lm" - }, - { - "name" : "CMAKE_DLLTOOL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "CMAKE_DLLTOOL-NOTFOUND" - }, - { - "name" : "CMAKE_EDIT_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to cache edit program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake" - }, - { - "name" : "CMAKE_ERROR_DEPRECATED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Whether to issue deprecation errors for macros and functions." - } - ], - "type" : "INTERNAL", - "value" : "FALSE" - }, - { - "name" : "CMAKE_EXECUTABLE_FORMAT", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Executable file format" - } - ], - "type" : "INTERNAL", - "value" : "ELF" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "ON" - }, - { - "name" : "CMAKE_EXTRA_GENERATOR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of external makefile project generator." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator." - } - ], - "type" : "INTERNAL", - "value" : "Ninja" - }, - { - "name" : "CMAKE_GENERATOR_INSTANCE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Generator instance identifier." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR_PLATFORM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator platform." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR_TOOLSET", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator toolset." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_HOME_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Source directory with the top level CMakeLists.txt file for this project" - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - { - "name" : "CMAKE_INSTALL_PREFIX", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Install path prefix, prepended onto install directories." - } - ], - "type" : "PATH", - "value" : "/usr/local" - }, - { - "name" : "CMAKE_INSTALL_SO_NO_EXE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Install .so files without execute permission." - } - ], - "type" : "INTERNAL", - "value" : "0" - }, - { - "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a" - }, - { - "name" : "CMAKE_LINKER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" - }, - { - "name" : "CMAKE_MAKE_PROGRAM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_NM", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm" - }, - { - "name" : "CMAKE_NUMBER_OF_MAKEFILES", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "number of local generators" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_OBJCOPY", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy" - }, - { - "name" : "CMAKE_OBJDUMP", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump" - }, - { - "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Platform information initialized" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_PROJECT_DESCRIPTION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "" - }, - { - "name" : "CMAKE_PROJECT_HOMEPAGE_URL", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "" - }, - { - "name" : "CMAKE_PROJECT_NAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "Project" - }, - { - "name" : "CMAKE_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Ranlib" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_READELF", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf" - }, - { - "name" : "CMAKE_ROOT", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to CMake installation." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" - }, - { - "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of dll's." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SKIP_INSTALL_RPATH", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." - } - ], - "type" : "BOOL", - "value" : "NO" - }, - { - "name" : "CMAKE_SKIP_RPATH", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If set, runtime paths are not added when using shared libraries." - } - ], - "type" : "BOOL", - "value" : "NO" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STRIP", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Strip" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip" - }, - { - "name" : "CMAKE_SUPPRESS_DEVELOPER_ERRORS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Suppress errors that are meant for the author of the CMakeLists.txt files." - } - ], - "type" : "INTERNAL", - "value" : "TRUE" - }, - { - "name" : "CMAKE_SUPPRESS_DEVELOPER_WARNINGS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Suppress Warnings that are meant for the author of the CMakeLists.txt files." - } - ], - "type" : "INTERNAL", - "value" : "TRUE" - }, - { - "name" : "CMAKE_SYSTEM_NAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "Android" - }, - { - "name" : "CMAKE_SYSTEM_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "26" - }, - { - "name" : "CMAKE_TOOLCHAIN_FILE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "The CMake toolchain file" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "name" : "CMAKE_UNAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "uname command" - } - ], - "type" : "INTERNAL", - "value" : "/usr/bin/uname" - }, - { - "name" : "CMAKE_VERBOSE_MAKEFILE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." - } - ], - "type" : "BOOL", - "value" : "FALSE" - }, - { - "name" : "CMAKE_WARN_DEPRECATED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Whether to issue warnings for deprecated functionality." - } - ], - "type" : "INTERNAL", - "value" : "FALSE" - }, - { - "name" : "Project_BINARY_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a" - }, - { - "name" : "Project_IS_TOP_LEVEL", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "ON" - }, - { - "name" : "Project_SOURCE_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - } - ], - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-25067417d59f0d26c931.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-25067417d59f0d26c931.json deleted file mode 100644 index 5a3733f..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-25067417d59f0d26c931.json +++ /dev/null @@ -1,799 +0,0 @@ -{ - "inputs" : - [ - { - "path" : "CMakeLists.txt" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" - } - ], - "kind" : "cmakeFiles", - "paths" : - { - "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", - "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - "version" : - { - "major" : 1, - "minor" : 0 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-aa70310decf347f6cbdc.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-aa70310decf347f6cbdc.json deleted file mode 100644 index 421c157..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-aa70310decf347f6cbdc.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "configurations" : - [ - { - "directories" : - [ - { - "build" : ".", - "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", - "minimumCMakeVersion" : - { - "string" : "3.6.0" - }, - "projectIndex" : 0, - "source" : "." - } - ], - "name" : "Debug", - "projects" : - [ - { - "directoryIndexes" : - [ - 0 - ], - "name" : "Project" - } - ], - "targets" : [] - } - ], - "kind" : "codemodel", - "paths" : - { - "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", - "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - "version" : - { - "major" : 2, - "minor" : 3 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json deleted file mode 100644 index 3a67af9..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "backtraceGraph" : - { - "commands" : [], - "files" : [], - "nodes" : [] - }, - "installers" : [], - "paths" : - { - "build" : ".", - "source" : "." - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0557.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0557.json deleted file mode 100644 index 7f77f77..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0557.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "cmake" : - { - "generator" : - { - "multiConfig" : false, - "name" : "Ninja" - }, - "paths" : - { - "cmake" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake", - "cpack" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack", - "ctest" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest", - "root" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" - }, - "version" : - { - "isDirty" : false, - "major" : 3, - "minor" : 22, - "patch" : 1, - "string" : "3.22.1-g37088a8", - "suffix" : "g37088a8" - } - }, - "objects" : - [ - { - "jsonFile" : "codemodel-v2-aa70310decf347f6cbdc.json", - "kind" : "codemodel", - "version" : - { - "major" : 2, - "minor" : 3 - } - }, - { - "jsonFile" : "cache-v2-d7ea1a46fca8a951bac1.json", - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } - }, - { - "jsonFile" : "cmakeFiles-v1-25067417d59f0d26c931.json", - "kind" : "cmakeFiles", - "version" : - { - "major" : 1, - "minor" : 0 - } - } - ], - "reply" : - { - "client-agp" : - { - "cache-v2" : - { - "jsonFile" : "cache-v2-d7ea1a46fca8a951bac1.json", - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } - }, - "cmakeFiles-v1" : - { - "jsonFile" : "cmakeFiles-v1-25067417d59f0d26c931.json", - "kind" : "cmakeFiles", - "version" : - { - "major" : 1, - "minor" : 0 - } - }, - "codemodel-v2" : - { - "jsonFile" : "codemodel-v2-aa70310decf347f6cbdc.json", - "kind" : "codemodel", - "version" : - { - "major" : 2, - "minor" : 3 - } - } - } - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeCache.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeCache.txt deleted file mode 100644 index 5701b44..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeCache.txt +++ /dev/null @@ -1,405 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a -# It was generated by CMake: /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//No help, variable specified on the command line. -ANDROID_ABI:UNINITIALIZED=arm64-v8a - -//No help, variable specified on the command line. -ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 - -//No help, variable specified on the command line. -ANDROID_PLATFORM:UNINITIALIZED=android-26 - -//Path to a program. -CMAKE_ADDR2LINE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line - -//No help, variable specified on the command line. -CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=arm64-v8a - -//No help, variable specified on the command line. -CMAKE_ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 - -//Archiver -CMAKE_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Flags used by the compiler during all build types. -CMAKE_ASM_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_ASM_FLAGS_DEBUG:STRING= - -//Flags used by the compiler during release builds. -CMAKE_ASM_FLAGS_RELEASE:STRING= - -//Choose the type of build, options are: None Debug Release RelWithDebInfo -// MinSizeRel ... -CMAKE_BUILD_TYPE:STRING=Debug - -//LLVM archiver -CMAKE_CXX_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Generate index for LLVM archive -CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING= - -//Flags used by the CXX compiler during MINSIZEREL builds. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_CXX_FLAGS_RELEASE:STRING= - -//Flags used by the CXX compiler during RELWITHDEBINFO builds. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Libraries linked by default with all C++ applications. -CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm - -//LLVM archiver -CMAKE_C_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Generate index for LLVM archive -CMAKE_C_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING= - -//Flags used by the C compiler during MINSIZEREL builds. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_C_FLAGS_RELEASE:STRING= - -//Flags used by the C compiler during RELWITHDEBINFO builds. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Libraries linked by default with all C applications. -CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm - -//Path to a program. -CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING= - -//Flags used by the linker during DEBUG builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during MINSIZEREL builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during RELEASE builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during RELWITHDEBINFO builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//No help, variable specified on the command line. -CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//No help, variable specified on the command line. -CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a - -//Path to a program. -CMAKE_LINKER:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld - -//No help, variable specified on the command line. -CMAKE_MAKE_PROGRAM:UNINITIALIZED=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of modules during -// DEBUG builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of modules during -// MINSIZEREL builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of modules during -// RELEASE builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of modules during -// RELWITHDEBINFO builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump - -//Value Computed by CMake -CMAKE_PROJECT_DESCRIPTION:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_HOMEPAGE_URL:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=Project - -//Ranlib -CMAKE_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Path to a program. -CMAKE_READELF:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf - -//No help, variable specified on the command line. -CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of shared libraries -// during DEBUG builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of shared libraries -// during MINSIZEREL builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELEASE builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELWITHDEBINFO builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries -// during all build types. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of static libraries -// during DEBUG builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of static libraries -// during MINSIZEREL builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELEASE builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELWITHDEBINFO builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Strip -CMAKE_STRIP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip - -//No help, variable specified on the command line. -CMAKE_SYSTEM_NAME:UNINITIALIZED=Android - -//No help, variable specified on the command line. -CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 - -//The CMake toolchain file -CMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//Value Computed by CMake -Project_BINARY_DIR:STATIC=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a - -//Value Computed by CMake -Project_IS_TOP_LEVEL:STATIC=ON - -//Value Computed by CMake -Project_SOURCE_DIR:STATIC=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: CMAKE_ADDR2LINE -CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest -//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR -CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB -CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES -CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_AR -CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB -CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES -CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_DLLTOOL -CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 -//Path to cache edit program executable. -CMAKE_EDIT_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -//Whether to issue deprecation errors for macros and functions. -CMAKE_ERROR_DEPRECATED:INTERNAL=FALSE -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Ninja -//Generator instance identifier. -CMAKE_GENERATOR_INSTANCE:INTERNAL= -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -//Install .so files without execute permission. -CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_READELF -CMAKE_READELF-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//Suppress errors that are meant for the author of the CMakeLists.txt -// files. -CMAKE_SUPPRESS_DEVELOPER_ERRORS:INTERNAL=TRUE -//Suppress Warnings that are meant for the author of the CMakeLists.txt -// files. -CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=TRUE -//uname command -CMAKE_UNAME:INTERNAL=/usr/bin/uname -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Whether to issue warnings for deprecated functionality. -CMAKE_WARN_DEPRECATED:INTERNAL=FALSE - diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake deleted file mode 100644 index 1fc1c84..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake +++ /dev/null @@ -1,72 +0,0 @@ -set(CMAKE_C_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang") -set(CMAKE_C_COMPILER_ARG1 "") -set(CMAKE_C_COMPILER_ID "Clang") -set(CMAKE_C_COMPILER_VERSION "17.0.2") -set(CMAKE_C_COMPILER_VERSION_INTERNAL "") -set(CMAKE_C_COMPILER_WRAPPER "") -set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") -set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") -set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") -set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") -set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") -set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") -set(CMAKE_C17_COMPILE_FEATURES "c_std_17") -set(CMAKE_C23_COMPILE_FEATURES "c_std_23") - -set(CMAKE_C_PLATFORM_ID "Linux") -set(CMAKE_C_SIMULATE_ID "") -set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") -set(CMAKE_C_SIMULATE_VERSION "") - - - - -set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_C_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_C_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") -set(CMAKE_MT "") -set(CMAKE_COMPILER_IS_GNUCC ) -set(CMAKE_C_COMPILER_LOADED 1) -set(CMAKE_C_COMPILER_WORKS TRUE) -set(CMAKE_C_ABI_COMPILED TRUE) - -set(CMAKE_C_COMPILER_ENV_VAR "CC") - -set(CMAKE_C_COMPILER_ID_RUN 1) -set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) -set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) -set(CMAKE_C_LINKER_PREFERENCE 10) - -# Save compiler ABI information. -set(CMAKE_C_SIZEOF_DATA_PTR "8") -set(CMAKE_C_COMPILER_ABI "ELF") -set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") -set(CMAKE_C_LIBRARY_ARCHITECTURE "") - -if(CMAKE_C_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_C_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") -endif() - -if(CMAKE_C_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - -set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") -if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) - set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") -endif() - - - - - -set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") -set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") -set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/aarch64;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") -set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake deleted file mode 100644 index 8d1017c..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake +++ /dev/null @@ -1,83 +0,0 @@ -set(CMAKE_CXX_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++") -set(CMAKE_CXX_COMPILER_ARG1 "") -set(CMAKE_CXX_COMPILER_ID "Clang") -set(CMAKE_CXX_COMPILER_VERSION "17.0.2") -set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") -set(CMAKE_CXX_COMPILER_WRAPPER "") -set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") -set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") -set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") -set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") -set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") -set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") -set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") -set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") -set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") - -set(CMAKE_CXX_PLATFORM_ID "Linux") -set(CMAKE_CXX_SIMULATE_ID "") -set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") -set(CMAKE_CXX_SIMULATE_VERSION "") - - - - -set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_CXX_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_CXX_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") -set(CMAKE_MT "") -set(CMAKE_COMPILER_IS_GNUCXX ) -set(CMAKE_CXX_COMPILER_LOADED 1) -set(CMAKE_CXX_COMPILER_WORKS TRUE) -set(CMAKE_CXX_ABI_COMPILED TRUE) - -set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") - -set(CMAKE_CXX_COMPILER_ID_RUN 1) -set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) -set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) - -foreach (lang C OBJC OBJCXX) - if (CMAKE_${lang}_COMPILER_ID_RUN) - foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) - list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) - endforeach() - endif() -endforeach() - -set(CMAKE_CXX_LINKER_PREFERENCE 30) -set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) - -# Save compiler ABI information. -set(CMAKE_CXX_SIZEOF_DATA_PTR "8") -set(CMAKE_CXX_COMPILER_ABI "ELF") -set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") -set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") - -if(CMAKE_CXX_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_CXX_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") -endif() - -if(CMAKE_CXX_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - -set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") -if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) - set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") -endif() - - - - - -set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") -set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl") -set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/aarch64;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") -set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin deleted file mode 100755 index ecf7dc0ff0f4d29d1711e9eb64606718d80eaa08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7992 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 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin deleted file mode 100755 index b47dc244f44818d5bcfd2bcd35740eef4d9b6946..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8136 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 xElPw})rO<*o!b$4{Q3O34f;HHB+uamlAT diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake deleted file mode 100644 index 43edff4..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake +++ /dev/null @@ -1,15 +0,0 @@ -set(CMAKE_HOST_SYSTEM "Darwin-24.3.0") -set(CMAKE_HOST_SYSTEM_NAME "Darwin") -set(CMAKE_HOST_SYSTEM_VERSION "24.3.0") -set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64") - -include("/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake") - -set(CMAKE_SYSTEM "Android-1") -set(CMAKE_SYSTEM_NAME "Android") -set(CMAKE_SYSTEM_VERSION "1") -set(CMAKE_SYSTEM_PROCESSOR "aarch64") - -set(CMAKE_CROSSCOMPILING "TRUE") - -set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c deleted file mode 100644 index 41b99d7..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c +++ /dev/null @@ -1,803 +0,0 @@ -#ifdef __cplusplus -# error "A C++ compiler has been selected for C." -#endif - -#if defined(__18CXX) -# define ID_VOID_MAIN -#endif -#if defined(__CLASSIC_C__) -/* cv-qualifiers did not exist in K&R C */ -# define const -# define volatile -#endif - -#if !defined(__has_include) -/* If the compiler does not have __has_include, pretend the answer is - always no. */ -# define __has_include(x) 0 -#endif - - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# if defined(__GNUC__) -# define SIMULATE_ID "GNU" -# endif - /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, - except that a few beta releases use the old format with V=2021. */ -# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# if defined(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# else -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# endif -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) - /* The third version component from --version is an update index, - but no macro is provided for it. */ -# define COMPILER_VERSION_PATCH DEC(0) -# endif -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -# elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) -# define COMPILER_ID "IntelLLVM" -#if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -#endif -#if defined(__GNUC__) -# define SIMULATE_ID "GNU" -#endif -/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and - * later. Look for 6 digit vs. 8 digit version number to decide encoding. - * VVVV is no smaller than the current year when a version is released. - */ -#if __INTEL_LLVM_COMPILER < 1000000L -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) -#else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) -#endif -#if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -#endif -#if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -#elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -#endif -#if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -#endif -#if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -#endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__WATCOMC__) -# define COMPILER_ID "OpenWatcom" - /* __WATCOMC__ = VVRP + 1100 */ -# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__SUNPRO_C) -# define COMPILER_ID "SunPro" -# if __SUNPRO_C >= 0x5100 - /* __SUNPRO_C = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# endif - -#elif defined(__HP_cc) -# define COMPILER_ID "HP" - /* __HP_cc = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) - -#elif defined(__DECC) -# define COMPILER_ID "Compaq" - /* __DECC_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) - -#elif defined(__IBMC__) && defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__ibmxl__) && defined(__clang__) -# define COMPILER_ID "XLClang" -# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) -# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) -# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) - - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 -# define COMPILER_ID "XL" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 -# define COMPILER_ID "VisualAge" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__NVCOMPILER) -# define COMPILER_ID "NVHPC" -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__CLANG_FUJITSU) -# define COMPILER_ID "FujitsuClang" -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# define COMPILER_VERSION_INTERNAL_STR __clang_version__ - - -#elif defined(__FUJITSU) -# define COMPILER_ID "Fujitsu" -# if defined(__FCC_version__) -# define COMPILER_VERSION __FCC_version__ -# elif defined(__FCC_major__) -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# endif -# if defined(__fcc_version) -# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) -# elif defined(__FCC_VERSION) -# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) -# endif - - -#elif defined(__ghs__) -# define COMPILER_ID "GHS" -/* __GHS_VERSION_NUMBER = VVVVRP */ -# ifdef __GHS_VERSION_NUMBER -# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) -# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) -# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) -# endif - -#elif defined(__TINYC__) -# define COMPILER_ID "TinyCC" - -#elif defined(__BCC__) -# define COMPILER_ID "Bruce" - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__ARMCC_VERSION) && !defined(__clang__) -# define COMPILER_ID "ARMCC" -#if __ARMCC_VERSION >= 1000000 - /* __ARMCC_VERSION = VRRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#else - /* __ARMCC_VERSION = VRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#endif - - -#elif defined(__clang__) && defined(__apple_build_version__) -# define COMPILER_ID "AppleClang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) - -#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) -# define COMPILER_ID "ARMClang" - # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) -# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif - -#elif defined(__GNUC__) -# define COMPILER_ID "GNU" -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# if defined(__GNUC_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" -#if defined(__VISUALDSPVERSION__) - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) -#endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" -# if defined(__VER__) && defined(__ICCARM__) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) -# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) -# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) -# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) -# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# endif - -#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) -# define COMPILER_ID "SDCC" -# if defined(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) -# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) -# else - /* SDCC = VRP */ -# define COMPILER_VERSION_MAJOR DEC(SDCC/100) -# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) -# define COMPILER_VERSION_PATCH DEC(SDCC % 10) -# endif - - -/* These compilers are either not known or too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; -#ifdef SIMULATE_ID -char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; -#endif - -#ifdef __QNXNTO__ -char const* qnxnto = "INFO" ":" "qnxnto[]"; -#endif - -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) -char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; -#endif - -#define STRINGIFY_HELPER(X) #X -#define STRINGIFY(X) STRINGIFY_HELPER(X) - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__MSYS__) -# define PLATFORM_ID "MSYS" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#elif defined(__WATCOMC__) -# if defined(__LINUX__) -# define PLATFORM_ID "Linux" - -# elif defined(__DOS__) -# define PLATFORM_ID "DOS" - -# elif defined(__OS2__) -# define PLATFORM_ID "OS2" - -# elif defined(__WINDOWS__) -# define PLATFORM_ID "Windows3x" - -# elif defined(__VXWORKS__) -# define PLATFORM_ID "VxWorks" - -# else /* unknown platform */ -# define PLATFORM_ID -# endif - -#elif defined(__INTEGRITY) -# if defined(INT_178B) -# define PLATFORM_ID "Integrity178" - -# else /* regular Integrity */ -# define PLATFORM_ID "Integrity" -# endif - -#else /* unknown platform */ -# define PLATFORM_ID - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_ARM64EC) -# define ARCHITECTURE_ID "ARM64EC" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM64) -# define ARCHITECTURE_ID "ARM64" - -# elif defined(_M_ARM) -# if _M_ARM == 4 -# define ARCHITECTURE_ID "ARMV4I" -# elif _M_ARM == 5 -# define ARCHITECTURE_ID "ARMV5I" -# else -# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) -# endif - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__WATCOMC__) -# if defined(_M_I86) -# define ARCHITECTURE_ID "I86" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# if defined(__ICCARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__ICCRX__) -# define ARCHITECTURE_ID "RX" - -# elif defined(__ICCRH850__) -# define ARCHITECTURE_ID "RH850" - -# elif defined(__ICCRL78__) -# define ARCHITECTURE_ID "RL78" - -# elif defined(__ICCRISCV__) -# define ARCHITECTURE_ID "RISCV" - -# elif defined(__ICCAVR__) -# define ARCHITECTURE_ID "AVR" - -# elif defined(__ICC430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__ICCV850__) -# define ARCHITECTURE_ID "V850" - -# elif defined(__ICC8051__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__ICCSTM8__) -# define ARCHITECTURE_ID "STM8" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__ghs__) -# if defined(__PPC64__) -# define ARCHITECTURE_ID "PPC64" - -# elif defined(__ppc__) -# define ARCHITECTURE_ID "PPC" - -# elif defined(__ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__x86_64__) -# define ARCHITECTURE_ID "x64" - -# elif defined(__i386__) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__TI_COMPILER_VERSION__) -# if defined(__TI_ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__MSP430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__TMS320C28XX__) -# define ARCHITECTURE_ID "TMS320C28x" - -# elif defined(__TMS320C6X__) || defined(_TMS320C6X) -# define ARCHITECTURE_ID "TMS320C6x" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number. */ -#ifdef COMPILER_VERSION -char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; - -/* Construct a string literal encoding the version number components. */ -#elif defined(COMPILER_VERSION_MAJOR) -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct a string literal encoding the internal version number. */ -#ifdef COMPILER_VERSION_INTERNAL -char const info_version_internal[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', - 'i','n','t','e','r','n','a','l','[', - COMPILER_VERSION_INTERNAL,']','\0'}; -#elif defined(COMPILER_VERSION_INTERNAL_STR) -char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; -#endif - -/* Construct a string literal encoding the version number components. */ -#ifdef SIMULATE_VERSION_MAJOR -char const info_simulate_version[] = { - 'I', 'N', 'F', 'O', ':', - 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', - SIMULATE_VERSION_MAJOR, -# ifdef SIMULATE_VERSION_MINOR - '.', SIMULATE_VERSION_MINOR, -# ifdef SIMULATE_VERSION_PATCH - '.', SIMULATE_VERSION_PATCH, -# ifdef SIMULATE_VERSION_TWEAK - '.', SIMULATE_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -#if !defined(__STDC__) && !defined(__clang__) -# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) -# define C_VERSION "90" -# else -# define C_VERSION -# endif -#elif __STDC_VERSION__ > 201710L -# define C_VERSION "23" -#elif __STDC_VERSION__ >= 201710L -# define C_VERSION "17" -#elif __STDC_VERSION__ >= 201000L -# define C_VERSION "11" -#elif __STDC_VERSION__ >= 199901L -# define C_VERSION "99" -#else -# define C_VERSION "90" -#endif -const char* info_language_standard_default = - "INFO" ":" "standard_default[" C_VERSION "]"; - -const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ -#if (defined(__clang__) || defined(__GNUC__) || \ - defined(__TI_COMPILER_VERSION__)) && \ - !defined(__STRICT_ANSI__) && !defined(_MSC_VER) - "ON" -#else - "OFF" -#endif -"]"; - -/*--------------------------------------------------------------------------*/ - -#ifdef ID_VOID_MAIN -void main() {} -#else -# if defined(__CLASSIC_C__) -int main(argc, argv) int argc; char *argv[]; -# else -int main(int argc, char* argv[]) -# endif -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; - require += info_arch[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif -#ifdef COMPILER_VERSION_INTERNAL - require += info_version_internal[argc]; -#endif -#ifdef SIMULATE_ID - require += info_simulate[argc]; -#endif -#ifdef SIMULATE_VERSION_MAJOR - require += info_simulate_version[argc]; -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - require += info_cray[argc]; -#endif - require += info_language_standard_default[argc]; - require += info_language_extensions_default[argc]; - (void)argv; - return require; -} -#endif diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o deleted file mode 100644 index 644f7767da3c033867802fd2410539172e92a3b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6048 zcmdT|Z){sv6+h38T_?`mrJ=N2y3RlcD=g1{V><4)2_T{Ukr0!H=)ORa5E4uXCJ^PE`|k0( zzJ5U!@P%9X-gAHVch5QZ+&}N6j~zLFG-4RQ#eg3|&|?(f(#?T9C&W3}hs^7b!&}#H zhs~=~u=#!xKD@pYHWL6(Cycode?N78bF|T@T-!OfnJ`9^*Zzw!(&g)g3;!#fSJ5x@ z|H74M^_L4LjxHXmxvfs4>3B=?O{-l$3j*vkt=@|3wU&-I+G`sUw7lBtl9anWt8H7J zUA3JRYpvN^%9Z7av(alnLG1dnz^qs4{UZ;B~lffHA+ReJ_)|*b(UGr*=iPtgHbKPcb)oQde&E|S* zy5qSIIkjHeo?WTTt`zNDsZ=W1Gud3;nW<%Gi?cH;h2=ulsW}BZUnu1d!u%JkbI$y{ zyx9x3S%b{!F5a`uLu*z$bJBAkL4|HNW7+jJyv5V2Zp)c&S#7KCcU1(@ZDS*I zud}>X&lJ0*a;a0OWh}2%Do(FgtcoX|KIKA&y?}#DKNgi-Z}TUbO^5r96vQ$`Le)o(oldi0^d1= z6A*=oA^ZWsAI292zH5l@>-oqK{+!?sI5docOm&nVN4& znfy`lOA;skl$5D?QOd+uai-8!_LCn*{FZV3Br#4elv)@ssUXUXb6og@(Ef`ryyUY? zc(9vv*8IZwYqHOKN;u|p{lYO}{?Fyee%X>g{nrvP-e2~U6)i}C_1uT^sPH-%KQ8eH z{b6AID-yRQPWstrg1)Np+mg@wPJH#8Jg?}X{o;MOtm*lh)WdNiJ?gprnWl&L@i&?t z|D6T+gThzO^FI}w{Na74^GAi_@Qm!IWlR3>9uY6E;G~D+%kgGCl%!Mf-%tNsspt8u zqDS4|a}sAg@5uh68vdT_^SYV;zQiwT{NKv{cQyQ1vcJ!F7h>2~{V7YF;-KPS+LXyv zt>tCUSqHO+`4LdY*>W%;GCikhnYPulOp%xMldO;|YFqA5LMBaid)|)Ur zf8N}K`yQ6<{LN4Q;3au}*n-v-ZzEy+jxukK1+Aq!rIw#y=iklWQpqUm^WTuzoW{F< z%m?_M)7_+X^7okEj;GK#+2`-NKa2iu_9gyKGA>~;hp;E`N0=T%Kfej=5tj@3 zp+IYzV?eg6G8JJz$$yG5&u9E)#K``@-NpWS>8QRg_8%#tyn}U^|F20R+mrOZeeVAP zg)slmhxkuf7wcpH|AAPT{VO+U|F7HFzZhblAl?4rHukq}(EhP)?7tFXpRz^W{wKDv z|K<(ar#vDo{#zmTDUZ?ZlNo6WrJ(S4f3NJ_E%Q8UP0ZYggGo4-dsXq!SyQ1Lu&e<$Y$3}1Rve-I^s z=Q01|2oR>&-|GXuK)$MF gd>i{$L+n%jsN1K!N?$wae@WWEBnQbZ?Ug?NU#KI5*Z=?k diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp deleted file mode 100644 index 25c62a8..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp +++ /dev/null @@ -1,791 +0,0 @@ -/* This source file must have a .cpp extension so that all C++ compilers - recognize the extension without flags. Borland does not know .cxx for - example. */ -#ifndef __cplusplus -# error "A C compiler has been selected for C++." -#endif - -#if !defined(__has_include) -/* If the compiler does not have __has_include, pretend the answer is - always no. */ -# define __has_include(x) 0 -#endif - - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__COMO__) -# define COMPILER_ID "Comeau" - /* __COMO_VERSION__ = VRR */ -# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) -# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) - -#elif defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# if defined(__GNUC__) -# define SIMULATE_ID "GNU" -# endif - /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, - except that a few beta releases use the old format with V=2021. */ -# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# if defined(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# else -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# endif -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) - /* The third version component from --version is an update index, - but no macro is provided for it. */ -# define COMPILER_VERSION_PATCH DEC(0) -# endif -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -# elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) -# define COMPILER_ID "IntelLLVM" -#if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -#endif -#if defined(__GNUC__) -# define SIMULATE_ID "GNU" -#endif -/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and - * later. Look for 6 digit vs. 8 digit version number to decide encoding. - * VVVV is no smaller than the current year when a version is released. - */ -#if __INTEL_LLVM_COMPILER < 1000000L -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) -#else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) -#endif -#if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -#endif -#if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -#elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -#endif -#if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -#endif -#if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -#endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__WATCOMC__) -# define COMPILER_ID "OpenWatcom" - /* __WATCOMC__ = VVRP + 1100 */ -# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__SUNPRO_CC) -# define COMPILER_ID "SunPro" -# if __SUNPRO_CC >= 0x5100 - /* __SUNPRO_CC = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# endif - -#elif defined(__HP_aCC) -# define COMPILER_ID "HP" - /* __HP_aCC = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) - -#elif defined(__DECCXX) -# define COMPILER_ID "Compaq" - /* __DECCXX_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) - -#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__ibmxl__) && defined(__clang__) -# define COMPILER_ID "XLClang" -# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) -# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) -# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) - - -#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 -# define COMPILER_ID "XL" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 -# define COMPILER_ID "VisualAge" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__NVCOMPILER) -# define COMPILER_ID "NVHPC" -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__CLANG_FUJITSU) -# define COMPILER_ID "FujitsuClang" -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# define COMPILER_VERSION_INTERNAL_STR __clang_version__ - - -#elif defined(__FUJITSU) -# define COMPILER_ID "Fujitsu" -# if defined(__FCC_version__) -# define COMPILER_VERSION __FCC_version__ -# elif defined(__FCC_major__) -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# endif -# if defined(__fcc_version) -# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) -# elif defined(__FCC_VERSION) -# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) -# endif - - -#elif defined(__ghs__) -# define COMPILER_ID "GHS" -/* __GHS_VERSION_NUMBER = VVVVRP */ -# ifdef __GHS_VERSION_NUMBER -# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) -# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) -# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) -# endif - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__ARMCC_VERSION) && !defined(__clang__) -# define COMPILER_ID "ARMCC" -#if __ARMCC_VERSION >= 1000000 - /* __ARMCC_VERSION = VRRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#else - /* __ARMCC_VERSION = VRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#endif - - -#elif defined(__clang__) && defined(__apple_build_version__) -# define COMPILER_ID "AppleClang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) - -#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) -# define COMPILER_ID "ARMClang" - # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) -# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif - -#elif defined(__GNUC__) || defined(__GNUG__) -# define COMPILER_ID "GNU" -# if defined(__GNUC__) -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# else -# define COMPILER_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" -#if defined(__VISUALDSPVERSION__) - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) -#endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" -# if defined(__VER__) && defined(__ICCARM__) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) -# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) -# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) -# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) -# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# endif - - -/* These compilers are either not known or too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; -#ifdef SIMULATE_ID -char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; -#endif - -#ifdef __QNXNTO__ -char const* qnxnto = "INFO" ":" "qnxnto[]"; -#endif - -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) -char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; -#endif - -#define STRINGIFY_HELPER(X) #X -#define STRINGIFY(X) STRINGIFY_HELPER(X) - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__MSYS__) -# define PLATFORM_ID "MSYS" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#elif defined(__WATCOMC__) -# if defined(__LINUX__) -# define PLATFORM_ID "Linux" - -# elif defined(__DOS__) -# define PLATFORM_ID "DOS" - -# elif defined(__OS2__) -# define PLATFORM_ID "OS2" - -# elif defined(__WINDOWS__) -# define PLATFORM_ID "Windows3x" - -# elif defined(__VXWORKS__) -# define PLATFORM_ID "VxWorks" - -# else /* unknown platform */ -# define PLATFORM_ID -# endif - -#elif defined(__INTEGRITY) -# if defined(INT_178B) -# define PLATFORM_ID "Integrity178" - -# else /* regular Integrity */ -# define PLATFORM_ID "Integrity" -# endif - -#else /* unknown platform */ -# define PLATFORM_ID - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_ARM64EC) -# define ARCHITECTURE_ID "ARM64EC" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM64) -# define ARCHITECTURE_ID "ARM64" - -# elif defined(_M_ARM) -# if _M_ARM == 4 -# define ARCHITECTURE_ID "ARMV4I" -# elif _M_ARM == 5 -# define ARCHITECTURE_ID "ARMV5I" -# else -# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) -# endif - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__WATCOMC__) -# if defined(_M_I86) -# define ARCHITECTURE_ID "I86" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# if defined(__ICCARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__ICCRX__) -# define ARCHITECTURE_ID "RX" - -# elif defined(__ICCRH850__) -# define ARCHITECTURE_ID "RH850" - -# elif defined(__ICCRL78__) -# define ARCHITECTURE_ID "RL78" - -# elif defined(__ICCRISCV__) -# define ARCHITECTURE_ID "RISCV" - -# elif defined(__ICCAVR__) -# define ARCHITECTURE_ID "AVR" - -# elif defined(__ICC430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__ICCV850__) -# define ARCHITECTURE_ID "V850" - -# elif defined(__ICC8051__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__ICCSTM8__) -# define ARCHITECTURE_ID "STM8" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__ghs__) -# if defined(__PPC64__) -# define ARCHITECTURE_ID "PPC64" - -# elif defined(__ppc__) -# define ARCHITECTURE_ID "PPC" - -# elif defined(__ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__x86_64__) -# define ARCHITECTURE_ID "x64" - -# elif defined(__i386__) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__TI_COMPILER_VERSION__) -# if defined(__TI_ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__MSP430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__TMS320C28XX__) -# define ARCHITECTURE_ID "TMS320C28x" - -# elif defined(__TMS320C6X__) || defined(_TMS320C6X) -# define ARCHITECTURE_ID "TMS320C6x" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number. */ -#ifdef COMPILER_VERSION -char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; - -/* Construct a string literal encoding the version number components. */ -#elif defined(COMPILER_VERSION_MAJOR) -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct a string literal encoding the internal version number. */ -#ifdef COMPILER_VERSION_INTERNAL -char const info_version_internal[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', - 'i','n','t','e','r','n','a','l','[', - COMPILER_VERSION_INTERNAL,']','\0'}; -#elif defined(COMPILER_VERSION_INTERNAL_STR) -char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; -#endif - -/* Construct a string literal encoding the version number components. */ -#ifdef SIMULATE_VERSION_MAJOR -char const info_simulate_version[] = { - 'I', 'N', 'F', 'O', ':', - 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', - SIMULATE_VERSION_MAJOR, -# ifdef SIMULATE_VERSION_MINOR - '.', SIMULATE_VERSION_MINOR, -# ifdef SIMULATE_VERSION_PATCH - '.', SIMULATE_VERSION_PATCH, -# ifdef SIMULATE_VERSION_TWEAK - '.', SIMULATE_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L -# if defined(__INTEL_CXX11_MODE__) -# if defined(__cpp_aggregate_nsdmi) -# define CXX_STD 201402L -# else -# define CXX_STD 201103L -# endif -# else -# define CXX_STD 199711L -# endif -#elif defined(_MSC_VER) && defined(_MSVC_LANG) -# define CXX_STD _MSVC_LANG -#else -# define CXX_STD __cplusplus -#endif - -const char* info_language_standard_default = "INFO" ":" "standard_default[" -#if CXX_STD > 202002L - "23" -#elif CXX_STD > 201703L - "20" -#elif CXX_STD >= 201703L - "17" -#elif CXX_STD >= 201402L - "14" -#elif CXX_STD >= 201103L - "11" -#else - "98" -#endif -"]"; - -const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ -#if (defined(__clang__) || defined(__GNUC__) || \ - defined(__TI_COMPILER_VERSION__)) && \ - !defined(__STRICT_ANSI__) && !defined(_MSC_VER) - "ON" -#else - "OFF" -#endif -"]"; - -/*--------------------------------------------------------------------------*/ - -int main(int argc, char* argv[]) -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif -#ifdef COMPILER_VERSION_INTERNAL - require += info_version_internal[argc]; -#endif -#ifdef SIMULATE_ID - require += info_simulate[argc]; -#endif -#ifdef SIMULATE_VERSION_MAJOR - require += info_simulate_version[argc]; -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - require += info_cray[argc]; -#endif - require += info_language_standard_default[argc]; - require += info_language_extensions_default[argc]; - (void)argv; - return require; -} diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o deleted file mode 100644 index 388b75b4cb13f57f4bb096dcff3e4e8f3e045eec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6064 zcmdT|Yit}>6+W}$b?mIOiDS}++Df+~MG0kRA71aS6BHb!33bTB3W=1~jke?6@p{|c zoz3jna#2M?sl-Dd5q?0C%0GkxL~1}4)B&XatPl_Jqg6pj1O!rfNVGg8BBYvg?%cC; z_wKk2{NqNx_nhy3=W(BNH%}iwbs}aMz{P;?L#QzdaAQ{}&k1o3rjWV$Dfq?ay|8g> z5;lIDfZLlpVPgc~izCL|?LSUl*%)m!%5UtP+ZZuM6K}jrAMpcQxccANy;Hnf7#nlE z`m$MhZT`%Ovxll~tJ7#Y-r}*Q-L78(0d|_UzwCOg#Z!&;>beANue!1*<*skHYqnRb z)SP8|wdpVBO0vgU_nmgP;kLWIzO!d8g_HFzQeRG$HOC`Yi&;@}B`XlJSr+n_z!*2~ zPfob}UixQ=M-Ls%Kl8lxst%!g1KI*-*Jh@Zv=hl%ML+eEVsmmJ_S{`DD+l2PF6 zr?JpiNLJC<4Kn|k!V6=LL1?2gV!tPw-$mNoqu8j7*j^mG@wZ5uDaA%*Y{xKgp6s4i z>p| zN82^eZPZc+a@m=gd^TVHVCsQR-NkyzZTi?WeN@t|CSgl<*Qur4cFHT1OQk}ob}&_? zvz3y&IYs-}%BK#j_(-l2*Io6hj)mtkZ^F9(<^SvNw@5_U3WarEn{~&8LPU! zo_Ww&TCHaa-D0WOnXYDRuT?Ch*UENA#5#djNjEcXW8GpBA{dtov-961cck`|!&G7x!Hs-W0gF zruy)@z=JjG>p;a+^5?!K!ROt;XwaH4-VdO5N$>~pivr(0z$d_j_YC0Q5d1;>^8(*9 z!2hJc?;gMjFaf`{T3HkPLHrNM+pVm-*yo6S4*$l3n_hV0mH4N?S;H@^=moeS@NoVa zKPd2U{u$qg`HVxjj*RmROkh8sJqp1x*|AJ`mMSd7S4UR}U?9GVFG!sDVYc}3l=vPE zUs3q?NST_Zl*zw}KPz$aKPhEuJ|kt~t2k5W&<>ssx?KWX-vNw&fE~z|@!}RZkDpIm z4E=|z6V3_Y>aOOU%=k;v|6Q^rT+NZ^g!w<0ynV8zJbO1GV!U3Qzofw#DX^c@Xh((i z8x_XSN&L|O?%~T4Z%CZ{tNZ7Qg46u-7(Od;_U}tSUsm|)zPhI1pRv*&Rj@irqw3~auTmkHE^@hb|lML zsVsYT3soGAZ!cl{WQ*GUHEWitGF2t2id4-|RiG+2O|__Uc@jmH%Za|;u+VGH3a~8f zU$^+PAXoE$Z)l$nzJ37yB`?kI$o<3-G!=GY2Vs2QGH;Frtqp$vhTv~dd?)+sAyr7a z{jU%uY)rmSKoJJ@)xSG@OLoK0xrp9LxsMFBnC%(=D`HXcACn0(A8DfK`kxSuioX&OpKRHl z-$>5$OsDQIz~O;mEgAmTCdi*FJh055&2P>&`qsV zQ{e^VMvea!Iey+)wEyXirjOr8jC|@B;$7qv%dj>v9G_cy4@KEe$qQ{mcnK@E(X8y7muG~&7yte{K@;9&ne9x{hDHX#?vxB`{Q;*{Kq1| l*BFqkp8tU@;@^shPwz=RKE0>(u~VpPGX6`llj26@{~tJ_iIV^T diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/TargetDirectories.txt deleted file mode 100644 index 67bfb70..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/TargetDirectories.txt +++ /dev/null @@ -1,2 +0,0 @@ -/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/edit_cache.dir -/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/cmake.check_cache deleted file mode 100644 index 3dccd73..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/cmake.check_cache +++ /dev/null @@ -1 +0,0 @@ -# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rules.ninja b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rules.ninja deleted file mode 100644 index 28085d5..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/CMakeFiles/rules.ninja +++ /dev/null @@ -1,45 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Ninja" Generator, CMake Version 3.22 - -# This file contains all the rules used to get the outputs files -# built from the input files. -# It is included in the main 'build.ninja'. - -# ============================================================================= -# Project: Project -# Configurations: Debug -# ============================================================================= -# ============================================================================= - -############################################# -# Rule for running custom commands. - -rule CUSTOM_COMMAND - command = $COMMAND - description = $DESC - - -############################################# -# Rule for re-running cmake. - -rule RERUN_CMAKE - command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a - description = Re-running CMake... - generator = 1 - - -############################################# -# Rule for cleaning all built files. - -rule CLEAN - command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja $FILE_ARG -t clean $TARGETS - description = Cleaning all built files... - - -############################################# -# Rule for printing all primary targets available. - -rule HELP - command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja -t targets - description = All primary targets available: - diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/additional_project_files.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/additional_project_files.txt deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json deleted file mode 100644 index 0677eb2..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "buildFiles": [ - "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" - ], - "cleanCommandsComponents": [ - [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", - "clean" - ] - ], - "buildTargetsCommandComponents": [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", - "{LIST_OF_TARGETS_TO_BUILD}" - ], - "libraries": {}, - "toolchains": { - "toolchain": { - "cCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang.lld", - "cppCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++.lld" - } - }, - "cFileExtensions": [], - "cppFileExtensions": [] -} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json deleted file mode 100644 index 84dea41..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "buildFiles": [ - "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" - ], - "cleanCommandsComponents": [ - [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", - "clean" - ] - ], - "buildTargetsCommandComponents": [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a", - "{LIST_OF_TARGETS_TO_BUILD}" - ], - "libraries": {} -} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja deleted file mode 100644 index b54a2e4..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja +++ /dev/null @@ -1,112 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Ninja" Generator, CMake Version 3.22 - -# This file contains all the build statements describing the -# compilation DAG. - -# ============================================================================= -# Write statements declared in CMakeLists.txt: -# -# Which is the root file. -# ============================================================================= - -# ============================================================================= -# Project: Project -# Configurations: Debug -# ============================================================================= - -############################################# -# Minimal version of Ninja required by this file - -ninja_required_version = 1.5 - - -############################################# -# Set configuration variable for custom commands. - -CONFIGURATION = Debug -# ============================================================================= -# Include auxiliary files. - - -############################################# -# Include rules file. - -include CMakeFiles/rules.ninja - -# ============================================================================= - -############################################# -# Logical path to working directory; prefix for absolute paths. - -cmake_ninja_workdir = /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/ - -############################################# -# Utility command for edit_cache - -build CMakeFiles/edit_cache.util: CUSTOM_COMMAND - COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a - DESC = Running CMake cache editor... - pool = console - restat = 1 - -build edit_cache: phony CMakeFiles/edit_cache.util - - -############################################# -# Utility command for rebuild_cache - -build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND - COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a - DESC = Running CMake to regenerate build system... - pool = console - restat = 1 - -build rebuild_cache: phony CMakeFiles/rebuild_cache.util - -# ============================================================================= -# Target aliases. - -# ============================================================================= -# Folder targets. - -# ============================================================================= - -############################################# -# Folder: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a - -build all: phony - -# ============================================================================= -# Built-in targets - - -############################################# -# Re-run CMake if any of its inputs changed. - -build build.ninja: RERUN_CMAKE | /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake - pool = console - - -############################################# -# A missing CMake input file is not an error. - -build /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake: phony - - -############################################# -# Clean all the built files. - -build clean: CLEAN - - -############################################# -# Print all primary targets available. - -build help: HELP - - -############################################# -# Make the all target the default. - -default all diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt deleted file mode 100644 index ec6a72a..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt +++ /dev/null @@ -1 +0,0 @@ -/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/cmake_install.cmake b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/cmake_install.cmake deleted file mode 100644 index 27069b4..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/cmake_install.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# Install script for directory: /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy - -# Set the install prefix -if(NOT DEFINED CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local") -endif() -string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - if(BUILD_TYPE) - string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - else() - set(CMAKE_INSTALL_CONFIG_NAME "Debug") - endif() - message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -endif() - -# Set the component getting installed. -if(NOT CMAKE_INSTALL_COMPONENT) - if(COMPONENT) - message(STATUS "Install component: \"${COMPONENT}\"") - set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - else() - set(CMAKE_INSTALL_COMPONENT) - endif() -endif() - -# Install shared libraries without execute permission? -if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) - set(CMAKE_INSTALL_SO_NO_EXE "0") -endif() - -# Is this installation the result of a crosscompile? -if(NOT DEFINED CMAKE_CROSSCOMPILING) - set(CMAKE_CROSSCOMPILING "TRUE") -endif() - -# Set default install directory permissions. -if(NOT DEFINED CMAKE_OBJDUMP) - set(CMAKE_OBJDUMP "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump") -endif() - -if(CMAKE_INSTALL_COMPONENT) - set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") -else() - set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") -endif() - -string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT - "${CMAKE_INSTALL_MANIFEST_FILES}") -file(WRITE "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/${CMAKE_INSTALL_MANIFEST}" - "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin deleted file mode 100644 index 6a7dacd..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/configure_fingerprint.bin +++ /dev/null @@ -1,28 +0,0 @@ -C/C++ Structured Logu -s -q/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/additional_project_files.txtC -A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  „¹ã×2  ¹ã×2r -p -n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build.json  „¹ã×2Ï ‚¹ã×2w -u -s/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/android_gradle_build_mini.json  „¹ã×2Ú ƒ¹ã×2d -b -`/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja  „¹ã×2”Ä ÷¸ã×2h -f -d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build.ninja.txt  „¹ã×2m -k -i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/build_file_index.txt  „¹ã×2 P „¹ã×2n -l -j/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/compile_commands.json  „¹ã×2r -p -n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/compile_commands.json.bin  „¹ã×2 x -v -t/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt  „¹ã×2 -¾ „¹ã×2k -i -g/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json  „¹ã×2  ( „¹ã×2p -n -l/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt  „¹ã×2  c „¹ã×2T -R -P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  „¹ã×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt deleted file mode 100644 index df24dc1..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/metadata_generation_command.txt +++ /dev/null @@ -1,20 +0,0 @@ - -H/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy --DCMAKE_SYSTEM_NAME=Android --DCMAKE_EXPORT_COMPILE_COMMANDS=ON --DCMAKE_SYSTEM_VERSION=26 --DANDROID_PLATFORM=android-26 --DANDROID_ABI=arm64-v8a --DCMAKE_ANDROID_ARCH_ABI=arm64-v8a --DANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 --DCMAKE_ANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 --DCMAKE_TOOLCHAIN_FILE=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake --DCMAKE_MAKE_PROGRAM=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja --DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a --DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a --DCMAKE_BUILD_TYPE=Debug --B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/arm64-v8a --GNinja --Wno-dev ---no-warn-unused-cli - Build command args: [] - Version: 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json deleted file mode 100644 index e799de8..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/prefab_config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "enabled": false, - "packages": [] -} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt b/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt deleted file mode 100644 index 44c632a..0000000 --- a/android/app/.cxx/Debug/4s676p3c/arm64-v8a/symbol_folder_index.txt +++ /dev/null @@ -1 +0,0 @@ -/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/arm64-v8a \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cache-v2 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/query/client-agp/codemodel-v2 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cache-v2-6573c0656e67becaeff1.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cache-v2-6573c0656e67becaeff1.json deleted file mode 100644 index 12ec5a0..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cache-v2-6573c0656e67becaeff1.json +++ /dev/null @@ -1,1391 +0,0 @@ -{ - "entries" : - [ - { - "name" : "ANDROID_ABI", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "armeabi-v7a" - }, - { - "name" : "ANDROID_NDK", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" - }, - { - "name" : "ANDROID_PLATFORM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "android-26" - }, - { - "name" : "CMAKE_ADDR2LINE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line" - }, - { - "name" : "CMAKE_ANDROID_ARCH_ABI", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "armeabi-v7a" - }, - { - "name" : "CMAKE_ANDROID_NDK", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" - }, - { - "name" : "CMAKE_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_ASM_FLAGS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_ASM_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_ASM_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_BUILD_TYPE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." - } - ], - "type" : "STRING", - "value" : "Debug" - }, - { - "name" : "CMAKE_CACHEFILE_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "This is the directory where this CMakeCache.txt was created" - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a" - }, - { - "name" : "CMAKE_CACHE_MAJOR_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Major version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "3" - }, - { - "name" : "CMAKE_CACHE_MINOR_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Minor version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "22" - }, - { - "name" : "CMAKE_CACHE_PATCH_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Patch version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to CMake executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake" - }, - { - "name" : "CMAKE_CPACK_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to cpack program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack" - }, - { - "name" : "CMAKE_CTEST_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to ctest program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest" - }, - { - "name" : "CMAKE_CXX_COMPILER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "(This variable does not exist and should not be used)" - } - ], - "type" : "UNINITIALIZED", - "value" : "" - }, - { - "name" : "CMAKE_CXX_COMPILER_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "LLVM archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_CXX_COMPILER_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Generate index for LLVM archive" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_CXX_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the CXX compiler during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "-Os -DNDEBUG" - }, - { - "name" : "CMAKE_CXX_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "-O2 -g -DNDEBUG" - }, - { - "name" : "CMAKE_CXX_STANDARD_LIBRARIES", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Libraries linked by default with all C++ applications." - } - ], - "type" : "STRING", - "value" : "-latomic -lm" - }, - { - "name" : "CMAKE_C_COMPILER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "(This variable does not exist and should not be used)" - } - ], - "type" : "UNINITIALIZED", - "value" : "" - }, - { - "name" : "CMAKE_C_COMPILER_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "LLVM archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_C_COMPILER_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Generate index for LLVM archive" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_C_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the C compiler during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "-Os -DNDEBUG" - }, - { - "name" : "CMAKE_C_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "-O2 -g -DNDEBUG" - }, - { - "name" : "CMAKE_C_STANDARD_LIBRARIES", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Libraries linked by default with all C applications." - } - ], - "type" : "STRING", - "value" : "-latomic -lm" - }, - { - "name" : "CMAKE_DLLTOOL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "CMAKE_DLLTOOL-NOTFOUND" - }, - { - "name" : "CMAKE_EDIT_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to cache edit program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake" - }, - { - "name" : "CMAKE_ERROR_DEPRECATED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Whether to issue deprecation errors for macros and functions." - } - ], - "type" : "INTERNAL", - "value" : "FALSE" - }, - { - "name" : "CMAKE_EXECUTABLE_FORMAT", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Executable file format" - } - ], - "type" : "INTERNAL", - "value" : "ELF" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "ON" - }, - { - "name" : "CMAKE_EXTRA_GENERATOR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of external makefile project generator." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator." - } - ], - "type" : "INTERNAL", - "value" : "Ninja" - }, - { - "name" : "CMAKE_GENERATOR_INSTANCE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Generator instance identifier." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR_PLATFORM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator platform." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR_TOOLSET", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator toolset." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_HOME_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Source directory with the top level CMakeLists.txt file for this project" - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - { - "name" : "CMAKE_INSTALL_PREFIX", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Install path prefix, prepended onto install directories." - } - ], - "type" : "PATH", - "value" : "/usr/local" - }, - { - "name" : "CMAKE_INSTALL_SO_NO_EXE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Install .so files without execute permission." - } - ], - "type" : "INTERNAL", - "value" : "0" - }, - { - "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a" - }, - { - "name" : "CMAKE_LINKER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" - }, - { - "name" : "CMAKE_MAKE_PROGRAM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_NM", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm" - }, - { - "name" : "CMAKE_NUMBER_OF_MAKEFILES", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "number of local generators" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_OBJCOPY", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy" - }, - { - "name" : "CMAKE_OBJDUMP", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump" - }, - { - "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Platform information initialized" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_PROJECT_DESCRIPTION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "" - }, - { - "name" : "CMAKE_PROJECT_HOMEPAGE_URL", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "" - }, - { - "name" : "CMAKE_PROJECT_NAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "Project" - }, - { - "name" : "CMAKE_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Ranlib" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_READELF", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf" - }, - { - "name" : "CMAKE_ROOT", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to CMake installation." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" - }, - { - "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of dll's." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SKIP_INSTALL_RPATH", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." - } - ], - "type" : "BOOL", - "value" : "NO" - }, - { - "name" : "CMAKE_SKIP_RPATH", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If set, runtime paths are not added when using shared libraries." - } - ], - "type" : "BOOL", - "value" : "NO" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STRIP", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Strip" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip" - }, - { - "name" : "CMAKE_SUPPRESS_DEVELOPER_ERRORS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Suppress errors that are meant for the author of the CMakeLists.txt files." - } - ], - "type" : "INTERNAL", - "value" : "TRUE" - }, - { - "name" : "CMAKE_SUPPRESS_DEVELOPER_WARNINGS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Suppress Warnings that are meant for the author of the CMakeLists.txt files." - } - ], - "type" : "INTERNAL", - "value" : "TRUE" - }, - { - "name" : "CMAKE_SYSTEM_NAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "Android" - }, - { - "name" : "CMAKE_SYSTEM_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "26" - }, - { - "name" : "CMAKE_TOOLCHAIN_FILE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "The CMake toolchain file" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "name" : "CMAKE_UNAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "uname command" - } - ], - "type" : "INTERNAL", - "value" : "/usr/bin/uname" - }, - { - "name" : "CMAKE_VERBOSE_MAKEFILE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." - } - ], - "type" : "BOOL", - "value" : "FALSE" - }, - { - "name" : "CMAKE_WARN_DEPRECATED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Whether to issue warnings for deprecated functionality." - } - ], - "type" : "INTERNAL", - "value" : "FALSE" - }, - { - "name" : "Project_BINARY_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a" - }, - { - "name" : "Project_IS_TOP_LEVEL", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "ON" - }, - { - "name" : "Project_SOURCE_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - } - ], - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-161e4284e257b7dbcee8.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-161e4284e257b7dbcee8.json deleted file mode 100644 index ad14735..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-161e4284e257b7dbcee8.json +++ /dev/null @@ -1,799 +0,0 @@ -{ - "inputs" : - [ - { - "path" : "CMakeLists.txt" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" - } - ], - "kind" : "cmakeFiles", - "paths" : - { - "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", - "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - "version" : - { - "major" : 1, - "minor" : 0 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-769fcb1eb528b5a1f77c.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-769fcb1eb528b5a1f77c.json deleted file mode 100644 index 35467aa..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-769fcb1eb528b5a1f77c.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "configurations" : - [ - { - "directories" : - [ - { - "build" : ".", - "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", - "minimumCMakeVersion" : - { - "string" : "3.6.0" - }, - "projectIndex" : 0, - "source" : "." - } - ], - "name" : "Debug", - "projects" : - [ - { - "directoryIndexes" : - [ - 0 - ], - "name" : "Project" - } - ], - "targets" : [] - } - ], - "kind" : "codemodel", - "paths" : - { - "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", - "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - "version" : - { - "major" : 2, - "minor" : 3 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json deleted file mode 100644 index 3a67af9..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "backtraceGraph" : - { - "commands" : [], - "files" : [], - "nodes" : [] - }, - "installers" : [], - "paths" : - { - "build" : ".", - "source" : "." - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0871.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0871.json deleted file mode 100644 index 70ff0c6..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/.cmake/api/v1/reply/index-2025-03-09T19-31-30-0871.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "cmake" : - { - "generator" : - { - "multiConfig" : false, - "name" : "Ninja" - }, - "paths" : - { - "cmake" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake", - "cpack" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack", - "ctest" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest", - "root" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" - }, - "version" : - { - "isDirty" : false, - "major" : 3, - "minor" : 22, - "patch" : 1, - "string" : "3.22.1-g37088a8", - "suffix" : "g37088a8" - } - }, - "objects" : - [ - { - "jsonFile" : "codemodel-v2-769fcb1eb528b5a1f77c.json", - "kind" : "codemodel", - "version" : - { - "major" : 2, - "minor" : 3 - } - }, - { - "jsonFile" : "cache-v2-6573c0656e67becaeff1.json", - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } - }, - { - "jsonFile" : "cmakeFiles-v1-161e4284e257b7dbcee8.json", - "kind" : "cmakeFiles", - "version" : - { - "major" : 1, - "minor" : 0 - } - } - ], - "reply" : - { - "client-agp" : - { - "cache-v2" : - { - "jsonFile" : "cache-v2-6573c0656e67becaeff1.json", - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } - }, - "cmakeFiles-v1" : - { - "jsonFile" : "cmakeFiles-v1-161e4284e257b7dbcee8.json", - "kind" : "cmakeFiles", - "version" : - { - "major" : 1, - "minor" : 0 - } - }, - "codemodel-v2" : - { - "jsonFile" : "codemodel-v2-769fcb1eb528b5a1f77c.json", - "kind" : "codemodel", - "version" : - { - "major" : 2, - "minor" : 3 - } - } - } - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeCache.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeCache.txt deleted file mode 100644 index 4f7a9db..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeCache.txt +++ /dev/null @@ -1,405 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a -# It was generated by CMake: /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//No help, variable specified on the command line. -ANDROID_ABI:UNINITIALIZED=armeabi-v7a - -//No help, variable specified on the command line. -ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 - -//No help, variable specified on the command line. -ANDROID_PLATFORM:UNINITIALIZED=android-26 - -//Path to a program. -CMAKE_ADDR2LINE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line - -//No help, variable specified on the command line. -CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=armeabi-v7a - -//No help, variable specified on the command line. -CMAKE_ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 - -//Archiver -CMAKE_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Flags used by the compiler during all build types. -CMAKE_ASM_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_ASM_FLAGS_DEBUG:STRING= - -//Flags used by the compiler during release builds. -CMAKE_ASM_FLAGS_RELEASE:STRING= - -//Choose the type of build, options are: None Debug Release RelWithDebInfo -// MinSizeRel ... -CMAKE_BUILD_TYPE:STRING=Debug - -//LLVM archiver -CMAKE_CXX_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Generate index for LLVM archive -CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING= - -//Flags used by the CXX compiler during MINSIZEREL builds. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_CXX_FLAGS_RELEASE:STRING= - -//Flags used by the CXX compiler during RELWITHDEBINFO builds. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Libraries linked by default with all C++ applications. -CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm - -//LLVM archiver -CMAKE_C_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Generate index for LLVM archive -CMAKE_C_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING= - -//Flags used by the C compiler during MINSIZEREL builds. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_C_FLAGS_RELEASE:STRING= - -//Flags used by the C compiler during RELWITHDEBINFO builds. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Libraries linked by default with all C applications. -CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm - -//Path to a program. -CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING= - -//Flags used by the linker during DEBUG builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during MINSIZEREL builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during RELEASE builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during RELWITHDEBINFO builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//No help, variable specified on the command line. -CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//No help, variable specified on the command line. -CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a - -//Path to a program. -CMAKE_LINKER:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld - -//No help, variable specified on the command line. -CMAKE_MAKE_PROGRAM:UNINITIALIZED=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of modules during -// DEBUG builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of modules during -// MINSIZEREL builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of modules during -// RELEASE builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of modules during -// RELWITHDEBINFO builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump - -//Value Computed by CMake -CMAKE_PROJECT_DESCRIPTION:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_HOMEPAGE_URL:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=Project - -//Ranlib -CMAKE_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Path to a program. -CMAKE_READELF:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf - -//No help, variable specified on the command line. -CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of shared libraries -// during DEBUG builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of shared libraries -// during MINSIZEREL builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELEASE builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELWITHDEBINFO builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries -// during all build types. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of static libraries -// during DEBUG builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of static libraries -// during MINSIZEREL builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELEASE builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELWITHDEBINFO builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Strip -CMAKE_STRIP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip - -//No help, variable specified on the command line. -CMAKE_SYSTEM_NAME:UNINITIALIZED=Android - -//No help, variable specified on the command line. -CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 - -//The CMake toolchain file -CMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//Value Computed by CMake -Project_BINARY_DIR:STATIC=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a - -//Value Computed by CMake -Project_IS_TOP_LEVEL:STATIC=ON - -//Value Computed by CMake -Project_SOURCE_DIR:STATIC=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: CMAKE_ADDR2LINE -CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest -//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR -CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB -CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES -CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_AR -CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB -CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES -CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_DLLTOOL -CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 -//Path to cache edit program executable. -CMAKE_EDIT_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -//Whether to issue deprecation errors for macros and functions. -CMAKE_ERROR_DEPRECATED:INTERNAL=FALSE -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Ninja -//Generator instance identifier. -CMAKE_GENERATOR_INSTANCE:INTERNAL= -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -//Install .so files without execute permission. -CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_READELF -CMAKE_READELF-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//Suppress errors that are meant for the author of the CMakeLists.txt -// files. -CMAKE_SUPPRESS_DEVELOPER_ERRORS:INTERNAL=TRUE -//Suppress Warnings that are meant for the author of the CMakeLists.txt -// files. -CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=TRUE -//uname command -CMAKE_UNAME:INTERNAL=/usr/bin/uname -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Whether to issue warnings for deprecated functionality. -CMAKE_WARN_DEPRECATED:INTERNAL=FALSE - diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake deleted file mode 100644 index 802edf5..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake +++ /dev/null @@ -1,72 +0,0 @@ -set(CMAKE_C_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang") -set(CMAKE_C_COMPILER_ARG1 "") -set(CMAKE_C_COMPILER_ID "Clang") -set(CMAKE_C_COMPILER_VERSION "17.0.2") -set(CMAKE_C_COMPILER_VERSION_INTERNAL "") -set(CMAKE_C_COMPILER_WRAPPER "") -set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") -set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") -set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") -set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") -set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") -set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") -set(CMAKE_C17_COMPILE_FEATURES "c_std_17") -set(CMAKE_C23_COMPILE_FEATURES "c_std_23") - -set(CMAKE_C_PLATFORM_ID "Linux") -set(CMAKE_C_SIMULATE_ID "") -set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") -set(CMAKE_C_SIMULATE_VERSION "") - - - - -set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_C_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_C_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") -set(CMAKE_MT "") -set(CMAKE_COMPILER_IS_GNUCC ) -set(CMAKE_C_COMPILER_LOADED 1) -set(CMAKE_C_COMPILER_WORKS TRUE) -set(CMAKE_C_ABI_COMPILED TRUE) - -set(CMAKE_C_COMPILER_ENV_VAR "CC") - -set(CMAKE_C_COMPILER_ID_RUN 1) -set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) -set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) -set(CMAKE_C_LINKER_PREFERENCE 10) - -# Save compiler ABI information. -set(CMAKE_C_SIZEOF_DATA_PTR "4") -set(CMAKE_C_COMPILER_ABI "ELF") -set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") -set(CMAKE_C_LIBRARY_ARCHITECTURE "") - -if(CMAKE_C_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_C_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") -endif() - -if(CMAKE_C_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - -set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") -if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) - set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") -endif() - - - - - -set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/arm-linux-androideabi;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") -set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") -set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/arm;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/arm-linux-androideabi/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/arm-linux-androideabi;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") -set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake deleted file mode 100644 index 2193dfd..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake +++ /dev/null @@ -1,83 +0,0 @@ -set(CMAKE_CXX_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++") -set(CMAKE_CXX_COMPILER_ARG1 "") -set(CMAKE_CXX_COMPILER_ID "Clang") -set(CMAKE_CXX_COMPILER_VERSION "17.0.2") -set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") -set(CMAKE_CXX_COMPILER_WRAPPER "") -set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") -set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") -set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") -set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") -set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") -set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") -set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") -set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") -set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") - -set(CMAKE_CXX_PLATFORM_ID "Linux") -set(CMAKE_CXX_SIMULATE_ID "") -set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") -set(CMAKE_CXX_SIMULATE_VERSION "") - - - - -set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_CXX_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_CXX_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") -set(CMAKE_MT "") -set(CMAKE_COMPILER_IS_GNUCXX ) -set(CMAKE_CXX_COMPILER_LOADED 1) -set(CMAKE_CXX_COMPILER_WORKS TRUE) -set(CMAKE_CXX_ABI_COMPILED TRUE) - -set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") - -set(CMAKE_CXX_COMPILER_ID_RUN 1) -set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) -set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) - -foreach (lang C OBJC OBJCXX) - if (CMAKE_${lang}_COMPILER_ID_RUN) - foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) - list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) - endforeach() - endif() -endforeach() - -set(CMAKE_CXX_LINKER_PREFERENCE 30) -set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) - -# Save compiler ABI information. -set(CMAKE_CXX_SIZEOF_DATA_PTR "4") -set(CMAKE_CXX_COMPILER_ABI "ELF") -set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") -set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") - -if(CMAKE_CXX_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_CXX_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") -endif() - -if(CMAKE_CXX_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - -set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") -if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) - set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") -endif() - - - - - -set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/arm-linux-androideabi;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") -set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl") -set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/arm;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/arm-linux-androideabi/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/arm-linux-androideabi;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") -set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin deleted file mode 100755 index 3f1c03f0c432c32e4e2cfcdb062fe1e43751825d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5896 zcmdT|U2GiH6}~gOYj5oJdhHOBK!6E#gCp$S^}ihujsKD?a*P{{3QgL{?9O<-WOrvf zJ5Fr`Y6Ve+RA`{8+91&;Nc5pntGW-BDwS5M6!Fj>iHE$jPfk(?kyb6K0MSz6e&5Vo zXS|52f~Q{l%st;Z=brn2?!Ei9>6t@{q6nEHqFWGMiU=`?Jl=_qDq@2|6D`nb;!e>7 z5p|Ldq5vrh83{#&3oL0nFo`;dJwmpbvN0h@_!lDO>pj^H$Uzzkkyx+P&jHNs^NC{m zmUa8;h=r+e%o9Q0734k0S63rnKNH|7l)DxD z5$0HsGt4oFx!FSx9jKR{uT+m2~D$7gc$^E1=>^z2k_d{*j>eCas$G9Vgq;i_1>aJ5ZbxV*8kaa|ng zeXDKt!sXN(N3Ud4=hvgz=dUQK^KT|n&#!j@laGVn6Yx>+B6Z%=yM}qZzJ|)**^4>Lo?nk-&#v7| z8St4^^^njaFR0&EUKB5=FSQ?8o*F+P&c&yQ+JLg}ccdh4X~4}PYjG~RT04C0!;Ou< zf&L9jpiT~fOwqO8b#d+N73KQ3uFT)~_4=iTBwmN^x6fU<|Hf;cPU36>?g}v6d;S}9 zOtlyTG3Oe-6U06J!N!ISSsY==OC9*eu?{$d8i;X`cK?DM*EZMSqtG*k?E-P%jbiO^ z53(#{&=i!d$hl9rLoNa%e2EFryB}`YKL*yoGj{GpPXD_>qrkTZn0xRb@SXs_jrz}^ z9EQ+-4mtYAc5f!yvOIk*v7w=~1}tgDi)RP4nVBiAZzP>f_X`=%wC=v_&`^K2f3!!t zw^p?A&D&)cS=j~Xt&}Ot8+FUn?5gGrj*g5Bj+pzkLfNPmwbPbUFG22m)w&m5w^l!p z$rygLOc!mtShni+l2fqK1-p`QZM$4pG#F&drz^cR$9~)@xSBb(Fgms{X!Z>c4-c3_ z*}i^jsE{2S92;5~$PZ+#f;C|F4-EJ37vuM#lZJ(zC6qp}ll|%Jm}qKg9*-;A)Rss> zNs4wQrF5vB(OZ-qVrOKRvRk=Ly<6F*C>_dYliOpFWNPQ_$quCx^QI1pNHVwmbGr|; z-q)&PawCe8!~940irn@QOlWK$7))^&>>g-sg`}BmYwH7G<9=ybc3T=XbT%E_6-iQb z&u%)#GKdK^5YbiZ;1-x@_bL$0m|1@gqsmEi><;nsV6KOeyHHW8K7`K*NQuTGH7vx) zBtVqX9U^uFnRg(@mF8V26>pAn-4{VhTP*So+SdU*`*smqru{20Y*yo3v@g)GGZuMu zi(yK{KLf>2sO*VFE>bxO;CV@kZL)337gpg)ZT}~9E$UNohTlyT?eh@#VypU;I1C%L zla`{X9ZNeFO~jx|um=JQ#1WidBS!`l9W)qJsUrrTUpt-Z7k&OmJz+)Xh_wLIr*@1L^+$ zbYG^98Mb^;FGZQ7wz;%f#pI-2si8(^d?J@FVE$Y`t}?zyu}PFClL_8mo^ zY{x2!ir+ws8}tXsHf9iU-6^3F!r}iZ+Zbx%BE5fFe_Q*^CP#6_SJ}5nN{KbM{4#b| zCYEeU$66O+`m)^udyK{bUjfV-_JEQyL68wsfSzVK6< zcdq>zcpd^3x5YbUJKz#@N6IZrK)Y>1n?BF7T_8%-zsd9qV5n+0kgea zQ?!2uxlA0N?*VWw{M06126HilUjb%(_5K9B*kCxO)y4#DJlMrJQc$K0NxYA?*eNf{626`2>%rQxly?B?U&6R3>r6SUl2G^1;KzDq& zXw(;dYZns7Dzl_Wj~_dl#`DBn_GPs)YH@7Sa1D{hy9LM-)f|g28r^UlV})(J$u9s% zIb0f*QUNvED2b0>I$y5~UV|!LCs?K7x=ty-iFmw8zRm{wMhlKn zu_VBA6+Alc8hPZ4u=6=T7X`=7F*ivYy<0M>?7sD z%S1WTH$k*(0x?E==QIUDlJ&j_EbZ1HB+W@9DN>;wJr?BVZ$Yv5(wte5=jAohcH{0*oZg=E_y+MJi) zftPlCkB`ER<1CZx$0Z2pm;SupCt)Xbw3YlH!P8%sLL~m4`Fo%BzSNPffZ(g<3Gvy3 z&2qm4$Z5mGGgobgp!?T Nu$x8UUr1%h?mq}<`*{EW diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin deleted file mode 100755 index 1f893f66cb6e585cdf4f0e709db8d25249c8967a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6036 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 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake deleted file mode 100644 index 72a079f..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake +++ /dev/null @@ -1,15 +0,0 @@ -set(CMAKE_HOST_SYSTEM "Darwin-24.3.0") -set(CMAKE_HOST_SYSTEM_NAME "Darwin") -set(CMAKE_HOST_SYSTEM_VERSION "24.3.0") -set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64") - -include("/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake") - -set(CMAKE_SYSTEM "Android-1") -set(CMAKE_SYSTEM_NAME "Android") -set(CMAKE_SYSTEM_VERSION "1") -set(CMAKE_SYSTEM_PROCESSOR "armv7-a") - -set(CMAKE_CROSSCOMPILING "TRUE") - -set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c deleted file mode 100644 index 41b99d7..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c +++ /dev/null @@ -1,803 +0,0 @@ -#ifdef __cplusplus -# error "A C++ compiler has been selected for C." -#endif - -#if defined(__18CXX) -# define ID_VOID_MAIN -#endif -#if defined(__CLASSIC_C__) -/* cv-qualifiers did not exist in K&R C */ -# define const -# define volatile -#endif - -#if !defined(__has_include) -/* If the compiler does not have __has_include, pretend the answer is - always no. */ -# define __has_include(x) 0 -#endif - - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# if defined(__GNUC__) -# define SIMULATE_ID "GNU" -# endif - /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, - except that a few beta releases use the old format with V=2021. */ -# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# if defined(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# else -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# endif -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) - /* The third version component from --version is an update index, - but no macro is provided for it. */ -# define COMPILER_VERSION_PATCH DEC(0) -# endif -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -# elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) -# define COMPILER_ID "IntelLLVM" -#if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -#endif -#if defined(__GNUC__) -# define SIMULATE_ID "GNU" -#endif -/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and - * later. Look for 6 digit vs. 8 digit version number to decide encoding. - * VVVV is no smaller than the current year when a version is released. - */ -#if __INTEL_LLVM_COMPILER < 1000000L -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) -#else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) -#endif -#if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -#endif -#if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -#elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -#endif -#if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -#endif -#if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -#endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__WATCOMC__) -# define COMPILER_ID "OpenWatcom" - /* __WATCOMC__ = VVRP + 1100 */ -# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__SUNPRO_C) -# define COMPILER_ID "SunPro" -# if __SUNPRO_C >= 0x5100 - /* __SUNPRO_C = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# endif - -#elif defined(__HP_cc) -# define COMPILER_ID "HP" - /* __HP_cc = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) - -#elif defined(__DECC) -# define COMPILER_ID "Compaq" - /* __DECC_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) - -#elif defined(__IBMC__) && defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__ibmxl__) && defined(__clang__) -# define COMPILER_ID "XLClang" -# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) -# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) -# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) - - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 -# define COMPILER_ID "XL" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 -# define COMPILER_ID "VisualAge" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__NVCOMPILER) -# define COMPILER_ID "NVHPC" -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__CLANG_FUJITSU) -# define COMPILER_ID "FujitsuClang" -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# define COMPILER_VERSION_INTERNAL_STR __clang_version__ - - -#elif defined(__FUJITSU) -# define COMPILER_ID "Fujitsu" -# if defined(__FCC_version__) -# define COMPILER_VERSION __FCC_version__ -# elif defined(__FCC_major__) -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# endif -# if defined(__fcc_version) -# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) -# elif defined(__FCC_VERSION) -# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) -# endif - - -#elif defined(__ghs__) -# define COMPILER_ID "GHS" -/* __GHS_VERSION_NUMBER = VVVVRP */ -# ifdef __GHS_VERSION_NUMBER -# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) -# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) -# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) -# endif - -#elif defined(__TINYC__) -# define COMPILER_ID "TinyCC" - -#elif defined(__BCC__) -# define COMPILER_ID "Bruce" - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__ARMCC_VERSION) && !defined(__clang__) -# define COMPILER_ID "ARMCC" -#if __ARMCC_VERSION >= 1000000 - /* __ARMCC_VERSION = VRRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#else - /* __ARMCC_VERSION = VRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#endif - - -#elif defined(__clang__) && defined(__apple_build_version__) -# define COMPILER_ID "AppleClang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) - -#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) -# define COMPILER_ID "ARMClang" - # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) -# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif - -#elif defined(__GNUC__) -# define COMPILER_ID "GNU" -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# if defined(__GNUC_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" -#if defined(__VISUALDSPVERSION__) - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) -#endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" -# if defined(__VER__) && defined(__ICCARM__) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) -# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) -# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) -# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) -# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# endif - -#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) -# define COMPILER_ID "SDCC" -# if defined(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) -# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) -# else - /* SDCC = VRP */ -# define COMPILER_VERSION_MAJOR DEC(SDCC/100) -# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) -# define COMPILER_VERSION_PATCH DEC(SDCC % 10) -# endif - - -/* These compilers are either not known or too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; -#ifdef SIMULATE_ID -char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; -#endif - -#ifdef __QNXNTO__ -char const* qnxnto = "INFO" ":" "qnxnto[]"; -#endif - -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) -char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; -#endif - -#define STRINGIFY_HELPER(X) #X -#define STRINGIFY(X) STRINGIFY_HELPER(X) - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__MSYS__) -# define PLATFORM_ID "MSYS" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#elif defined(__WATCOMC__) -# if defined(__LINUX__) -# define PLATFORM_ID "Linux" - -# elif defined(__DOS__) -# define PLATFORM_ID "DOS" - -# elif defined(__OS2__) -# define PLATFORM_ID "OS2" - -# elif defined(__WINDOWS__) -# define PLATFORM_ID "Windows3x" - -# elif defined(__VXWORKS__) -# define PLATFORM_ID "VxWorks" - -# else /* unknown platform */ -# define PLATFORM_ID -# endif - -#elif defined(__INTEGRITY) -# if defined(INT_178B) -# define PLATFORM_ID "Integrity178" - -# else /* regular Integrity */ -# define PLATFORM_ID "Integrity" -# endif - -#else /* unknown platform */ -# define PLATFORM_ID - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_ARM64EC) -# define ARCHITECTURE_ID "ARM64EC" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM64) -# define ARCHITECTURE_ID "ARM64" - -# elif defined(_M_ARM) -# if _M_ARM == 4 -# define ARCHITECTURE_ID "ARMV4I" -# elif _M_ARM == 5 -# define ARCHITECTURE_ID "ARMV5I" -# else -# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) -# endif - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__WATCOMC__) -# if defined(_M_I86) -# define ARCHITECTURE_ID "I86" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# if defined(__ICCARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__ICCRX__) -# define ARCHITECTURE_ID "RX" - -# elif defined(__ICCRH850__) -# define ARCHITECTURE_ID "RH850" - -# elif defined(__ICCRL78__) -# define ARCHITECTURE_ID "RL78" - -# elif defined(__ICCRISCV__) -# define ARCHITECTURE_ID "RISCV" - -# elif defined(__ICCAVR__) -# define ARCHITECTURE_ID "AVR" - -# elif defined(__ICC430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__ICCV850__) -# define ARCHITECTURE_ID "V850" - -# elif defined(__ICC8051__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__ICCSTM8__) -# define ARCHITECTURE_ID "STM8" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__ghs__) -# if defined(__PPC64__) -# define ARCHITECTURE_ID "PPC64" - -# elif defined(__ppc__) -# define ARCHITECTURE_ID "PPC" - -# elif defined(__ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__x86_64__) -# define ARCHITECTURE_ID "x64" - -# elif defined(__i386__) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__TI_COMPILER_VERSION__) -# if defined(__TI_ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__MSP430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__TMS320C28XX__) -# define ARCHITECTURE_ID "TMS320C28x" - -# elif defined(__TMS320C6X__) || defined(_TMS320C6X) -# define ARCHITECTURE_ID "TMS320C6x" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number. */ -#ifdef COMPILER_VERSION -char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; - -/* Construct a string literal encoding the version number components. */ -#elif defined(COMPILER_VERSION_MAJOR) -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct a string literal encoding the internal version number. */ -#ifdef COMPILER_VERSION_INTERNAL -char const info_version_internal[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', - 'i','n','t','e','r','n','a','l','[', - COMPILER_VERSION_INTERNAL,']','\0'}; -#elif defined(COMPILER_VERSION_INTERNAL_STR) -char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; -#endif - -/* Construct a string literal encoding the version number components. */ -#ifdef SIMULATE_VERSION_MAJOR -char const info_simulate_version[] = { - 'I', 'N', 'F', 'O', ':', - 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', - SIMULATE_VERSION_MAJOR, -# ifdef SIMULATE_VERSION_MINOR - '.', SIMULATE_VERSION_MINOR, -# ifdef SIMULATE_VERSION_PATCH - '.', SIMULATE_VERSION_PATCH, -# ifdef SIMULATE_VERSION_TWEAK - '.', SIMULATE_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -#if !defined(__STDC__) && !defined(__clang__) -# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) -# define C_VERSION "90" -# else -# define C_VERSION -# endif -#elif __STDC_VERSION__ > 201710L -# define C_VERSION "23" -#elif __STDC_VERSION__ >= 201710L -# define C_VERSION "17" -#elif __STDC_VERSION__ >= 201000L -# define C_VERSION "11" -#elif __STDC_VERSION__ >= 199901L -# define C_VERSION "99" -#else -# define C_VERSION "90" -#endif -const char* info_language_standard_default = - "INFO" ":" "standard_default[" C_VERSION "]"; - -const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ -#if (defined(__clang__) || defined(__GNUC__) || \ - defined(__TI_COMPILER_VERSION__)) && \ - !defined(__STRICT_ANSI__) && !defined(_MSC_VER) - "ON" -#else - "OFF" -#endif -"]"; - -/*--------------------------------------------------------------------------*/ - -#ifdef ID_VOID_MAIN -void main() {} -#else -# if defined(__CLASSIC_C__) -int main(argc, argv) int argc; char *argv[]; -# else -int main(int argc, char* argv[]) -# endif -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; - require += info_arch[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif -#ifdef COMPILER_VERSION_INTERNAL - require += info_version_internal[argc]; -#endif -#ifdef SIMULATE_ID - require += info_simulate[argc]; -#endif -#ifdef SIMULATE_VERSION_MAJOR - require += info_simulate_version[argc]; -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - require += info_cray[argc]; -#endif - require += info_language_standard_default[argc]; - require += info_language_extensions_default[argc]; - (void)argv; - return require; -} -#endif diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o deleted file mode 100644 index c4b399f47492347c701418e5762a811923832d9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4148 zcmdT{U5p#m6+ScLv7PnC`$xzx)I}j(Xgy?iyN64E6<8+yrhJBG5+x; zG4feY{1wQsdXYY7F%dYE{x=AEBz^%TKF@#)P1|#8c4{)4nV!yNasJd>o z?zG*GS9T0sAJcc;dU@5VHO+c`t&whd?pdeor|h}P>|7;pXJ=++rtIlVHs?&2GjsX5 z>B>}TD&v%$DLXecle>c!k6P!P#YJ%wmu;g==BYOBhk3SRHO&*Admeyp+qCRz2e&T0 z>NcEo!)jVp$CG)PR;y(i#Q-#dztTk(HgkL1A#-n0!;pEAMhl=+v|MGD0frm~UE*7cQthhy4GJ2BOuAU$Z zM^EC4(c^eyJIJ;;SU3jE->)9jz{bMMC(Emrc~~RQd8AYGaOD4AANayuIIR{x6;iTb z7js5tj-o@cg}Aas9nyxCB#kJe%9uJHxk=eZ+qE6aPGy&Ro3amweH1gkMT?-^C>N5$ zTOqSfHojK}lcV%1Xe6kfcw7B1xs^aLozRu*ow;DXt}@Y{jw*U==q){I>U*LUJ!$9( zLr+Gl1JaJZZFh7PcDTVgswFFWx^LoXW?veDqZUmV+9&5LsMw+RXb>O6aZXaS2>tV0 z$urgPdopBajR)E9I|cP6B*pqXGa8|Chnhw=ha|S|8j$zU7tnA>-q&$>yd*rh*pE@1 zzS$%vXs^hxXWvS13p>Am$58t2-{e1nuZLdi`Hux_(eRe)Lahz=D!qn>e2L{G(GyHZ zh@N699{iobV?)8#p+x&3igzZd7ywNwwr5;W-U)RJ1v|j{TUiEfhAD6tgdcxTu>H88 zrrOL8eg&al67-aywxEv)iq8X5<3xLy@;pJwu(@Iuty0Nz*2wTtg@`MA!$H|GJg08h zmTwtB@#|Nz>y)Y+xqh$c84D+m8kX;SwNl4-+A@K*?+u3Q*V-O-kSFH>KX)T3S%U*7 z#&)_jyBjRT2jp_ZWZ8TlqF^(KNl}5_tbA!nQ^*oeFz1DPuPmox}vl`Cz zDvN=Y`BsUH_W1_Wy|$60z#J#@32kl2T{yGZZ^bc`v`RheC$>R6~cbCsRx865- zkLQu^9Jha<^PI3B-*?%h-)B%D6wM368Js6ho9_ze!+ucFU(kWqdK{G7yXdT!IZM0` zpbO(&h7Qvo z;29U!C1|q{WDcxg8@K$3iWvMShy6H@?*RE!T(|%L diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp deleted file mode 100644 index 25c62a8..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp +++ /dev/null @@ -1,791 +0,0 @@ -/* This source file must have a .cpp extension so that all C++ compilers - recognize the extension without flags. Borland does not know .cxx for - example. */ -#ifndef __cplusplus -# error "A C compiler has been selected for C++." -#endif - -#if !defined(__has_include) -/* If the compiler does not have __has_include, pretend the answer is - always no. */ -# define __has_include(x) 0 -#endif - - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__COMO__) -# define COMPILER_ID "Comeau" - /* __COMO_VERSION__ = VRR */ -# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) -# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) - -#elif defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# if defined(__GNUC__) -# define SIMULATE_ID "GNU" -# endif - /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, - except that a few beta releases use the old format with V=2021. */ -# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# if defined(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# else -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# endif -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) - /* The third version component from --version is an update index, - but no macro is provided for it. */ -# define COMPILER_VERSION_PATCH DEC(0) -# endif -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -# elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) -# define COMPILER_ID "IntelLLVM" -#if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -#endif -#if defined(__GNUC__) -# define SIMULATE_ID "GNU" -#endif -/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and - * later. Look for 6 digit vs. 8 digit version number to decide encoding. - * VVVV is no smaller than the current year when a version is released. - */ -#if __INTEL_LLVM_COMPILER < 1000000L -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) -#else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) -#endif -#if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -#endif -#if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -#elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -#endif -#if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -#endif -#if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -#endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__WATCOMC__) -# define COMPILER_ID "OpenWatcom" - /* __WATCOMC__ = VVRP + 1100 */ -# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__SUNPRO_CC) -# define COMPILER_ID "SunPro" -# if __SUNPRO_CC >= 0x5100 - /* __SUNPRO_CC = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# endif - -#elif defined(__HP_aCC) -# define COMPILER_ID "HP" - /* __HP_aCC = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) - -#elif defined(__DECCXX) -# define COMPILER_ID "Compaq" - /* __DECCXX_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) - -#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__ibmxl__) && defined(__clang__) -# define COMPILER_ID "XLClang" -# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) -# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) -# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) - - -#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 -# define COMPILER_ID "XL" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 -# define COMPILER_ID "VisualAge" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__NVCOMPILER) -# define COMPILER_ID "NVHPC" -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__CLANG_FUJITSU) -# define COMPILER_ID "FujitsuClang" -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# define COMPILER_VERSION_INTERNAL_STR __clang_version__ - - -#elif defined(__FUJITSU) -# define COMPILER_ID "Fujitsu" -# if defined(__FCC_version__) -# define COMPILER_VERSION __FCC_version__ -# elif defined(__FCC_major__) -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# endif -# if defined(__fcc_version) -# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) -# elif defined(__FCC_VERSION) -# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) -# endif - - -#elif defined(__ghs__) -# define COMPILER_ID "GHS" -/* __GHS_VERSION_NUMBER = VVVVRP */ -# ifdef __GHS_VERSION_NUMBER -# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) -# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) -# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) -# endif - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__ARMCC_VERSION) && !defined(__clang__) -# define COMPILER_ID "ARMCC" -#if __ARMCC_VERSION >= 1000000 - /* __ARMCC_VERSION = VRRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#else - /* __ARMCC_VERSION = VRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#endif - - -#elif defined(__clang__) && defined(__apple_build_version__) -# define COMPILER_ID "AppleClang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) - -#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) -# define COMPILER_ID "ARMClang" - # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) -# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif - -#elif defined(__GNUC__) || defined(__GNUG__) -# define COMPILER_ID "GNU" -# if defined(__GNUC__) -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# else -# define COMPILER_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" -#if defined(__VISUALDSPVERSION__) - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) -#endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" -# if defined(__VER__) && defined(__ICCARM__) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) -# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) -# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) -# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) -# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# endif - - -/* These compilers are either not known or too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; -#ifdef SIMULATE_ID -char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; -#endif - -#ifdef __QNXNTO__ -char const* qnxnto = "INFO" ":" "qnxnto[]"; -#endif - -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) -char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; -#endif - -#define STRINGIFY_HELPER(X) #X -#define STRINGIFY(X) STRINGIFY_HELPER(X) - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__MSYS__) -# define PLATFORM_ID "MSYS" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#elif defined(__WATCOMC__) -# if defined(__LINUX__) -# define PLATFORM_ID "Linux" - -# elif defined(__DOS__) -# define PLATFORM_ID "DOS" - -# elif defined(__OS2__) -# define PLATFORM_ID "OS2" - -# elif defined(__WINDOWS__) -# define PLATFORM_ID "Windows3x" - -# elif defined(__VXWORKS__) -# define PLATFORM_ID "VxWorks" - -# else /* unknown platform */ -# define PLATFORM_ID -# endif - -#elif defined(__INTEGRITY) -# if defined(INT_178B) -# define PLATFORM_ID "Integrity178" - -# else /* regular Integrity */ -# define PLATFORM_ID "Integrity" -# endif - -#else /* unknown platform */ -# define PLATFORM_ID - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_ARM64EC) -# define ARCHITECTURE_ID "ARM64EC" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM64) -# define ARCHITECTURE_ID "ARM64" - -# elif defined(_M_ARM) -# if _M_ARM == 4 -# define ARCHITECTURE_ID "ARMV4I" -# elif _M_ARM == 5 -# define ARCHITECTURE_ID "ARMV5I" -# else -# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) -# endif - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__WATCOMC__) -# if defined(_M_I86) -# define ARCHITECTURE_ID "I86" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# if defined(__ICCARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__ICCRX__) -# define ARCHITECTURE_ID "RX" - -# elif defined(__ICCRH850__) -# define ARCHITECTURE_ID "RH850" - -# elif defined(__ICCRL78__) -# define ARCHITECTURE_ID "RL78" - -# elif defined(__ICCRISCV__) -# define ARCHITECTURE_ID "RISCV" - -# elif defined(__ICCAVR__) -# define ARCHITECTURE_ID "AVR" - -# elif defined(__ICC430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__ICCV850__) -# define ARCHITECTURE_ID "V850" - -# elif defined(__ICC8051__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__ICCSTM8__) -# define ARCHITECTURE_ID "STM8" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__ghs__) -# if defined(__PPC64__) -# define ARCHITECTURE_ID "PPC64" - -# elif defined(__ppc__) -# define ARCHITECTURE_ID "PPC" - -# elif defined(__ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__x86_64__) -# define ARCHITECTURE_ID "x64" - -# elif defined(__i386__) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__TI_COMPILER_VERSION__) -# if defined(__TI_ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__MSP430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__TMS320C28XX__) -# define ARCHITECTURE_ID "TMS320C28x" - -# elif defined(__TMS320C6X__) || defined(_TMS320C6X) -# define ARCHITECTURE_ID "TMS320C6x" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number. */ -#ifdef COMPILER_VERSION -char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; - -/* Construct a string literal encoding the version number components. */ -#elif defined(COMPILER_VERSION_MAJOR) -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct a string literal encoding the internal version number. */ -#ifdef COMPILER_VERSION_INTERNAL -char const info_version_internal[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', - 'i','n','t','e','r','n','a','l','[', - COMPILER_VERSION_INTERNAL,']','\0'}; -#elif defined(COMPILER_VERSION_INTERNAL_STR) -char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; -#endif - -/* Construct a string literal encoding the version number components. */ -#ifdef SIMULATE_VERSION_MAJOR -char const info_simulate_version[] = { - 'I', 'N', 'F', 'O', ':', - 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', - SIMULATE_VERSION_MAJOR, -# ifdef SIMULATE_VERSION_MINOR - '.', SIMULATE_VERSION_MINOR, -# ifdef SIMULATE_VERSION_PATCH - '.', SIMULATE_VERSION_PATCH, -# ifdef SIMULATE_VERSION_TWEAK - '.', SIMULATE_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L -# if defined(__INTEL_CXX11_MODE__) -# if defined(__cpp_aggregate_nsdmi) -# define CXX_STD 201402L -# else -# define CXX_STD 201103L -# endif -# else -# define CXX_STD 199711L -# endif -#elif defined(_MSC_VER) && defined(_MSVC_LANG) -# define CXX_STD _MSVC_LANG -#else -# define CXX_STD __cplusplus -#endif - -const char* info_language_standard_default = "INFO" ":" "standard_default[" -#if CXX_STD > 202002L - "23" -#elif CXX_STD > 201703L - "20" -#elif CXX_STD >= 201703L - "17" -#elif CXX_STD >= 201402L - "14" -#elif CXX_STD >= 201103L - "11" -#else - "98" -#endif -"]"; - -const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ -#if (defined(__clang__) || defined(__GNUC__) || \ - defined(__TI_COMPILER_VERSION__)) && \ - !defined(__STRICT_ANSI__) && !defined(_MSC_VER) - "ON" -#else - "OFF" -#endif -"]"; - -/*--------------------------------------------------------------------------*/ - -int main(int argc, char* argv[]) -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif -#ifdef COMPILER_VERSION_INTERNAL - require += info_version_internal[argc]; -#endif -#ifdef SIMULATE_ID - require += info_simulate[argc]; -#endif -#ifdef SIMULATE_VERSION_MAJOR - require += info_simulate_version[argc]; -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - require += info_cray[argc]; -#endif - require += info_language_standard_default[argc]; - require += info_language_extensions_default[argc]; - (void)argv; - return require; -} diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o deleted file mode 100644 index ec6bab69ee4d78ac0747a374e943316816171846..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4184 zcmdT{O>7&-6@I(Rr6^KfOS0W4j?prP8z^bCOH!05*+nWR0=X6FAqa8^5+KQ;mmqMyH=LoC zbXD})5oW)6?|t*;&EFg9r>9P@Ynn!?Xf#W^64CXHu$V;wv-B-kZ`{?_DQn!+f2qAj zHxK<_=Ok_EcUE7Z+o_Xub9zM9?^w_%>%@q4d_<<(iMySr>96N8-bvI&R2%guDwn%= zjq4j{*UufV2CYt`>4%$ZO}AaYLPFVTx=}3%TbrjF?cR=5x?y!|Q?|R2+xFbhD|>#; z?KPv#d`VjToyc!@8$r7}u$?=5MT~g}-zQKx7LIFZ{PMORa<|Q#DEX4zZ{%{SQMf|d zl=f}wfN5Bh4?SW{Y12s}y+|7ej%QAo`V5hwX&VQK5|2Vx!it-Zp+S^9MuzoNCIihF zH#3>1&`cH4+&J*PhgI+K{eqqD>-*ZaMU=5I?sRfx#;{n)U5F-3(gzBneZ?V>Ucu%k zFh_jFF?f{zBqXB0OWXk>cp~kFW*V$CR`5xj#^(^3rvS-w=$q2UE;5Xzwg5iVgAU^> zkorFUrke(@Z)#hSSOW#=xAD>5gT!lZtl%TYn4r`R#bqn>q`!lY_5mc`qh0P{O8s1M z*($i7G4~5dyqCM&Bb54s;Gz;HhN}HWYW@kqSb<5zQXuRH5ig1M+^5XDuSb9h z{pHlZhs4B}eeoxNefrA?8D!01G9|yj*G!CG2aNOj(Q4ZZgNB!#&F2;t3c144liBZd z>H)r$pcw(05rnx`lXVrh>wDRtoehgirBbovJ)W)doyf|QndLKS7qYWkQPk-kcN|;+ z_HNgMpx*SmK`*TOHtv%X1wpgAx99Jel^N^%eAHDTG7idE-ub{3%Pv3 zU#RAmi^~hO`O19Guln;|VScgjIIW#=ulj4xKffj~=Z0rjI~{VK?c$O+FZSHFb3P2N z!D-NST(924Rh-)jTK-(iZM$_pRIxd3r{mbwogL?-U+LAIVt28$*qN_7ZrJkON@H%j zSnnFg*59X0RL2d?>FQ3jA#JEb+!h(YnksH>l{Mn|^ z|8cJo;?DfP9)#5sIK?jS6lr-h*9vxSnUd+T)s!}_r;Q2CqW#*WHlkXfe+U$^gDlXM4|5U&GXurIBBxKQFH!!^?OI*P)F ziOYv;eBac}vGiX|%Q256Yo=wJ8QZjy^_cWXatj(5U``rV&72z|Is+*UqLIwl#>dxc z`awh@1{(gn9upJv`Tdwk2L66A)X5;u72bek(EGAo0BSTnuyDhmu@QOHj`t*14Ejb) z;{Jz6cv}MNc6MGmev3DMp^Lj)cuKW%-+o@S9^qr*)}6 zBk`g{ml1JtJj}Z$^{+A_?pspN`^$d+$T&sxw$%Sa>i@-vd3_@FUrBu$>!M?x`x(*y z2qU&LE9E>R;yfYcA46MD*ONHIe$(*7$o(Xe?Qt?KyOm1lZ<8G%R}m-vmXGXX zhkn!c+{m>>b{gcn|B%r3qCSus?bQosY&VL+Mx__|T@^q#3P*<=&p9UU&UcXa?RF6P_S0vdox^mhS4RUCFG4JuW~1#( zj)<-nx-BR$#mKDyueBJDd3JsfGi-T?$0D0g-v3svVsFJy5=s9A`+W;KRa6tl3%LQm zDWsvO2om`&axp*}<#AqBMe#UEVJKRWhL>=!_+Inf;dqz_6@82ff1Ou=T;4=wy^2}+ z`v|(Yzu$wzJobmHKk#>5#>csi%Uh_NA5`JkxxOY*jgy5^jm2Em{u$cwao>!M%j2tg zOv`bVKmPHje8l}((8v9~74wIyH}H3S#NX^5{uW34-HZ9-Jf`B~+yv@iU7y^;-v&7G z_}+>6L&_TXJ38Vow}(I8pSZtwWBxcrtN7lP{*ZP=DZ-!HLsoF?To_fGIeZJ=6zQQK*jsfh`(Fl&Bl1@EM5k0Xuc45A9%j} wzNz`19r1S${(c+tr^e+sCGPJ-2)u;skKYmHuM1vmx#$J?PO%?#PC1UR0n?*oDgXcg diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/TargetDirectories.txt deleted file mode 100644 index ca4b484..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/TargetDirectories.txt +++ /dev/null @@ -1,2 +0,0 @@ -/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/edit_cache.dir -/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/cmake.check_cache deleted file mode 100644 index 3dccd73..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/cmake.check_cache +++ /dev/null @@ -1 +0,0 @@ -# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rules.ninja b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rules.ninja deleted file mode 100644 index 6a55d4f..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/CMakeFiles/rules.ninja +++ /dev/null @@ -1,45 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Ninja" Generator, CMake Version 3.22 - -# This file contains all the rules used to get the outputs files -# built from the input files. -# It is included in the main 'build.ninja'. - -# ============================================================================= -# Project: Project -# Configurations: Debug -# ============================================================================= -# ============================================================================= - -############################################# -# Rule for running custom commands. - -rule CUSTOM_COMMAND - command = $COMMAND - description = $DESC - - -############################################# -# Rule for re-running cmake. - -rule RERUN_CMAKE - command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a - description = Re-running CMake... - generator = 1 - - -############################################# -# Rule for cleaning all built files. - -rule CLEAN - command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja $FILE_ARG -t clean $TARGETS - description = Cleaning all built files... - - -############################################# -# Rule for printing all primary targets available. - -rule HELP - command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja -t targets - description = All primary targets available: - diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/additional_project_files.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/additional_project_files.txt deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json deleted file mode 100644 index f074409..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "buildFiles": [ - "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" - ], - "cleanCommandsComponents": [ - [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", - "clean" - ] - ], - "buildTargetsCommandComponents": [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", - "{LIST_OF_TARGETS_TO_BUILD}" - ], - "libraries": {}, - "toolchains": { - "toolchain": { - "cCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang.lld", - "cppCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++.lld" - } - }, - "cFileExtensions": [], - "cppFileExtensions": [] -} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json deleted file mode 100644 index c404902..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "buildFiles": [ - "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" - ], - "cleanCommandsComponents": [ - [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", - "clean" - ] - ], - "buildTargetsCommandComponents": [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a", - "{LIST_OF_TARGETS_TO_BUILD}" - ], - "libraries": {} -} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja deleted file mode 100644 index cda47cd..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja +++ /dev/null @@ -1,112 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Ninja" Generator, CMake Version 3.22 - -# This file contains all the build statements describing the -# compilation DAG. - -# ============================================================================= -# Write statements declared in CMakeLists.txt: -# -# Which is the root file. -# ============================================================================= - -# ============================================================================= -# Project: Project -# Configurations: Debug -# ============================================================================= - -############################################# -# Minimal version of Ninja required by this file - -ninja_required_version = 1.5 - - -############################################# -# Set configuration variable for custom commands. - -CONFIGURATION = Debug -# ============================================================================= -# Include auxiliary files. - - -############################################# -# Include rules file. - -include CMakeFiles/rules.ninja - -# ============================================================================= - -############################################# -# Logical path to working directory; prefix for absolute paths. - -cmake_ninja_workdir = /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/ - -############################################# -# Utility command for edit_cache - -build CMakeFiles/edit_cache.util: CUSTOM_COMMAND - COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a - DESC = Running CMake cache editor... - pool = console - restat = 1 - -build edit_cache: phony CMakeFiles/edit_cache.util - - -############################################# -# Utility command for rebuild_cache - -build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND - COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a - DESC = Running CMake to regenerate build system... - pool = console - restat = 1 - -build rebuild_cache: phony CMakeFiles/rebuild_cache.util - -# ============================================================================= -# Target aliases. - -# ============================================================================= -# Folder targets. - -# ============================================================================= - -############################################# -# Folder: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a - -build all: phony - -# ============================================================================= -# Built-in targets - - -############################################# -# Re-run CMake if any of its inputs changed. - -build build.ninja: RERUN_CMAKE | /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake - pool = console - - -############################################# -# A missing CMake input file is not an error. - -build /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake: phony - - -############################################# -# Clean all the built files. - -build clean: CLEAN - - -############################################# -# Print all primary targets available. - -build help: HELP - - -############################################# -# Make the all target the default. - -default all diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt deleted file mode 100644 index ec6a72a..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt +++ /dev/null @@ -1 +0,0 @@ -/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/cmake_install.cmake b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/cmake_install.cmake deleted file mode 100644 index 05e628b..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/cmake_install.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# Install script for directory: /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy - -# Set the install prefix -if(NOT DEFINED CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local") -endif() -string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - if(BUILD_TYPE) - string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - else() - set(CMAKE_INSTALL_CONFIG_NAME "Debug") - endif() - message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -endif() - -# Set the component getting installed. -if(NOT CMAKE_INSTALL_COMPONENT) - if(COMPONENT) - message(STATUS "Install component: \"${COMPONENT}\"") - set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - else() - set(CMAKE_INSTALL_COMPONENT) - endif() -endif() - -# Install shared libraries without execute permission? -if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) - set(CMAKE_INSTALL_SO_NO_EXE "0") -endif() - -# Is this installation the result of a crosscompile? -if(NOT DEFINED CMAKE_CROSSCOMPILING) - set(CMAKE_CROSSCOMPILING "TRUE") -endif() - -# Set default install directory permissions. -if(NOT DEFINED CMAKE_OBJDUMP) - set(CMAKE_OBJDUMP "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump") -endif() - -if(CMAKE_INSTALL_COMPONENT) - set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") -else() - set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") -endif() - -string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT - "${CMAKE_INSTALL_MANIFEST_FILES}") -file(WRITE "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/${CMAKE_INSTALL_MANIFEST}" - "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin deleted file mode 100644 index 00da33a..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/configure_fingerprint.bin +++ /dev/null @@ -1,28 +0,0 @@ -C/C++ Structured Logw -u -s/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/additional_project_files.txtC -A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ¼»ã×2  º»ã×2t -r -p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build.json  ¼»ã×2Ó »»ã×2y -w -u/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/android_gradle_build_mini.json  ¼»ã×2Þ »»ã×2f -d -b/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja  ¼»ã×2 Ä ±»ã×2j -h -f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build.ninja.txt  ¼»ã×2o -m -k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/build_file_index.txt  ¼»ã×2 P ¼»ã×2p -n -l/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/compile_commands.json  ¼»ã×2t -r -p/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/compile_commands.json.bin  ¼»ã×2 z -x -v/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt  ¼»ã×2 -È »»ã×2m -k -i/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json  ¼»ã×2  ( »»ã×2r -p -n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt  ¼»ã×2  e ¼»ã×2T -R -P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  ¼»ã×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt deleted file mode 100644 index b418b0d..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/metadata_generation_command.txt +++ /dev/null @@ -1,20 +0,0 @@ - -H/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy --DCMAKE_SYSTEM_NAME=Android --DCMAKE_EXPORT_COMPILE_COMMANDS=ON --DCMAKE_SYSTEM_VERSION=26 --DANDROID_PLATFORM=android-26 --DANDROID_ABI=armeabi-v7a --DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a --DANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 --DCMAKE_ANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 --DCMAKE_TOOLCHAIN_FILE=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake --DCMAKE_MAKE_PROGRAM=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja --DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a --DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a --DCMAKE_BUILD_TYPE=Debug --B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/armeabi-v7a --GNinja --Wno-dev ---no-warn-unused-cli - Build command args: [] - Version: 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json deleted file mode 100644 index e799de8..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/prefab_config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "enabled": false, - "packages": [] -} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt b/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt deleted file mode 100644 index ac80ab6..0000000 --- a/android/app/.cxx/Debug/4s676p3c/armeabi-v7a/symbol_folder_index.txt +++ /dev/null @@ -1 +0,0 @@ -/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/armeabi-v7a \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/hash_key.txt b/android/app/.cxx/Debug/4s676p3c/hash_key.txt deleted file mode 100644 index aff771b..0000000 --- a/android/app/.cxx/Debug/4s676p3c/hash_key.txt +++ /dev/null @@ -1,27 +0,0 @@ -# Values used to calculate the hash in this folder name. -# Should not depend on the absolute path of the project itself. -# - AGP: 8.6.0. -# - $NDK is the path to NDK 26.1.10909125. -# - $PROJECT is the path to the parent folder of the root Gradle build file. -# - $ABI is the ABI to be built with. The specific value doesn't contribute to the value of the hash. -# - $HASH is the hash value computed from this text. -# - $CMAKE is the path to CMake 3.22.1. -# - $NINJA is the path to Ninja. --H/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy --DCMAKE_SYSTEM_NAME=Android --DCMAKE_EXPORT_COMPILE_COMMANDS=ON --DCMAKE_SYSTEM_VERSION=26 --DANDROID_PLATFORM=android-26 --DANDROID_ABI=$ABI --DCMAKE_ANDROID_ARCH_ABI=$ABI --DANDROID_NDK=$NDK --DCMAKE_ANDROID_NDK=$NDK --DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake --DCMAKE_MAKE_PROGRAM=$NINJA --DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/$HASH/obj/$ABI --DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/$HASH/obj/$ABI --DCMAKE_BUILD_TYPE=Debug --B$PROJECT/app/.cxx/Debug/$HASH/$ABI --GNinja --Wno-dev ---no-warn-unused-cli \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cache-v2 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/cmakeFiles-v1 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/query/client-agp/codemodel-v2 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cache-v2-920dacdb871097de2130.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cache-v2-920dacdb871097de2130.json deleted file mode 100644 index 04a71c8..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cache-v2-920dacdb871097de2130.json +++ /dev/null @@ -1,1391 +0,0 @@ -{ - "entries" : - [ - { - "name" : "ANDROID_ABI", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "x86" - }, - { - "name" : "ANDROID_NDK", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" - }, - { - "name" : "ANDROID_PLATFORM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "android-26" - }, - { - "name" : "CMAKE_ADDR2LINE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line" - }, - { - "name" : "CMAKE_ANDROID_ARCH_ABI", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "x86" - }, - { - "name" : "CMAKE_ANDROID_NDK", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" - }, - { - "name" : "CMAKE_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_ASM_FLAGS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_ASM_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_ASM_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_BUILD_TYPE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." - } - ], - "type" : "STRING", - "value" : "Debug" - }, - { - "name" : "CMAKE_CACHEFILE_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "This is the directory where this CMakeCache.txt was created" - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86" - }, - { - "name" : "CMAKE_CACHE_MAJOR_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Major version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "3" - }, - { - "name" : "CMAKE_CACHE_MINOR_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Minor version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "22" - }, - { - "name" : "CMAKE_CACHE_PATCH_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Patch version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to CMake executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake" - }, - { - "name" : "CMAKE_CPACK_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to cpack program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack" - }, - { - "name" : "CMAKE_CTEST_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to ctest program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest" - }, - { - "name" : "CMAKE_CXX_COMPILER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "(This variable does not exist and should not be used)" - } - ], - "type" : "UNINITIALIZED", - "value" : "" - }, - { - "name" : "CMAKE_CXX_COMPILER_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "LLVM archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_CXX_COMPILER_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Generate index for LLVM archive" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_CXX_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the CXX compiler during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "-Os -DNDEBUG" - }, - { - "name" : "CMAKE_CXX_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "-O2 -g -DNDEBUG" - }, - { - "name" : "CMAKE_CXX_STANDARD_LIBRARIES", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Libraries linked by default with all C++ applications." - } - ], - "type" : "STRING", - "value" : "-latomic -lm" - }, - { - "name" : "CMAKE_C_COMPILER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "(This variable does not exist and should not be used)" - } - ], - "type" : "UNINITIALIZED", - "value" : "" - }, - { - "name" : "CMAKE_C_COMPILER_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "LLVM archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_C_COMPILER_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Generate index for LLVM archive" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_C_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the C compiler during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "-Os -DNDEBUG" - }, - { - "name" : "CMAKE_C_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "-O2 -g -DNDEBUG" - }, - { - "name" : "CMAKE_C_STANDARD_LIBRARIES", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Libraries linked by default with all C applications." - } - ], - "type" : "STRING", - "value" : "-latomic -lm" - }, - { - "name" : "CMAKE_DLLTOOL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "CMAKE_DLLTOOL-NOTFOUND" - }, - { - "name" : "CMAKE_EDIT_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to cache edit program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake" - }, - { - "name" : "CMAKE_ERROR_DEPRECATED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Whether to issue deprecation errors for macros and functions." - } - ], - "type" : "INTERNAL", - "value" : "FALSE" - }, - { - "name" : "CMAKE_EXECUTABLE_FORMAT", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Executable file format" - } - ], - "type" : "INTERNAL", - "value" : "ELF" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "ON" - }, - { - "name" : "CMAKE_EXTRA_GENERATOR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of external makefile project generator." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator." - } - ], - "type" : "INTERNAL", - "value" : "Ninja" - }, - { - "name" : "CMAKE_GENERATOR_INSTANCE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Generator instance identifier." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR_PLATFORM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator platform." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR_TOOLSET", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator toolset." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_HOME_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Source directory with the top level CMakeLists.txt file for this project" - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - { - "name" : "CMAKE_INSTALL_PREFIX", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Install path prefix, prepended onto install directories." - } - ], - "type" : "PATH", - "value" : "/usr/local" - }, - { - "name" : "CMAKE_INSTALL_SO_NO_EXE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Install .so files without execute permission." - } - ], - "type" : "INTERNAL", - "value" : "0" - }, - { - "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86" - }, - { - "name" : "CMAKE_LINKER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" - }, - { - "name" : "CMAKE_MAKE_PROGRAM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_NM", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm" - }, - { - "name" : "CMAKE_NUMBER_OF_MAKEFILES", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "number of local generators" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_OBJCOPY", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy" - }, - { - "name" : "CMAKE_OBJDUMP", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump" - }, - { - "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Platform information initialized" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_PROJECT_DESCRIPTION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "" - }, - { - "name" : "CMAKE_PROJECT_HOMEPAGE_URL", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "" - }, - { - "name" : "CMAKE_PROJECT_NAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "Project" - }, - { - "name" : "CMAKE_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Ranlib" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_READELF", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf" - }, - { - "name" : "CMAKE_ROOT", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to CMake installation." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" - }, - { - "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of dll's." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SKIP_INSTALL_RPATH", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." - } - ], - "type" : "BOOL", - "value" : "NO" - }, - { - "name" : "CMAKE_SKIP_RPATH", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If set, runtime paths are not added when using shared libraries." - } - ], - "type" : "BOOL", - "value" : "NO" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STRIP", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Strip" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip" - }, - { - "name" : "CMAKE_SUPPRESS_DEVELOPER_ERRORS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Suppress errors that are meant for the author of the CMakeLists.txt files." - } - ], - "type" : "INTERNAL", - "value" : "TRUE" - }, - { - "name" : "CMAKE_SUPPRESS_DEVELOPER_WARNINGS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Suppress Warnings that are meant for the author of the CMakeLists.txt files." - } - ], - "type" : "INTERNAL", - "value" : "TRUE" - }, - { - "name" : "CMAKE_SYSTEM_NAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "Android" - }, - { - "name" : "CMAKE_SYSTEM_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "26" - }, - { - "name" : "CMAKE_TOOLCHAIN_FILE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "The CMake toolchain file" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "name" : "CMAKE_UNAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "uname command" - } - ], - "type" : "INTERNAL", - "value" : "/usr/bin/uname" - }, - { - "name" : "CMAKE_VERBOSE_MAKEFILE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." - } - ], - "type" : "BOOL", - "value" : "FALSE" - }, - { - "name" : "CMAKE_WARN_DEPRECATED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Whether to issue warnings for deprecated functionality." - } - ], - "type" : "INTERNAL", - "value" : "FALSE" - }, - { - "name" : "Project_BINARY_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86" - }, - { - "name" : "Project_IS_TOP_LEVEL", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "ON" - }, - { - "name" : "Project_SOURCE_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - } - ], - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cmakeFiles-v1-f1661dab2653e3c04b8e.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cmakeFiles-v1-f1661dab2653e3c04b8e.json deleted file mode 100644 index 73685b0..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/cmakeFiles-v1-f1661dab2653e3c04b8e.json +++ /dev/null @@ -1,799 +0,0 @@ -{ - "inputs" : - [ - { - "path" : "CMakeLists.txt" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" - } - ], - "kind" : "cmakeFiles", - "paths" : - { - "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", - "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - "version" : - { - "major" : 1, - "minor" : 0 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/codemodel-v2-95b6204aa3712c2f8293.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/codemodel-v2-95b6204aa3712c2f8293.json deleted file mode 100644 index 996721e..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/codemodel-v2-95b6204aa3712c2f8293.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "configurations" : - [ - { - "directories" : - [ - { - "build" : ".", - "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", - "minimumCMakeVersion" : - { - "string" : "3.6.0" - }, - "projectIndex" : 0, - "source" : "." - } - ], - "name" : "Debug", - "projects" : - [ - { - "directoryIndexes" : - [ - 0 - ], - "name" : "Project" - } - ], - "targets" : [] - } - ], - "kind" : "codemodel", - "paths" : - { - "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", - "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - "version" : - { - "major" : 2, - "minor" : 3 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json deleted file mode 100644 index 3a67af9..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "backtraceGraph" : - { - "commands" : [], - "files" : [], - "nodes" : [] - }, - "installers" : [], - "paths" : - { - "build" : ".", - "source" : "." - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0179.json b/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0179.json deleted file mode 100644 index b8f0a1d..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0179.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "cmake" : - { - "generator" : - { - "multiConfig" : false, - "name" : "Ninja" - }, - "paths" : - { - "cmake" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake", - "cpack" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack", - "ctest" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest", - "root" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" - }, - "version" : - { - "isDirty" : false, - "major" : 3, - "minor" : 22, - "patch" : 1, - "string" : "3.22.1-g37088a8", - "suffix" : "g37088a8" - } - }, - "objects" : - [ - { - "jsonFile" : "codemodel-v2-95b6204aa3712c2f8293.json", - "kind" : "codemodel", - "version" : - { - "major" : 2, - "minor" : 3 - } - }, - { - "jsonFile" : "cache-v2-920dacdb871097de2130.json", - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } - }, - { - "jsonFile" : "cmakeFiles-v1-f1661dab2653e3c04b8e.json", - "kind" : "cmakeFiles", - "version" : - { - "major" : 1, - "minor" : 0 - } - } - ], - "reply" : - { - "client-agp" : - { - "cache-v2" : - { - "jsonFile" : "cache-v2-920dacdb871097de2130.json", - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } - }, - "cmakeFiles-v1" : - { - "jsonFile" : "cmakeFiles-v1-f1661dab2653e3c04b8e.json", - "kind" : "cmakeFiles", - "version" : - { - "major" : 1, - "minor" : 0 - } - }, - "codemodel-v2" : - { - "jsonFile" : "codemodel-v2-95b6204aa3712c2f8293.json", - "kind" : "codemodel", - "version" : - { - "major" : 2, - "minor" : 3 - } - } - } - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeCache.txt b/android/app/.cxx/Debug/4s676p3c/x86/CMakeCache.txt deleted file mode 100644 index 5de09a9..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/CMakeCache.txt +++ /dev/null @@ -1,405 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 -# It was generated by CMake: /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//No help, variable specified on the command line. -ANDROID_ABI:UNINITIALIZED=x86 - -//No help, variable specified on the command line. -ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 - -//No help, variable specified on the command line. -ANDROID_PLATFORM:UNINITIALIZED=android-26 - -//Path to a program. -CMAKE_ADDR2LINE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line - -//No help, variable specified on the command line. -CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=x86 - -//No help, variable specified on the command line. -CMAKE_ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 - -//Archiver -CMAKE_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Flags used by the compiler during all build types. -CMAKE_ASM_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_ASM_FLAGS_DEBUG:STRING= - -//Flags used by the compiler during release builds. -CMAKE_ASM_FLAGS_RELEASE:STRING= - -//Choose the type of build, options are: None Debug Release RelWithDebInfo -// MinSizeRel ... -CMAKE_BUILD_TYPE:STRING=Debug - -//LLVM archiver -CMAKE_CXX_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Generate index for LLVM archive -CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING= - -//Flags used by the CXX compiler during MINSIZEREL builds. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_CXX_FLAGS_RELEASE:STRING= - -//Flags used by the CXX compiler during RELWITHDEBINFO builds. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Libraries linked by default with all C++ applications. -CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm - -//LLVM archiver -CMAKE_C_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Generate index for LLVM archive -CMAKE_C_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING= - -//Flags used by the C compiler during MINSIZEREL builds. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_C_FLAGS_RELEASE:STRING= - -//Flags used by the C compiler during RELWITHDEBINFO builds. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Libraries linked by default with all C applications. -CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm - -//Path to a program. -CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING= - -//Flags used by the linker during DEBUG builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during MINSIZEREL builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during RELEASE builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during RELWITHDEBINFO builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//No help, variable specified on the command line. -CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//No help, variable specified on the command line. -CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 - -//Path to a program. -CMAKE_LINKER:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld - -//No help, variable specified on the command line. -CMAKE_MAKE_PROGRAM:UNINITIALIZED=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of modules during -// DEBUG builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of modules during -// MINSIZEREL builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of modules during -// RELEASE builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of modules during -// RELWITHDEBINFO builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump - -//Value Computed by CMake -CMAKE_PROJECT_DESCRIPTION:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_HOMEPAGE_URL:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=Project - -//Ranlib -CMAKE_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Path to a program. -CMAKE_READELF:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf - -//No help, variable specified on the command line. -CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of shared libraries -// during DEBUG builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of shared libraries -// during MINSIZEREL builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELEASE builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELWITHDEBINFO builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries -// during all build types. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of static libraries -// during DEBUG builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of static libraries -// during MINSIZEREL builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELEASE builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELWITHDEBINFO builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Strip -CMAKE_STRIP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip - -//No help, variable specified on the command line. -CMAKE_SYSTEM_NAME:UNINITIALIZED=Android - -//No help, variable specified on the command line. -CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 - -//The CMake toolchain file -CMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//Value Computed by CMake -Project_BINARY_DIR:STATIC=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 - -//Value Computed by CMake -Project_IS_TOP_LEVEL:STATIC=ON - -//Value Computed by CMake -Project_SOURCE_DIR:STATIC=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: CMAKE_ADDR2LINE -CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest -//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR -CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB -CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES -CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_AR -CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB -CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES -CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_DLLTOOL -CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 -//Path to cache edit program executable. -CMAKE_EDIT_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -//Whether to issue deprecation errors for macros and functions. -CMAKE_ERROR_DEPRECATED:INTERNAL=FALSE -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Ninja -//Generator instance identifier. -CMAKE_GENERATOR_INSTANCE:INTERNAL= -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -//Install .so files without execute permission. -CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_READELF -CMAKE_READELF-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//Suppress errors that are meant for the author of the CMakeLists.txt -// files. -CMAKE_SUPPRESS_DEVELOPER_ERRORS:INTERNAL=TRUE -//Suppress Warnings that are meant for the author of the CMakeLists.txt -// files. -CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=TRUE -//uname command -CMAKE_UNAME:INTERNAL=/usr/bin/uname -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Whether to issue warnings for deprecated functionality. -CMAKE_WARN_DEPRECATED:INTERNAL=FALSE - diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake deleted file mode 100644 index 53c7c7c..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake +++ /dev/null @@ -1,72 +0,0 @@ -set(CMAKE_C_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang") -set(CMAKE_C_COMPILER_ARG1 "") -set(CMAKE_C_COMPILER_ID "Clang") -set(CMAKE_C_COMPILER_VERSION "17.0.2") -set(CMAKE_C_COMPILER_VERSION_INTERNAL "") -set(CMAKE_C_COMPILER_WRAPPER "") -set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") -set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") -set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") -set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") -set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") -set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") -set(CMAKE_C17_COMPILE_FEATURES "c_std_17") -set(CMAKE_C23_COMPILE_FEATURES "c_std_23") - -set(CMAKE_C_PLATFORM_ID "Linux") -set(CMAKE_C_SIMULATE_ID "") -set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") -set(CMAKE_C_SIMULATE_VERSION "") - - - - -set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_C_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_C_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") -set(CMAKE_MT "") -set(CMAKE_COMPILER_IS_GNUCC ) -set(CMAKE_C_COMPILER_LOADED 1) -set(CMAKE_C_COMPILER_WORKS TRUE) -set(CMAKE_C_ABI_COMPILED TRUE) - -set(CMAKE_C_COMPILER_ENV_VAR "CC") - -set(CMAKE_C_COMPILER_ID_RUN 1) -set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) -set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) -set(CMAKE_C_LINKER_PREFERENCE 10) - -# Save compiler ABI information. -set(CMAKE_C_SIZEOF_DATA_PTR "4") -set(CMAKE_C_COMPILER_ABI "ELF") -set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") -set(CMAKE_C_LIBRARY_ARCHITECTURE "") - -if(CMAKE_C_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_C_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") -endif() - -if(CMAKE_C_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - -set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") -if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) - set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") -endif() - - - - - -set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/i686-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") -set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") -set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/i386;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/i686-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/i686-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") -set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake deleted file mode 100644 index 7940e01..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake +++ /dev/null @@ -1,83 +0,0 @@ -set(CMAKE_CXX_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++") -set(CMAKE_CXX_COMPILER_ARG1 "") -set(CMAKE_CXX_COMPILER_ID "Clang") -set(CMAKE_CXX_COMPILER_VERSION "17.0.2") -set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") -set(CMAKE_CXX_COMPILER_WRAPPER "") -set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") -set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") -set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") -set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") -set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") -set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") -set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") -set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") -set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") - -set(CMAKE_CXX_PLATFORM_ID "Linux") -set(CMAKE_CXX_SIMULATE_ID "") -set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") -set(CMAKE_CXX_SIMULATE_VERSION "") - - - - -set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_CXX_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_CXX_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") -set(CMAKE_MT "") -set(CMAKE_COMPILER_IS_GNUCXX ) -set(CMAKE_CXX_COMPILER_LOADED 1) -set(CMAKE_CXX_COMPILER_WORKS TRUE) -set(CMAKE_CXX_ABI_COMPILED TRUE) - -set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") - -set(CMAKE_CXX_COMPILER_ID_RUN 1) -set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) -set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) - -foreach (lang C OBJC OBJCXX) - if (CMAKE_${lang}_COMPILER_ID_RUN) - foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) - list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) - endforeach() - endif() -endforeach() - -set(CMAKE_CXX_LINKER_PREFERENCE 30) -set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) - -# Save compiler ABI information. -set(CMAKE_CXX_SIZEOF_DATA_PTR "4") -set(CMAKE_CXX_COMPILER_ABI "ELF") -set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") -set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") - -if(CMAKE_CXX_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_CXX_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") -endif() - -if(CMAKE_CXX_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - -set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") -if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) - set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") -endif() - - - - - -set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/i686-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") -set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl") -set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/i386;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/i686-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/i686-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") -set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin deleted file mode 100755 index edd4a3647d3c06d5d28cfcaf11bf082fdb0551c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5828 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 S2qoFQ&Tbr)zbBP-cK-p;S0)+& diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin deleted file mode 100755 index efba7088e248e7f7580ccc43f66c20c16bb89891..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5984 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 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake deleted file mode 100644 index 46bf291..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake +++ /dev/null @@ -1,15 +0,0 @@ -set(CMAKE_HOST_SYSTEM "Darwin-24.3.0") -set(CMAKE_HOST_SYSTEM_NAME "Darwin") -set(CMAKE_HOST_SYSTEM_VERSION "24.3.0") -set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64") - -include("/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake") - -set(CMAKE_SYSTEM "Android-1") -set(CMAKE_SYSTEM_NAME "Android") -set(CMAKE_SYSTEM_VERSION "1") -set(CMAKE_SYSTEM_PROCESSOR "i686") - -set(CMAKE_CROSSCOMPILING "TRUE") - -set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c deleted file mode 100644 index 41b99d7..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c +++ /dev/null @@ -1,803 +0,0 @@ -#ifdef __cplusplus -# error "A C++ compiler has been selected for C." -#endif - -#if defined(__18CXX) -# define ID_VOID_MAIN -#endif -#if defined(__CLASSIC_C__) -/* cv-qualifiers did not exist in K&R C */ -# define const -# define volatile -#endif - -#if !defined(__has_include) -/* If the compiler does not have __has_include, pretend the answer is - always no. */ -# define __has_include(x) 0 -#endif - - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# if defined(__GNUC__) -# define SIMULATE_ID "GNU" -# endif - /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, - except that a few beta releases use the old format with V=2021. */ -# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# if defined(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# else -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# endif -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) - /* The third version component from --version is an update index, - but no macro is provided for it. */ -# define COMPILER_VERSION_PATCH DEC(0) -# endif -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -# elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) -# define COMPILER_ID "IntelLLVM" -#if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -#endif -#if defined(__GNUC__) -# define SIMULATE_ID "GNU" -#endif -/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and - * later. Look for 6 digit vs. 8 digit version number to decide encoding. - * VVVV is no smaller than the current year when a version is released. - */ -#if __INTEL_LLVM_COMPILER < 1000000L -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) -#else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) -#endif -#if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -#endif -#if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -#elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -#endif -#if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -#endif -#if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -#endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__WATCOMC__) -# define COMPILER_ID "OpenWatcom" - /* __WATCOMC__ = VVRP + 1100 */ -# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__SUNPRO_C) -# define COMPILER_ID "SunPro" -# if __SUNPRO_C >= 0x5100 - /* __SUNPRO_C = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# endif - -#elif defined(__HP_cc) -# define COMPILER_ID "HP" - /* __HP_cc = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) - -#elif defined(__DECC) -# define COMPILER_ID "Compaq" - /* __DECC_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) - -#elif defined(__IBMC__) && defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__ibmxl__) && defined(__clang__) -# define COMPILER_ID "XLClang" -# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) -# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) -# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) - - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 -# define COMPILER_ID "XL" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 -# define COMPILER_ID "VisualAge" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__NVCOMPILER) -# define COMPILER_ID "NVHPC" -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__CLANG_FUJITSU) -# define COMPILER_ID "FujitsuClang" -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# define COMPILER_VERSION_INTERNAL_STR __clang_version__ - - -#elif defined(__FUJITSU) -# define COMPILER_ID "Fujitsu" -# if defined(__FCC_version__) -# define COMPILER_VERSION __FCC_version__ -# elif defined(__FCC_major__) -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# endif -# if defined(__fcc_version) -# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) -# elif defined(__FCC_VERSION) -# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) -# endif - - -#elif defined(__ghs__) -# define COMPILER_ID "GHS" -/* __GHS_VERSION_NUMBER = VVVVRP */ -# ifdef __GHS_VERSION_NUMBER -# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) -# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) -# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) -# endif - -#elif defined(__TINYC__) -# define COMPILER_ID "TinyCC" - -#elif defined(__BCC__) -# define COMPILER_ID "Bruce" - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__ARMCC_VERSION) && !defined(__clang__) -# define COMPILER_ID "ARMCC" -#if __ARMCC_VERSION >= 1000000 - /* __ARMCC_VERSION = VRRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#else - /* __ARMCC_VERSION = VRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#endif - - -#elif defined(__clang__) && defined(__apple_build_version__) -# define COMPILER_ID "AppleClang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) - -#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) -# define COMPILER_ID "ARMClang" - # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) -# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif - -#elif defined(__GNUC__) -# define COMPILER_ID "GNU" -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# if defined(__GNUC_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" -#if defined(__VISUALDSPVERSION__) - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) -#endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" -# if defined(__VER__) && defined(__ICCARM__) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) -# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) -# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) -# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) -# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# endif - -#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) -# define COMPILER_ID "SDCC" -# if defined(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) -# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) -# else - /* SDCC = VRP */ -# define COMPILER_VERSION_MAJOR DEC(SDCC/100) -# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) -# define COMPILER_VERSION_PATCH DEC(SDCC % 10) -# endif - - -/* These compilers are either not known or too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; -#ifdef SIMULATE_ID -char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; -#endif - -#ifdef __QNXNTO__ -char const* qnxnto = "INFO" ":" "qnxnto[]"; -#endif - -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) -char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; -#endif - -#define STRINGIFY_HELPER(X) #X -#define STRINGIFY(X) STRINGIFY_HELPER(X) - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__MSYS__) -# define PLATFORM_ID "MSYS" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#elif defined(__WATCOMC__) -# if defined(__LINUX__) -# define PLATFORM_ID "Linux" - -# elif defined(__DOS__) -# define PLATFORM_ID "DOS" - -# elif defined(__OS2__) -# define PLATFORM_ID "OS2" - -# elif defined(__WINDOWS__) -# define PLATFORM_ID "Windows3x" - -# elif defined(__VXWORKS__) -# define PLATFORM_ID "VxWorks" - -# else /* unknown platform */ -# define PLATFORM_ID -# endif - -#elif defined(__INTEGRITY) -# if defined(INT_178B) -# define PLATFORM_ID "Integrity178" - -# else /* regular Integrity */ -# define PLATFORM_ID "Integrity" -# endif - -#else /* unknown platform */ -# define PLATFORM_ID - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_ARM64EC) -# define ARCHITECTURE_ID "ARM64EC" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM64) -# define ARCHITECTURE_ID "ARM64" - -# elif defined(_M_ARM) -# if _M_ARM == 4 -# define ARCHITECTURE_ID "ARMV4I" -# elif _M_ARM == 5 -# define ARCHITECTURE_ID "ARMV5I" -# else -# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) -# endif - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__WATCOMC__) -# if defined(_M_I86) -# define ARCHITECTURE_ID "I86" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# if defined(__ICCARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__ICCRX__) -# define ARCHITECTURE_ID "RX" - -# elif defined(__ICCRH850__) -# define ARCHITECTURE_ID "RH850" - -# elif defined(__ICCRL78__) -# define ARCHITECTURE_ID "RL78" - -# elif defined(__ICCRISCV__) -# define ARCHITECTURE_ID "RISCV" - -# elif defined(__ICCAVR__) -# define ARCHITECTURE_ID "AVR" - -# elif defined(__ICC430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__ICCV850__) -# define ARCHITECTURE_ID "V850" - -# elif defined(__ICC8051__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__ICCSTM8__) -# define ARCHITECTURE_ID "STM8" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__ghs__) -# if defined(__PPC64__) -# define ARCHITECTURE_ID "PPC64" - -# elif defined(__ppc__) -# define ARCHITECTURE_ID "PPC" - -# elif defined(__ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__x86_64__) -# define ARCHITECTURE_ID "x64" - -# elif defined(__i386__) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__TI_COMPILER_VERSION__) -# if defined(__TI_ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__MSP430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__TMS320C28XX__) -# define ARCHITECTURE_ID "TMS320C28x" - -# elif defined(__TMS320C6X__) || defined(_TMS320C6X) -# define ARCHITECTURE_ID "TMS320C6x" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number. */ -#ifdef COMPILER_VERSION -char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; - -/* Construct a string literal encoding the version number components. */ -#elif defined(COMPILER_VERSION_MAJOR) -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct a string literal encoding the internal version number. */ -#ifdef COMPILER_VERSION_INTERNAL -char const info_version_internal[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', - 'i','n','t','e','r','n','a','l','[', - COMPILER_VERSION_INTERNAL,']','\0'}; -#elif defined(COMPILER_VERSION_INTERNAL_STR) -char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; -#endif - -/* Construct a string literal encoding the version number components. */ -#ifdef SIMULATE_VERSION_MAJOR -char const info_simulate_version[] = { - 'I', 'N', 'F', 'O', ':', - 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', - SIMULATE_VERSION_MAJOR, -# ifdef SIMULATE_VERSION_MINOR - '.', SIMULATE_VERSION_MINOR, -# ifdef SIMULATE_VERSION_PATCH - '.', SIMULATE_VERSION_PATCH, -# ifdef SIMULATE_VERSION_TWEAK - '.', SIMULATE_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -#if !defined(__STDC__) && !defined(__clang__) -# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) -# define C_VERSION "90" -# else -# define C_VERSION -# endif -#elif __STDC_VERSION__ > 201710L -# define C_VERSION "23" -#elif __STDC_VERSION__ >= 201710L -# define C_VERSION "17" -#elif __STDC_VERSION__ >= 201000L -# define C_VERSION "11" -#elif __STDC_VERSION__ >= 199901L -# define C_VERSION "99" -#else -# define C_VERSION "90" -#endif -const char* info_language_standard_default = - "INFO" ":" "standard_default[" C_VERSION "]"; - -const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ -#if (defined(__clang__) || defined(__GNUC__) || \ - defined(__TI_COMPILER_VERSION__)) && \ - !defined(__STRICT_ANSI__) && !defined(_MSC_VER) - "ON" -#else - "OFF" -#endif -"]"; - -/*--------------------------------------------------------------------------*/ - -#ifdef ID_VOID_MAIN -void main() {} -#else -# if defined(__CLASSIC_C__) -int main(argc, argv) int argc; char *argv[]; -# else -int main(int argc, char* argv[]) -# endif -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; - require += info_arch[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif -#ifdef COMPILER_VERSION_INTERNAL - require += info_version_internal[argc]; -#endif -#ifdef SIMULATE_ID - require += info_simulate[argc]; -#endif -#ifdef SIMULATE_VERSION_MAJOR - require += info_simulate_version[argc]; -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - require += info_cray[argc]; -#endif - require += info_language_standard_default[argc]; - require += info_language_extensions_default[argc]; - (void)argv; - return require; -} -#endif diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o deleted file mode 100644 index 9310552de2220fe57f8bc45400db0b4e002fad4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3924 zcmdT{ZD?Cn7=CY(o7^^CW;^FTIwgMBkKUW6Y0_;n+tqYd+I4Iz=(>^JCO2ufBsaTB zW+qdoQ{31DKM@tgANouEp+7|ZF@y;sB8Y8O-sUsKH9L%N;Grw$KyX~=h%ApL+|?mr>442 zO=%ydFR<>z^diHl6Ye~ttvu7!?VnmaIkos7Ra01UTI1E1UUtk4&Yl6ypI$tfUObgv zJpO^U@9f0(@##%jyHr^yTF&fP(JUACk*ll}&05}eO0$y-<$6OXO(#1)EBI>7Eayxo zm&sXqvtF#t4y1&|YSgT9b-^xITej)#`?v< zHppx^yajA10d`{5?d#++Z6*API&N^GQ%9Pf;K*8kgdJ{N$F4+Sm3%_Q&RvORB0Ye+ z5kQHU-CJ@cz2izm9}9d5h-$Hmrxlg&1NlcV1-4;YP3kC?1(o19KnsQT0QSSs^3^Oz z9V3`R^ROLd+iN}%hiz`0xXAD|EPQyOx{SjbD9HCVCgmGQe6aozOzz4q3LTfeY=xeD zKVVXRhr}OX$#*@49+$qqN#6)G%Ab(mFBMi!oDZ9 zFP4d2Up2*h0bRZ)8{e@QcAZK641yZajsmn1jyhV-Irc&>+BXmz8j8o_!?#9nsT6F? zb9S)?DApkKmx`>LGpklEYL}xzD%;ZlFau@6|;S~RyYKfE!Y$PFZu$-&%EY#?q8 zWn&u?8;A0PbAvG}YYpb&gUR?!G&W@(w8qB7Tb#)0Su$p-cpt`rx>+`MIQ9_)w5x`h zE7bAs`seME)n78pX2Eh~U4~hy7<#tRFz&GC>IEZFO{S8S!K~33P8x28alG`ZF{sDm z`apkSFcljfHiwO+v}1%_IF!kZ?%X+gPiEJ|o^)pSJv-8w3@w!Nc1AXfrX-H3Dae-5 zl(<(kIX=)js?4;vj5hN>`v#S8pzx}Z=@ha&9VW**R9|p#)&H*_n&@)Ary%9NounMq zl-{mD-~=x42IzP&@w=eWi1w&&>k8HP0z8ObhAQB8Li{3~kE|d7mJx<>vHJrP9*2)- z|H+`DhB~z`)kt045X`HQ+tlz~Y9v@_lh(Fuy}^0d;r1}VAIYozEfX&@T2dz*{lV~U zJ{1LVGA~{0(FEw%zq~d-eoMXNC)F#$+TAA0lWVH|w2nRy9(-OsSiy}`(q&*C69PBo zZVJ-p%j6C^zf2C(8$yn|{u=FCW?w;l%jA_5f!vATU)FbY5N&2eXWPz*Uzt2(7m>rb zg6L63UIbFa_Wup>+eQkCM+j1IJUs%hV1#kKkgsCIr;afq?x@h;DR5fgUPjb;P{<8N z1b>PV>z)((R~WI6w}k$z(0|H^eSItRKMVZ@M(nQ>=g)C^8BuQ^Blg?Ri271O&)GjG1kd(_2R;Gt=YayVAQeyGOT9rZcUw z;XI%Z;H>{6CGoBBsate{?-g{CB)bv{=J_r&HUCy_@;vj~WIBW4^&5fA?^+VSXQuZs zkcvhyn4)-p!@yn)u7~46MSBs9!U-V+Z`yA^K=yf@zIOT?RKi&yc)LrZAIyQVGP6PJj0Ra?AeK+q2-k=W+~r7op?t+k+wVI^cOZ_gbbm@d3}Z#bc5G z^!EBakAC+qFA&5w9^VTTYT79uicqi*(>gHB%X_sOethpG$#19<2U>_!#q$K diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp deleted file mode 100644 index 25c62a8..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp +++ /dev/null @@ -1,791 +0,0 @@ -/* This source file must have a .cpp extension so that all C++ compilers - recognize the extension without flags. Borland does not know .cxx for - example. */ -#ifndef __cplusplus -# error "A C compiler has been selected for C++." -#endif - -#if !defined(__has_include) -/* If the compiler does not have __has_include, pretend the answer is - always no. */ -# define __has_include(x) 0 -#endif - - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__COMO__) -# define COMPILER_ID "Comeau" - /* __COMO_VERSION__ = VRR */ -# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) -# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) - -#elif defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# if defined(__GNUC__) -# define SIMULATE_ID "GNU" -# endif - /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, - except that a few beta releases use the old format with V=2021. */ -# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# if defined(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# else -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# endif -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) - /* The third version component from --version is an update index, - but no macro is provided for it. */ -# define COMPILER_VERSION_PATCH DEC(0) -# endif -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -# elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) -# define COMPILER_ID "IntelLLVM" -#if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -#endif -#if defined(__GNUC__) -# define SIMULATE_ID "GNU" -#endif -/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and - * later. Look for 6 digit vs. 8 digit version number to decide encoding. - * VVVV is no smaller than the current year when a version is released. - */ -#if __INTEL_LLVM_COMPILER < 1000000L -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) -#else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) -#endif -#if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -#endif -#if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -#elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -#endif -#if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -#endif -#if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -#endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__WATCOMC__) -# define COMPILER_ID "OpenWatcom" - /* __WATCOMC__ = VVRP + 1100 */ -# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__SUNPRO_CC) -# define COMPILER_ID "SunPro" -# if __SUNPRO_CC >= 0x5100 - /* __SUNPRO_CC = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# endif - -#elif defined(__HP_aCC) -# define COMPILER_ID "HP" - /* __HP_aCC = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) - -#elif defined(__DECCXX) -# define COMPILER_ID "Compaq" - /* __DECCXX_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) - -#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__ibmxl__) && defined(__clang__) -# define COMPILER_ID "XLClang" -# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) -# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) -# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) - - -#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 -# define COMPILER_ID "XL" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 -# define COMPILER_ID "VisualAge" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__NVCOMPILER) -# define COMPILER_ID "NVHPC" -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__CLANG_FUJITSU) -# define COMPILER_ID "FujitsuClang" -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# define COMPILER_VERSION_INTERNAL_STR __clang_version__ - - -#elif defined(__FUJITSU) -# define COMPILER_ID "Fujitsu" -# if defined(__FCC_version__) -# define COMPILER_VERSION __FCC_version__ -# elif defined(__FCC_major__) -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# endif -# if defined(__fcc_version) -# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) -# elif defined(__FCC_VERSION) -# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) -# endif - - -#elif defined(__ghs__) -# define COMPILER_ID "GHS" -/* __GHS_VERSION_NUMBER = VVVVRP */ -# ifdef __GHS_VERSION_NUMBER -# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) -# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) -# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) -# endif - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__ARMCC_VERSION) && !defined(__clang__) -# define COMPILER_ID "ARMCC" -#if __ARMCC_VERSION >= 1000000 - /* __ARMCC_VERSION = VRRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#else - /* __ARMCC_VERSION = VRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#endif - - -#elif defined(__clang__) && defined(__apple_build_version__) -# define COMPILER_ID "AppleClang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) - -#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) -# define COMPILER_ID "ARMClang" - # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) -# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif - -#elif defined(__GNUC__) || defined(__GNUG__) -# define COMPILER_ID "GNU" -# if defined(__GNUC__) -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# else -# define COMPILER_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" -#if defined(__VISUALDSPVERSION__) - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) -#endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" -# if defined(__VER__) && defined(__ICCARM__) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) -# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) -# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) -# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) -# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# endif - - -/* These compilers are either not known or too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; -#ifdef SIMULATE_ID -char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; -#endif - -#ifdef __QNXNTO__ -char const* qnxnto = "INFO" ":" "qnxnto[]"; -#endif - -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) -char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; -#endif - -#define STRINGIFY_HELPER(X) #X -#define STRINGIFY(X) STRINGIFY_HELPER(X) - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__MSYS__) -# define PLATFORM_ID "MSYS" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#elif defined(__WATCOMC__) -# if defined(__LINUX__) -# define PLATFORM_ID "Linux" - -# elif defined(__DOS__) -# define PLATFORM_ID "DOS" - -# elif defined(__OS2__) -# define PLATFORM_ID "OS2" - -# elif defined(__WINDOWS__) -# define PLATFORM_ID "Windows3x" - -# elif defined(__VXWORKS__) -# define PLATFORM_ID "VxWorks" - -# else /* unknown platform */ -# define PLATFORM_ID -# endif - -#elif defined(__INTEGRITY) -# if defined(INT_178B) -# define PLATFORM_ID "Integrity178" - -# else /* regular Integrity */ -# define PLATFORM_ID "Integrity" -# endif - -#else /* unknown platform */ -# define PLATFORM_ID - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_ARM64EC) -# define ARCHITECTURE_ID "ARM64EC" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM64) -# define ARCHITECTURE_ID "ARM64" - -# elif defined(_M_ARM) -# if _M_ARM == 4 -# define ARCHITECTURE_ID "ARMV4I" -# elif _M_ARM == 5 -# define ARCHITECTURE_ID "ARMV5I" -# else -# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) -# endif - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__WATCOMC__) -# if defined(_M_I86) -# define ARCHITECTURE_ID "I86" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# if defined(__ICCARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__ICCRX__) -# define ARCHITECTURE_ID "RX" - -# elif defined(__ICCRH850__) -# define ARCHITECTURE_ID "RH850" - -# elif defined(__ICCRL78__) -# define ARCHITECTURE_ID "RL78" - -# elif defined(__ICCRISCV__) -# define ARCHITECTURE_ID "RISCV" - -# elif defined(__ICCAVR__) -# define ARCHITECTURE_ID "AVR" - -# elif defined(__ICC430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__ICCV850__) -# define ARCHITECTURE_ID "V850" - -# elif defined(__ICC8051__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__ICCSTM8__) -# define ARCHITECTURE_ID "STM8" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__ghs__) -# if defined(__PPC64__) -# define ARCHITECTURE_ID "PPC64" - -# elif defined(__ppc__) -# define ARCHITECTURE_ID "PPC" - -# elif defined(__ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__x86_64__) -# define ARCHITECTURE_ID "x64" - -# elif defined(__i386__) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__TI_COMPILER_VERSION__) -# if defined(__TI_ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__MSP430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__TMS320C28XX__) -# define ARCHITECTURE_ID "TMS320C28x" - -# elif defined(__TMS320C6X__) || defined(_TMS320C6X) -# define ARCHITECTURE_ID "TMS320C6x" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number. */ -#ifdef COMPILER_VERSION -char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; - -/* Construct a string literal encoding the version number components. */ -#elif defined(COMPILER_VERSION_MAJOR) -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct a string literal encoding the internal version number. */ -#ifdef COMPILER_VERSION_INTERNAL -char const info_version_internal[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', - 'i','n','t','e','r','n','a','l','[', - COMPILER_VERSION_INTERNAL,']','\0'}; -#elif defined(COMPILER_VERSION_INTERNAL_STR) -char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; -#endif - -/* Construct a string literal encoding the version number components. */ -#ifdef SIMULATE_VERSION_MAJOR -char const info_simulate_version[] = { - 'I', 'N', 'F', 'O', ':', - 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', - SIMULATE_VERSION_MAJOR, -# ifdef SIMULATE_VERSION_MINOR - '.', SIMULATE_VERSION_MINOR, -# ifdef SIMULATE_VERSION_PATCH - '.', SIMULATE_VERSION_PATCH, -# ifdef SIMULATE_VERSION_TWEAK - '.', SIMULATE_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L -# if defined(__INTEL_CXX11_MODE__) -# if defined(__cpp_aggregate_nsdmi) -# define CXX_STD 201402L -# else -# define CXX_STD 201103L -# endif -# else -# define CXX_STD 199711L -# endif -#elif defined(_MSC_VER) && defined(_MSVC_LANG) -# define CXX_STD _MSVC_LANG -#else -# define CXX_STD __cplusplus -#endif - -const char* info_language_standard_default = "INFO" ":" "standard_default[" -#if CXX_STD > 202002L - "23" -#elif CXX_STD > 201703L - "20" -#elif CXX_STD >= 201703L - "17" -#elif CXX_STD >= 201402L - "14" -#elif CXX_STD >= 201103L - "11" -#else - "98" -#endif -"]"; - -const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ -#if (defined(__clang__) || defined(__GNUC__) || \ - defined(__TI_COMPILER_VERSION__)) && \ - !defined(__STRICT_ANSI__) && !defined(_MSC_VER) - "ON" -#else - "OFF" -#endif -"]"; - -/*--------------------------------------------------------------------------*/ - -int main(int argc, char* argv[]) -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif -#ifdef COMPILER_VERSION_INTERNAL - require += info_version_internal[argc]; -#endif -#ifdef SIMULATE_ID - require += info_simulate[argc]; -#endif -#ifdef SIMULATE_VERSION_MAJOR - require += info_simulate_version[argc]; -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - require += info_cray[argc]; -#endif - require += info_language_standard_default[argc]; - require += info_language_extensions_default[argc]; - (void)argv; - return require; -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o deleted file mode 100644 index 76432df37b6b61f70c2e6d975b1be0efd7bd1acd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3960 zcmdT{U1%Fu7CxiV$YV=Z>SWubjVa2KE^c={BgwL@B&M~K$XN$F4oM72O_&`^BiXH_ zQAeZTwCVp(65N+STguXhJ~S^&31y#lVOa`WwhyJdltLHwp_GL{yOjNXG3+kc@66n* zjGUVGwHNOF&fk3Z+&lN4k)AEh&nk*SvMHp}ZH;J8GV~Mz7@^@FFVWJ~n=gK?f63mn z&%dt%HWpGF3;Ktp|FZ4F(k8>km0(=bclKwX#%yR(~N5*xv zw0X6(xl!7D@dN$*@8(X-E*>nqjn-P-@s^L&?Pl#f1;$q0_N%VfSe{>NcGiW__R6cv zLT>wZvtoM{tKwAcPTgP5O$v{*?mNx)n%iu5eTyf~a}Gpzqd$Z`fqoLbCjsk%FvdY7iA@7ldLJ*4bR5XA~Kx9ec?kQUp6ZBUfCT}1JHuubAk zXg`8Ll-N&d`r%{}mOd7f$%i581&DLI9=TUO-M=G<9tiEBwV5VL8kl!yVtS97W+OjB zl+q~HH4qIJdQ^G=ha!$OVhoPQKKfOl5&co%1`x>;DK9A+9|TgTF~sLF+)Y{ukT`~C z6H4DaK=0Fk25?~RKF~i6E#&w(rm4KYdQ%3m1qO<}i9z`TG~Ro48bdHgiu6k|mc6i3 z>;nwSU!d_jx*dBT>95FG_6D*4;Mjjb<9B&Gc9`_*GM2p@JMep0_Mba zT=InXfn$%ZEZyX|TQMJyie1zH)}yBW9jZ?O24mOOH(6Cw4yMFkF>3Mt=K%e@e>Bsq zcA4p{>b6b0QtRL@j;^{5XS88A?V97s+)TUGGL7>3x_Q)D z>D0_Zdt!2;HC8s)ixXxr%Pekx+Z;3Uc_TMk8=K4)i+0hxJu$K%ti>bCnmKi9=A3nU z?$MHU=G@7WWzkx*>RPgdgqo}!p~giclz1mQNX^<>JGQv*EFfWkcnM@ZI-ko2^GZtt z8;uyBY_C@4;R1Qi6P+~=cjfzf0O$vNe9@FAPmyv-SN5jj@hdpj!?1DZ#@B^r()!D> z!-HDvG9rlHfGJJ}Mtr6IlOAN?yMeB3cdX#Xy@~Ot-qIAUZ$ST(mhNc7iK>>K(vruu zbfOl~_9j+gf#U^$nyzZ2J%MId8$h6%NKVBxq`~yP?e&Nnr+?mxsQ9X?#KnkP9$lfk z0$C0!X;KVOy~97W#V>a>G^=zkeIX)vA9rHD#Ym1k+hyVBIzB`R`g@PA)9D^PMI$|W znsy7m@c9A4r-TLuD2VGv!8-)KKScpgKbB*$K1k#-axj|04}S~dD@Y0kP?6HdYYFil zM*KXuPw4kE;x%U(!8B0~&xp8-!u|>)CV5TRuM7Jx8Fvu9FYKQP`{#^U z&)35KKVcuhz9?AV4o2iV%!u`8gq~wWo`-~fT;Mr@s{%U$GvJMJJoEE0HY!}~EPG|e zb1snKqoxoS=7xhRVR%m6sMx-31XZM4m%gF!Y!`Y*2@?~xeQzs$w>WN7(!(i&bU7V7 z?gqKtS>}RBUWySEye+wP%dXLMeaARF^ceiDfAclvS8V3SRX zI8M0p_@)a-K?VpE*Mj~GJsLL+J*bN!PF9W2pkpeU7WOIJ3%&wy#w?Bo8tK)IG8j4~&Vl=9P%qx04=3D3jx^4jFQUqNPG$v3qP-%Z3s`TPhU z^Gd!UJRjwo-iB`w_9)+_2p>vSmoKOhk^GKs!#B4jzn3C>T%TlqKZG33@2A`Fam|Y6 z$A5QtoxFcsA|>B%ATu9de{TGfS-wNo*~g7h%B(*Fa<&{teH_XOr6v)Wu(iVlc9gdr(Uw_L{sX z!p1S&#v!mQr&>i^G4O-~=f{m}ZqGWP$bH@ozg))yf-iUo!`tBdxm18W7q@*|_}+@} c;ono2kN@Gw-1xaEd=Hp}c{m@Qm+$cZ0ohYm6951J diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/TargetDirectories.txt deleted file mode 100644 index 15fd9a6..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/TargetDirectories.txt +++ /dev/null @@ -1,2 +0,0 @@ -/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/edit_cache.dir -/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/cmake.check_cache deleted file mode 100644 index 3dccd73..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/cmake.check_cache +++ /dev/null @@ -1 +0,0 @@ -# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rules.ninja b/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rules.ninja deleted file mode 100644 index fd37716..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/CMakeFiles/rules.ninja +++ /dev/null @@ -1,45 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Ninja" Generator, CMake Version 3.22 - -# This file contains all the rules used to get the outputs files -# built from the input files. -# It is included in the main 'build.ninja'. - -# ============================================================================= -# Project: Project -# Configurations: Debug -# ============================================================================= -# ============================================================================= - -############################################# -# Rule for running custom commands. - -rule CUSTOM_COMMAND - command = $COMMAND - description = $DESC - - -############################################# -# Rule for re-running cmake. - -rule RERUN_CMAKE - command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 - description = Re-running CMake... - generator = 1 - - -############################################# -# Rule for cleaning all built files. - -rule CLEAN - command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja $FILE_ARG -t clean $TARGETS - description = Cleaning all built files... - - -############################################# -# Rule for printing all primary targets available. - -rule HELP - command = /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja -t targets - description = All primary targets available: - diff --git a/android/app/.cxx/Debug/4s676p3c/x86/additional_project_files.txt b/android/app/.cxx/Debug/4s676p3c/x86/additional_project_files.txt deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json b/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json deleted file mode 100644 index 5e59a91..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "buildFiles": [ - "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" - ], - "cleanCommandsComponents": [ - [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", - "clean" - ] - ], - "buildTargetsCommandComponents": [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", - "{LIST_OF_TARGETS_TO_BUILD}" - ], - "libraries": {}, - "toolchains": { - "toolchain": { - "cCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang.lld", - "cppCompilerExecutable": "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++.lld" - } - }, - "cFileExtensions": [], - "cppFileExtensions": [] -} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json b/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json deleted file mode 100644 index 984990b..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "buildFiles": [ - "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt" - ], - "cleanCommandsComponents": [ - [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", - "clean" - ] - ], - "buildTargetsCommandComponents": [ - "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja", - "-C", - "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86", - "{LIST_OF_TARGETS_TO_BUILD}" - ], - "libraries": {} -} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/build.ninja b/android/app/.cxx/Debug/4s676p3c/x86/build.ninja deleted file mode 100644 index 908e700..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/build.ninja +++ /dev/null @@ -1,112 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Ninja" Generator, CMake Version 3.22 - -# This file contains all the build statements describing the -# compilation DAG. - -# ============================================================================= -# Write statements declared in CMakeLists.txt: -# -# Which is the root file. -# ============================================================================= - -# ============================================================================= -# Project: Project -# Configurations: Debug -# ============================================================================= - -############################################# -# Minimal version of Ninja required by this file - -ninja_required_version = 1.5 - - -############################################# -# Set configuration variable for custom commands. - -CONFIGURATION = Debug -# ============================================================================= -# Include auxiliary files. - - -############################################# -# Include rules file. - -include CMakeFiles/rules.ninja - -# ============================================================================= - -############################################# -# Logical path to working directory; prefix for absolute paths. - -cmake_ninja_workdir = /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/ - -############################################# -# Utility command for edit_cache - -build CMakeFiles/edit_cache.util: CUSTOM_COMMAND - COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 - DESC = Running CMake cache editor... - pool = console - restat = 1 - -build edit_cache: phony CMakeFiles/edit_cache.util - - -############################################# -# Utility command for rebuild_cache - -build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND - COMMAND = cd /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 && /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 - DESC = Running CMake to regenerate build system... - pool = console - restat = 1 - -build rebuild_cache: phony CMakeFiles/rebuild_cache.util - -# ============================================================================= -# Target aliases. - -# ============================================================================= -# Folder targets. - -# ============================================================================= - -############################################# -# Folder: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 - -build all: phony - -# ============================================================================= -# Built-in targets - - -############################################# -# Re-run CMake if any of its inputs changed. - -build build.ninja: RERUN_CMAKE | /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake - pool = console - - -############################################# -# A missing CMake input file is not an error. - -build /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake: phony - - -############################################# -# Clean all the built files. - -build clean: CLEAN - - -############################################# -# Print all primary targets available. - -build help: HELP - - -############################################# -# Make the all target the default. - -default all diff --git a/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt b/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt deleted file mode 100644 index ec6a72a..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt +++ /dev/null @@ -1 +0,0 @@ -/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/cmake_install.cmake b/android/app/.cxx/Debug/4s676p3c/x86/cmake_install.cmake deleted file mode 100644 index 3ec8b80..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/cmake_install.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# Install script for directory: /Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy - -# Set the install prefix -if(NOT DEFINED CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local") -endif() -string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - if(BUILD_TYPE) - string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - else() - set(CMAKE_INSTALL_CONFIG_NAME "Debug") - endif() - message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -endif() - -# Set the component getting installed. -if(NOT CMAKE_INSTALL_COMPONENT) - if(COMPONENT) - message(STATUS "Install component: \"${COMPONENT}\"") - set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - else() - set(CMAKE_INSTALL_COMPONENT) - endif() -endif() - -# Install shared libraries without execute permission? -if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) - set(CMAKE_INSTALL_SO_NO_EXE "0") -endif() - -# Is this installation the result of a crosscompile? -if(NOT DEFINED CMAKE_CROSSCOMPILING) - set(CMAKE_CROSSCOMPILING "TRUE") -endif() - -# Set default install directory permissions. -if(NOT DEFINED CMAKE_OBJDUMP) - set(CMAKE_OBJDUMP "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump") -endif() - -if(CMAKE_INSTALL_COMPONENT) - set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") -else() - set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") -endif() - -string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT - "${CMAKE_INSTALL_MANIFEST_FILES}") -file(WRITE "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/${CMAKE_INSTALL_MANIFEST}" - "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin b/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin deleted file mode 100644 index aa45397..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/configure_fingerprint.bin +++ /dev/null @@ -1,28 +0,0 @@ -C/C++ Structured Logo -m -k/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/additional_project_files.txtC -A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ñ½ã×2  ï½ã×2l -j -h/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build.json  ñ½ã×2à ï½ã×2q -o -m/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/android_gradle_build_mini.json  ñ½ã×2Î ð½ã×2^ -\ -Z/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build.ninja  ñ½ã×2ðà å½ã×2b -` -^/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build.ninja.txt  ñ½ã×2g -e -c/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/build_file_index.txt  ñ½ã×2 P ð½ã×2h -f -d/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/compile_commands.json  ñ½ã×2l -j -h/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/compile_commands.json.bin  ñ½ã×2 r -p -n/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt  ñ½ã×2 -  ð½ã×2e -c -a/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json  ñ½ã×2  ( ð½ã×2j -h -f/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt  ñ½ã×2  ] ð½ã×2T -R -P/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt  ñ½ã×2 ¤ Ø„é×Ñ2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt b/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt deleted file mode 100644 index 2aed5c8..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/metadata_generation_command.txt +++ /dev/null @@ -1,20 +0,0 @@ - -H/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy --DCMAKE_SYSTEM_NAME=Android --DCMAKE_EXPORT_COMPILE_COMMANDS=ON --DCMAKE_SYSTEM_VERSION=26 --DANDROID_PLATFORM=android-26 --DANDROID_ABI=x86 --DCMAKE_ANDROID_ARCH_ABI=x86 --DANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 --DCMAKE_ANDROID_NDK=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 --DCMAKE_TOOLCHAIN_FILE=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake --DCMAKE_MAKE_PROGRAM=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja --DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 --DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 --DCMAKE_BUILD_TYPE=Debug --B/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86 --GNinja --Wno-dev ---no-warn-unused-cli - Build command args: [] - Version: 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json b/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json deleted file mode 100644 index e799de8..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/prefab_config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "enabled": false, - "packages": [] -} \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt b/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt deleted file mode 100644 index ec94a09..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86/symbol_folder_index.txt +++ /dev/null @@ -1 +0,0 @@ -/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86 \ No newline at end of file diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cache-v2 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/cmakeFiles-v1 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/query/client-agp/codemodel-v2 deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cache-v2-2b5d080db4293a9c0f40.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cache-v2-2b5d080db4293a9c0f40.json deleted file mode 100644 index 54f6d66..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cache-v2-2b5d080db4293a9c0f40.json +++ /dev/null @@ -1,1391 +0,0 @@ -{ - "entries" : - [ - { - "name" : "ANDROID_ABI", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "x86_64" - }, - { - "name" : "ANDROID_NDK", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" - }, - { - "name" : "ANDROID_PLATFORM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "android-26" - }, - { - "name" : "CMAKE_ADDR2LINE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line" - }, - { - "name" : "CMAKE_ANDROID_ARCH_ABI", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "x86_64" - }, - { - "name" : "CMAKE_ANDROID_NDK", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125" - }, - { - "name" : "CMAKE_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_ASM_FLAGS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_ASM_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_ASM_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_BUILD_TYPE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." - } - ], - "type" : "STRING", - "value" : "Debug" - }, - { - "name" : "CMAKE_CACHEFILE_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "This is the directory where this CMakeCache.txt was created" - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64" - }, - { - "name" : "CMAKE_CACHE_MAJOR_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Major version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "3" - }, - { - "name" : "CMAKE_CACHE_MINOR_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Minor version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "22" - }, - { - "name" : "CMAKE_CACHE_PATCH_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Patch version of cmake used to create the current loaded cache" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to CMake executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake" - }, - { - "name" : "CMAKE_CPACK_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to cpack program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack" - }, - { - "name" : "CMAKE_CTEST_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to ctest program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest" - }, - { - "name" : "CMAKE_CXX_COMPILER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "(This variable does not exist and should not be used)" - } - ], - "type" : "UNINITIALIZED", - "value" : "" - }, - { - "name" : "CMAKE_CXX_COMPILER_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "LLVM archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_CXX_COMPILER_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Generate index for LLVM archive" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_CXX_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the CXX compiler during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "-Os -DNDEBUG" - }, - { - "name" : "CMAKE_CXX_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "-O2 -g -DNDEBUG" - }, - { - "name" : "CMAKE_CXX_STANDARD_LIBRARIES", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Libraries linked by default with all C++ applications." - } - ], - "type" : "STRING", - "value" : "-latomic -lm" - }, - { - "name" : "CMAKE_C_COMPILER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "(This variable does not exist and should not be used)" - } - ], - "type" : "UNINITIALIZED", - "value" : "" - }, - { - "name" : "CMAKE_C_COMPILER_AR", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "LLVM archiver" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar" - }, - { - "name" : "CMAKE_C_COMPILER_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Generate index for LLVM archive" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_C_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during debug builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the C compiler during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "-Os -DNDEBUG" - }, - { - "name" : "CMAKE_C_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the compiler during release builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "-O2 -g -DNDEBUG" - }, - { - "name" : "CMAKE_C_STANDARD_LIBRARIES", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Libraries linked by default with all C applications." - } - ], - "type" : "STRING", - "value" : "-latomic -lm" - }, - { - "name" : "CMAKE_DLLTOOL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "CMAKE_DLLTOOL-NOTFOUND" - }, - { - "name" : "CMAKE_EDIT_COMMAND", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to cache edit program executable." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake" - }, - { - "name" : "CMAKE_ERROR_DEPRECATED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Whether to issue deprecation errors for macros and functions." - } - ], - "type" : "INTERNAL", - "value" : "FALSE" - }, - { - "name" : "CMAKE_EXECUTABLE_FORMAT", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Executable file format" - } - ], - "type" : "INTERNAL", - "value" : "ELF" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "ON" - }, - { - "name" : "CMAKE_EXTRA_GENERATOR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of external makefile project generator." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator." - } - ], - "type" : "INTERNAL", - "value" : "Ninja" - }, - { - "name" : "CMAKE_GENERATOR_INSTANCE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Generator instance identifier." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR_PLATFORM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator platform." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_GENERATOR_TOOLSET", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Name of generator toolset." - } - ], - "type" : "INTERNAL", - "value" : "" - }, - { - "name" : "CMAKE_HOME_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Source directory with the top level CMakeLists.txt file for this project" - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - { - "name" : "CMAKE_INSTALL_PREFIX", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Install path prefix, prepended onto install directories." - } - ], - "type" : "PATH", - "value" : "/usr/local" - }, - { - "name" : "CMAKE_INSTALL_SO_NO_EXE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Install .so files without execute permission." - } - ], - "type" : "INTERNAL", - "value" : "0" - }, - { - "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86_64" - }, - { - "name" : "CMAKE_LINKER", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" - }, - { - "name" : "CMAKE_MAKE_PROGRAM", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_NM", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm" - }, - { - "name" : "CMAKE_NUMBER_OF_MAKEFILES", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "number of local generators" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_OBJCOPY", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy" - }, - { - "name" : "CMAKE_OBJDUMP", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump" - }, - { - "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Platform information initialized" - } - ], - "type" : "INTERNAL", - "value" : "1" - }, - { - "name" : "CMAKE_PROJECT_DESCRIPTION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "" - }, - { - "name" : "CMAKE_PROJECT_HOMEPAGE_URL", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "" - }, - { - "name" : "CMAKE_PROJECT_NAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "Project" - }, - { - "name" : "CMAKE_RANLIB", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Ranlib" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib" - }, - { - "name" : "CMAKE_READELF", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Path to a program." - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf" - }, - { - "name" : "CMAKE_ROOT", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Path to CMake installation." - } - ], - "type" : "INTERNAL", - "value" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" - }, - { - "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86_64" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of dll's." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_SKIP_INSTALL_RPATH", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." - } - ], - "type" : "BOOL", - "value" : "NO" - }, - { - "name" : "CMAKE_SKIP_RPATH", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If set, runtime paths are not added when using shared libraries." - } - ], - "type" : "BOOL", - "value" : "NO" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during all build types." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." - } - ], - "type" : "STRING", - "value" : "" - }, - { - "name" : "CMAKE_STRIP", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "Strip" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip" - }, - { - "name" : "CMAKE_SUPPRESS_DEVELOPER_ERRORS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Suppress errors that are meant for the author of the CMakeLists.txt files." - } - ], - "type" : "INTERNAL", - "value" : "TRUE" - }, - { - "name" : "CMAKE_SUPPRESS_DEVELOPER_WARNINGS", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Suppress Warnings that are meant for the author of the CMakeLists.txt files." - } - ], - "type" : "INTERNAL", - "value" : "TRUE" - }, - { - "name" : "CMAKE_SYSTEM_NAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "Android" - }, - { - "name" : "CMAKE_SYSTEM_VERSION", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "No help, variable specified on the command line." - } - ], - "type" : "UNINITIALIZED", - "value" : "26" - }, - { - "name" : "CMAKE_TOOLCHAIN_FILE", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "The CMake toolchain file" - } - ], - "type" : "FILEPATH", - "value" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "name" : "CMAKE_UNAME", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "uname command" - } - ], - "type" : "INTERNAL", - "value" : "/usr/bin/uname" - }, - { - "name" : "CMAKE_VERBOSE_MAKEFILE", - "properties" : - [ - { - "name" : "ADVANCED", - "value" : "1" - }, - { - "name" : "HELPSTRING", - "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." - } - ], - "type" : "BOOL", - "value" : "FALSE" - }, - { - "name" : "CMAKE_WARN_DEPRECATED", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Whether to issue warnings for deprecated functionality." - } - ], - "type" : "INTERNAL", - "value" : "FALSE" - }, - { - "name" : "Project_BINARY_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64" - }, - { - "name" : "Project_IS_TOP_LEVEL", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "ON" - }, - { - "name" : "Project_SOURCE_DIR", - "properties" : - [ - { - "name" : "HELPSTRING", - "value" : "Value Computed by CMake" - } - ], - "type" : "STATIC", - "value" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - } - ], - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-9a2bf79ff0a2a89eb505.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-9a2bf79ff0a2a89eb505.json deleted file mode 100644 index bc82f99..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-9a2bf79ff0a2a89eb505.json +++ /dev/null @@ -1,799 +0,0 @@ -{ - "inputs" : - [ - { - "path" : "CMakeLists.txt" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android-legacy.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/platforms.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Determine.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Initialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/hooks/pre/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/flags.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake" - } - ], - "kind" : "cmakeFiles", - "paths" : - { - "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64", - "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - "version" : - { - "major" : 1, - "minor" : 0 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/codemodel-v2-852402f1316f6f65a056.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/codemodel-v2-852402f1316f6f65a056.json deleted file mode 100644 index 29446e0..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/codemodel-v2-852402f1316f6f65a056.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "configurations" : - [ - { - "directories" : - [ - { - "build" : ".", - "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", - "minimumCMakeVersion" : - { - "string" : "3.6.0" - }, - "projectIndex" : 0, - "source" : "." - } - ], - "name" : "Debug", - "projects" : - [ - { - "directoryIndexes" : - [ - 0 - ], - "name" : "Project" - } - ], - "targets" : [] - } - ], - "kind" : "codemodel", - "paths" : - { - "build" : "/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64", - "source" : "/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy" - }, - "version" : - { - "major" : 2, - "minor" : 3 - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json deleted file mode 100644 index 3a67af9..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "backtraceGraph" : - { - "commands" : [], - "files" : [], - "nodes" : [] - }, - "installers" : [], - "paths" : - { - "build" : ".", - "source" : "." - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0481.json b/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0481.json deleted file mode 100644 index 0148bde..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/.cmake/api/v1/reply/index-2025-03-09T19-31-31-0481.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "cmake" : - { - "generator" : - { - "multiConfig" : false, - "name" : "Ninja" - }, - "paths" : - { - "cmake" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake", - "cpack" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack", - "ctest" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest", - "root" : "/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22" - }, - "version" : - { - "isDirty" : false, - "major" : 3, - "minor" : 22, - "patch" : 1, - "string" : "3.22.1-g37088a8", - "suffix" : "g37088a8" - } - }, - "objects" : - [ - { - "jsonFile" : "codemodel-v2-852402f1316f6f65a056.json", - "kind" : "codemodel", - "version" : - { - "major" : 2, - "minor" : 3 - } - }, - { - "jsonFile" : "cache-v2-2b5d080db4293a9c0f40.json", - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } - }, - { - "jsonFile" : "cmakeFiles-v1-9a2bf79ff0a2a89eb505.json", - "kind" : "cmakeFiles", - "version" : - { - "major" : 1, - "minor" : 0 - } - } - ], - "reply" : - { - "client-agp" : - { - "cache-v2" : - { - "jsonFile" : "cache-v2-2b5d080db4293a9c0f40.json", - "kind" : "cache", - "version" : - { - "major" : 2, - "minor" : 0 - } - }, - "cmakeFiles-v1" : - { - "jsonFile" : "cmakeFiles-v1-9a2bf79ff0a2a89eb505.json", - "kind" : "cmakeFiles", - "version" : - { - "major" : 1, - "minor" : 0 - } - }, - "codemodel-v2" : - { - "jsonFile" : "codemodel-v2-852402f1316f6f65a056.json", - "kind" : "codemodel", - "version" : - { - "major" : 2, - "minor" : 3 - } - } - } - } -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt deleted file mode 100644 index 63f4eca..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeCache.txt +++ /dev/null @@ -1,405 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64 -# It was generated by CMake: /Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//No help, variable specified on the command line. -ANDROID_ABI:UNINITIALIZED=x86_64 - -//No help, variable specified on the command line. -ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 - -//No help, variable specified on the command line. -ANDROID_PLATFORM:UNINITIALIZED=android-26 - -//Path to a program. -CMAKE_ADDR2LINE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line - -//No help, variable specified on the command line. -CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=x86_64 - -//No help, variable specified on the command line. -CMAKE_ANDROID_NDK:UNINITIALIZED=/Users/juan/Library/Android/sdk/ndk/26.1.10909125 - -//Archiver -CMAKE_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Flags used by the compiler during all build types. -CMAKE_ASM_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_ASM_FLAGS_DEBUG:STRING= - -//Flags used by the compiler during release builds. -CMAKE_ASM_FLAGS_RELEASE:STRING= - -//Choose the type of build, options are: None Debug Release RelWithDebInfo -// MinSizeRel ... -CMAKE_BUILD_TYPE:STRING=Debug - -//LLVM archiver -CMAKE_CXX_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Generate index for LLVM archive -CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING= - -//Flags used by the CXX compiler during MINSIZEREL builds. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_CXX_FLAGS_RELEASE:STRING= - -//Flags used by the CXX compiler during RELWITHDEBINFO builds. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Libraries linked by default with all C++ applications. -CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm - -//LLVM archiver -CMAKE_C_COMPILER_AR:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar - -//Generate index for LLVM archive -CMAKE_C_COMPILER_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING= - -//Flags used by the C compiler during MINSIZEREL builds. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_C_FLAGS_RELEASE:STRING= - -//Flags used by the C compiler during RELWITHDEBINFO builds. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Libraries linked by default with all C applications. -CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm - -//Path to a program. -CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING= - -//Flags used by the linker during DEBUG builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during MINSIZEREL builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during RELEASE builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during RELWITHDEBINFO builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//No help, variable specified on the command line. -CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//No help, variable specified on the command line. -CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86_64 - -//Path to a program. -CMAKE_LINKER:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld - -//No help, variable specified on the command line. -CMAKE_MAKE_PROGRAM:UNINITIALIZED=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ninja - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of modules during -// DEBUG builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of modules during -// MINSIZEREL builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of modules during -// RELEASE builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of modules during -// RELWITHDEBINFO builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump - -//Value Computed by CMake -CMAKE_PROJECT_DESCRIPTION:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_HOMEPAGE_URL:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=Project - -//Ranlib -CMAKE_RANLIB:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib - -//Path to a program. -CMAKE_READELF:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf - -//No help, variable specified on the command line. -CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/juan/Proyectos/adguard-home-manager/build/app/intermediates/cxx/Debug/4s676p3c/obj/x86_64 - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of shared libraries -// during DEBUG builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of shared libraries -// during MINSIZEREL builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELEASE builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of shared libraries -// during RELWITHDEBINFO builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries -// during all build types. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during the creation of static libraries -// during DEBUG builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during the creation of static libraries -// during MINSIZEREL builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELEASE builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during the creation of static libraries -// during RELWITHDEBINFO builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Strip -CMAKE_STRIP:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip - -//No help, variable specified on the command line. -CMAKE_SYSTEM_NAME:UNINITIALIZED=Android - -//No help, variable specified on the command line. -CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 - -//The CMake toolchain file -CMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//Value Computed by CMake -Project_BINARY_DIR:STATIC=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64 - -//Value Computed by CMake -Project_IS_TOP_LEVEL:STATIC=ON - -//Value Computed by CMake -Project_SOURCE_DIR:STATIC=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: CMAKE_ADDR2LINE -CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/Users/juan/Proyectos/adguard-home-manager/android/app/.cxx/Debug/4s676p3c/x86_64 -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ctest -//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR -CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB -CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES -CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_AR -CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB -CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES -CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_DLLTOOL -CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 -//Path to cache edit program executable. -CMAKE_EDIT_COMMAND:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/bin/ccmake -//Whether to issue deprecation errors for macros and functions. -CMAKE_ERROR_DEPRECATED:INTERNAL=FALSE -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Ninja -//Generator instance identifier. -CMAKE_GENERATOR_INSTANCE:INTERNAL= -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/Users/juan/flutter/packages/flutter_tools/gradle/src/main/groovy -//Install .so files without execute permission. -CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_READELF -CMAKE_READELF-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/Users/juan/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//Suppress errors that are meant for the author of the CMakeLists.txt -// files. -CMAKE_SUPPRESS_DEVELOPER_ERRORS:INTERNAL=TRUE -//Suppress Warnings that are meant for the author of the CMakeLists.txt -// files. -CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=TRUE -//uname command -CMAKE_UNAME:INTERNAL=/usr/bin/uname -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Whether to issue warnings for deprecated functionality. -CMAKE_WARN_DEPRECATED:INTERNAL=FALSE - diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake deleted file mode 100644 index f2a3233..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake +++ /dev/null @@ -1,72 +0,0 @@ -set(CMAKE_C_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang") -set(CMAKE_C_COMPILER_ARG1 "") -set(CMAKE_C_COMPILER_ID "Clang") -set(CMAKE_C_COMPILER_VERSION "17.0.2") -set(CMAKE_C_COMPILER_VERSION_INTERNAL "") -set(CMAKE_C_COMPILER_WRAPPER "") -set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") -set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") -set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") -set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") -set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") -set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") -set(CMAKE_C17_COMPILE_FEATURES "c_std_17") -set(CMAKE_C23_COMPILE_FEATURES "c_std_23") - -set(CMAKE_C_PLATFORM_ID "Linux") -set(CMAKE_C_SIMULATE_ID "") -set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") -set(CMAKE_C_SIMULATE_VERSION "") - - - - -set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_C_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_C_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") -set(CMAKE_MT "") -set(CMAKE_COMPILER_IS_GNUCC ) -set(CMAKE_C_COMPILER_LOADED 1) -set(CMAKE_C_COMPILER_WORKS TRUE) -set(CMAKE_C_ABI_COMPILED TRUE) - -set(CMAKE_C_COMPILER_ENV_VAR "CC") - -set(CMAKE_C_COMPILER_ID_RUN 1) -set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) -set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) -set(CMAKE_C_LINKER_PREFERENCE 10) - -# Save compiler ABI information. -set(CMAKE_C_SIZEOF_DATA_PTR "8") -set(CMAKE_C_COMPILER_ABI "ELF") -set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") -set(CMAKE_C_LIBRARY_ARCHITECTURE "") - -if(CMAKE_C_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_C_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") -endif() - -if(CMAKE_C_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - -set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") -if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) - set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") -endif() - - - - - -set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/x86_64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") -set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") -set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/x86_64;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/x86_64-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/x86_64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") -set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake deleted file mode 100644 index 788db59..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake +++ /dev/null @@ -1,83 +0,0 @@ -set(CMAKE_CXX_COMPILER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++") -set(CMAKE_CXX_COMPILER_ARG1 "") -set(CMAKE_CXX_COMPILER_ID "Clang") -set(CMAKE_CXX_COMPILER_VERSION "17.0.2") -set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") -set(CMAKE_CXX_COMPILER_WRAPPER "") -set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17") -set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") -set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") -set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") -set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") -set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") -set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") -set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") -set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") - -set(CMAKE_CXX_PLATFORM_ID "Linux") -set(CMAKE_CXX_SIMULATE_ID "") -set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") -set(CMAKE_CXX_SIMULATE_VERSION "") - - - - -set(CMAKE_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_CXX_COMPILER_AR "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar") -set(CMAKE_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_CXX_COMPILER_RANLIB "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib") -set(CMAKE_LINKER "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld") -set(CMAKE_MT "") -set(CMAKE_COMPILER_IS_GNUCXX ) -set(CMAKE_CXX_COMPILER_LOADED 1) -set(CMAKE_CXX_COMPILER_WORKS TRUE) -set(CMAKE_CXX_ABI_COMPILED TRUE) - -set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") - -set(CMAKE_CXX_COMPILER_ID_RUN 1) -set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) -set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) - -foreach (lang C OBJC OBJCXX) - if (CMAKE_${lang}_COMPILER_ID_RUN) - foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) - list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) - endforeach() - endif() -endforeach() - -set(CMAKE_CXX_LINKER_PREFERENCE 30) -set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) - -# Save compiler ABI information. -set(CMAKE_CXX_SIZEOF_DATA_PTR "8") -set(CMAKE_CXX_COMPILER_ABI "ELF") -set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") -set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") - -if(CMAKE_CXX_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_CXX_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") -endif() - -if(CMAKE_CXX_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - -set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") -if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) - set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") -endif() - - - - - -set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/include;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/x86_64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include") -set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl") -set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux/x86_64;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/x86_64-linux-android/26;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/x86_64-linux-android;/Users/juan/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib") -set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin deleted file mode 100755 index c64b2be383508ad525bfcfa4c9d967cab98de8d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7008 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 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin deleted file mode 100755 index b6b339d14b87ec4b8dedb69b779399804a7a134c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7176 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 diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake deleted file mode 100644 index 1f4f5dd..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake +++ /dev/null @@ -1,15 +0,0 @@ -set(CMAKE_HOST_SYSTEM "Darwin-24.3.0") -set(CMAKE_HOST_SYSTEM_NAME "Darwin") -set(CMAKE_HOST_SYSTEM_VERSION "24.3.0") -set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64") - -include("/Users/juan/Library/Android/sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake") - -set(CMAKE_SYSTEM "Android-1") -set(CMAKE_SYSTEM_NAME "Android") -set(CMAKE_SYSTEM_VERSION "1") -set(CMAKE_SYSTEM_PROCESSOR "x86_64") - -set(CMAKE_CROSSCOMPILING "TRUE") - -set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c deleted file mode 100644 index 41b99d7..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c +++ /dev/null @@ -1,803 +0,0 @@ -#ifdef __cplusplus -# error "A C++ compiler has been selected for C." -#endif - -#if defined(__18CXX) -# define ID_VOID_MAIN -#endif -#if defined(__CLASSIC_C__) -/* cv-qualifiers did not exist in K&R C */ -# define const -# define volatile -#endif - -#if !defined(__has_include) -/* If the compiler does not have __has_include, pretend the answer is - always no. */ -# define __has_include(x) 0 -#endif - - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# if defined(__GNUC__) -# define SIMULATE_ID "GNU" -# endif - /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, - except that a few beta releases use the old format with V=2021. */ -# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# if defined(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# else -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# endif -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) - /* The third version component from --version is an update index, - but no macro is provided for it. */ -# define COMPILER_VERSION_PATCH DEC(0) -# endif -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -# elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) -# define COMPILER_ID "IntelLLVM" -#if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -#endif -#if defined(__GNUC__) -# define SIMULATE_ID "GNU" -#endif -/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and - * later. Look for 6 digit vs. 8 digit version number to decide encoding. - * VVVV is no smaller than the current year when a version is released. - */ -#if __INTEL_LLVM_COMPILER < 1000000L -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) -#else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) -#endif -#if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -#endif -#if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -#elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -#endif -#if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -#endif -#if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -#endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__WATCOMC__) -# define COMPILER_ID "OpenWatcom" - /* __WATCOMC__ = VVRP + 1100 */ -# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__SUNPRO_C) -# define COMPILER_ID "SunPro" -# if __SUNPRO_C >= 0x5100 - /* __SUNPRO_C = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# endif - -#elif defined(__HP_cc) -# define COMPILER_ID "HP" - /* __HP_cc = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) - -#elif defined(__DECC) -# define COMPILER_ID "Compaq" - /* __DECC_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) - -#elif defined(__IBMC__) && defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__ibmxl__) && defined(__clang__) -# define COMPILER_ID "XLClang" -# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) -# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) -# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) - - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 -# define COMPILER_ID "XL" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 -# define COMPILER_ID "VisualAge" - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) - -#elif defined(__NVCOMPILER) -# define COMPILER_ID "NVHPC" -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__CLANG_FUJITSU) -# define COMPILER_ID "FujitsuClang" -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# define COMPILER_VERSION_INTERNAL_STR __clang_version__ - - -#elif defined(__FUJITSU) -# define COMPILER_ID "Fujitsu" -# if defined(__FCC_version__) -# define COMPILER_VERSION __FCC_version__ -# elif defined(__FCC_major__) -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# endif -# if defined(__fcc_version) -# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) -# elif defined(__FCC_VERSION) -# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) -# endif - - -#elif defined(__ghs__) -# define COMPILER_ID "GHS" -/* __GHS_VERSION_NUMBER = VVVVRP */ -# ifdef __GHS_VERSION_NUMBER -# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) -# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) -# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) -# endif - -#elif defined(__TINYC__) -# define COMPILER_ID "TinyCC" - -#elif defined(__BCC__) -# define COMPILER_ID "Bruce" - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__ARMCC_VERSION) && !defined(__clang__) -# define COMPILER_ID "ARMCC" -#if __ARMCC_VERSION >= 1000000 - /* __ARMCC_VERSION = VRRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#else - /* __ARMCC_VERSION = VRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#endif - - -#elif defined(__clang__) && defined(__apple_build_version__) -# define COMPILER_ID "AppleClang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) - -#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) -# define COMPILER_ID "ARMClang" - # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) -# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif - -#elif defined(__GNUC__) -# define COMPILER_ID "GNU" -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# if defined(__GNUC_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" -#if defined(__VISUALDSPVERSION__) - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) -#endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" -# if defined(__VER__) && defined(__ICCARM__) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) -# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) -# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) -# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) -# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# endif - -#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) -# define COMPILER_ID "SDCC" -# if defined(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) -# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) -# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) -# else - /* SDCC = VRP */ -# define COMPILER_VERSION_MAJOR DEC(SDCC/100) -# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) -# define COMPILER_VERSION_PATCH DEC(SDCC % 10) -# endif - - -/* These compilers are either not known or too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; -#ifdef SIMULATE_ID -char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; -#endif - -#ifdef __QNXNTO__ -char const* qnxnto = "INFO" ":" "qnxnto[]"; -#endif - -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) -char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; -#endif - -#define STRINGIFY_HELPER(X) #X -#define STRINGIFY(X) STRINGIFY_HELPER(X) - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__MSYS__) -# define PLATFORM_ID "MSYS" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#elif defined(__WATCOMC__) -# if defined(__LINUX__) -# define PLATFORM_ID "Linux" - -# elif defined(__DOS__) -# define PLATFORM_ID "DOS" - -# elif defined(__OS2__) -# define PLATFORM_ID "OS2" - -# elif defined(__WINDOWS__) -# define PLATFORM_ID "Windows3x" - -# elif defined(__VXWORKS__) -# define PLATFORM_ID "VxWorks" - -# else /* unknown platform */ -# define PLATFORM_ID -# endif - -#elif defined(__INTEGRITY) -# if defined(INT_178B) -# define PLATFORM_ID "Integrity178" - -# else /* regular Integrity */ -# define PLATFORM_ID "Integrity" -# endif - -#else /* unknown platform */ -# define PLATFORM_ID - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_ARM64EC) -# define ARCHITECTURE_ID "ARM64EC" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM64) -# define ARCHITECTURE_ID "ARM64" - -# elif defined(_M_ARM) -# if _M_ARM == 4 -# define ARCHITECTURE_ID "ARMV4I" -# elif _M_ARM == 5 -# define ARCHITECTURE_ID "ARMV5I" -# else -# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) -# endif - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__WATCOMC__) -# if defined(_M_I86) -# define ARCHITECTURE_ID "I86" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# if defined(__ICCARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__ICCRX__) -# define ARCHITECTURE_ID "RX" - -# elif defined(__ICCRH850__) -# define ARCHITECTURE_ID "RH850" - -# elif defined(__ICCRL78__) -# define ARCHITECTURE_ID "RL78" - -# elif defined(__ICCRISCV__) -# define ARCHITECTURE_ID "RISCV" - -# elif defined(__ICCAVR__) -# define ARCHITECTURE_ID "AVR" - -# elif defined(__ICC430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__ICCV850__) -# define ARCHITECTURE_ID "V850" - -# elif defined(__ICC8051__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__ICCSTM8__) -# define ARCHITECTURE_ID "STM8" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__ghs__) -# if defined(__PPC64__) -# define ARCHITECTURE_ID "PPC64" - -# elif defined(__ppc__) -# define ARCHITECTURE_ID "PPC" - -# elif defined(__ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__x86_64__) -# define ARCHITECTURE_ID "x64" - -# elif defined(__i386__) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__TI_COMPILER_VERSION__) -# if defined(__TI_ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__MSP430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__TMS320C28XX__) -# define ARCHITECTURE_ID "TMS320C28x" - -# elif defined(__TMS320C6X__) || defined(_TMS320C6X) -# define ARCHITECTURE_ID "TMS320C6x" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number. */ -#ifdef COMPILER_VERSION -char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; - -/* Construct a string literal encoding the version number components. */ -#elif defined(COMPILER_VERSION_MAJOR) -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct a string literal encoding the internal version number. */ -#ifdef COMPILER_VERSION_INTERNAL -char const info_version_internal[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', - 'i','n','t','e','r','n','a','l','[', - COMPILER_VERSION_INTERNAL,']','\0'}; -#elif defined(COMPILER_VERSION_INTERNAL_STR) -char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; -#endif - -/* Construct a string literal encoding the version number components. */ -#ifdef SIMULATE_VERSION_MAJOR -char const info_simulate_version[] = { - 'I', 'N', 'F', 'O', ':', - 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', - SIMULATE_VERSION_MAJOR, -# ifdef SIMULATE_VERSION_MINOR - '.', SIMULATE_VERSION_MINOR, -# ifdef SIMULATE_VERSION_PATCH - '.', SIMULATE_VERSION_PATCH, -# ifdef SIMULATE_VERSION_TWEAK - '.', SIMULATE_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -#if !defined(__STDC__) && !defined(__clang__) -# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) -# define C_VERSION "90" -# else -# define C_VERSION -# endif -#elif __STDC_VERSION__ > 201710L -# define C_VERSION "23" -#elif __STDC_VERSION__ >= 201710L -# define C_VERSION "17" -#elif __STDC_VERSION__ >= 201000L -# define C_VERSION "11" -#elif __STDC_VERSION__ >= 199901L -# define C_VERSION "99" -#else -# define C_VERSION "90" -#endif -const char* info_language_standard_default = - "INFO" ":" "standard_default[" C_VERSION "]"; - -const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ -#if (defined(__clang__) || defined(__GNUC__) || \ - defined(__TI_COMPILER_VERSION__)) && \ - !defined(__STRICT_ANSI__) && !defined(_MSC_VER) - "ON" -#else - "OFF" -#endif -"]"; - -/*--------------------------------------------------------------------------*/ - -#ifdef ID_VOID_MAIN -void main() {} -#else -# if defined(__CLASSIC_C__) -int main(argc, argv) int argc; char *argv[]; -# else -int main(int argc, char* argv[]) -# endif -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; - require += info_arch[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif -#ifdef COMPILER_VERSION_INTERNAL - require += info_version_internal[argc]; -#endif -#ifdef SIMULATE_ID - require += info_simulate[argc]; -#endif -#ifdef SIMULATE_VERSION_MAJOR - require += info_simulate_version[argc]; -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - require += info_cray[argc]; -#endif - require += info_language_standard_default[argc]; - require += info_language_extensions_default[argc]; - (void)argv; - return require; -} -#endif diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o deleted file mode 100644 index 86331b4288bfd131e78c6da1fb2d30554f35ab88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5424 zcmdT|U5pb|6uvXvb_-n!%ZmJ);x8aO?RLBEf&`W<3%iEDAgH*(I@`{67urslPH`bI zJgCTuCJ-MaQ4(S_(eNPpVDN<(9*CM4qA`&K^+Aj#?t?!uVkF`@cg|^Nr-M=6Jj={I z=ey_c{+&DJ$iS9Os-g%cMXVDIiBTaE(FWfq**>uZGR5*O{+A#WxQOQAW*k*W5dK(ZM~e=t$a3bjOw+bJ=~R{9%I5b%GGhRT&?$Q z-?kTrDrs8G>_Njq)!~Gsu8ig|i3Bsrh9!IOZN-Bm!&**+^s^u&pUzhdS0TWV7&W&=+FH{j!;< zL72Irz6F6ODm<_dRfUKIg-Q@Ax22|u;(gdJEi&t{+&N2qNANnJ>RNayuP8GDtP&Um zu4OyC<_WpjAq7SzM7XsTn<6~Z^uq@LnSn;K|0V1{tGfJQzx0=+Xjfgm4WDjQ{S3W) z<I7?hMZjG6cnk1Y)z3)W6Q^EyHZ^fkHhIf z?^?k$3q_-9)~uYN!BLFcrdiC5>Eq>iv3Ri5S+UH0M$V4qSC96t9!=%D(&=<}z9-R@ zGf7cqe=^eON zft15Lg)%WmS=`ndJ^`C}31Ijj;n@%yqH~U_{j);qtDqsovjDY-mGD*+<&)=7V6+yDgsugnp@OF!BRLQqoz^omG!_hmB5PF@VzR%c zb`^BBh@WpZbzpG#^P_-sjGMXwqP+=2AW)yZ>D>VVMcqRmfjrk0SI#M5FT&F4exBqzT{!zhXpsv?KcA3%7qyrV&IMD7 z7|xUNA!0c0MpOXeaWFna_+w6YJ^#Ig=LtuV_Y^`;6V872lm2srquAJuLcHO^alLq5 z&JxakCdd!Z6N-)9F2u(kKPyT8#^dKG`I&O*V+^Lhh(R^Xhu6J>>^L8+c}Ov8vEj8w zJn6#G56|yr!r9NeB=2(RH%^}rJm1*uUSFP9_H&u+4^zwd6_O`C_}3(#^5EZ+{FVp* zg5((FfrPoZ^T|lmITvnRXnDNRv--%0WgHZm4OgYWFOQM|ccW$*MP1A5wyw!5x_;mK zT&TCyZMvH&WYxBs0@S|&$eYX!LxZN-$b&x)94*XQllQqdhx&JeRyJ)z+q`XeCuEb` z-xODVQn+Il$IAw38DrT|OD`FI*PsT2u=Nq4RS%V9OIZTkrE!g=slTmeJ*=x=oxDt& z`AJ%LcJ2`c-Ux`fYZdDD;me2IwGq27!t+n|eDATVIm}Rd0b2CgM>03(s3@HvU@^2f zPOeq(6HU@~2#)dj{v%jiC8o##wWy24E!H*Uy>mE73LFn@ki7B{!2I&>qvFPSV*WVC zY|r>RfMKX0A#eUSZV{jBE9--rB(MBC zpnmZyKJoG1VSAoG{HcpW^^TwGBI|>SB(MB1pnma>`NYS%&h{Mt9>DzKpZS;bkN3Y{ z{4+lB@vM5|V;BkrT!Y>w@U;dcIj`<%K)o0$_S1&^z|-jw#VOGB%l|y({{#8K{g2;F z-u!LA&}RZ3H~m2i`lBZxi`?S(hM)a4`dItW?UZy8V*Br1JmO5Jy#Db;MyneHyjhBK~=w c`1mWw8y~-iyko}zPs#rqYSb}|i;&m;ZvzX2*Z=?k diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp deleted file mode 100644 index 25c62a8..0000000 --- a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp +++ /dev/null @@ -1,791 +0,0 @@ -/* This source file must have a .cpp extension so that all C++ compilers - recognize the extension without flags. Borland does not know .cxx for - example. */ -#ifndef __cplusplus -# error "A C compiler has been selected for C++." -#endif - -#if !defined(__has_include) -/* If the compiler does not have __has_include, pretend the answer is - always no. */ -# define __has_include(x) 0 -#endif - - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__COMO__) -# define COMPILER_ID "Comeau" - /* __COMO_VERSION__ = VRR */ -# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) -# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) - -#elif defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# if defined(__GNUC__) -# define SIMULATE_ID "GNU" -# endif - /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, - except that a few beta releases use the old format with V=2021. */ -# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# if defined(__INTEL_COMPILER_UPDATE) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) -# else -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# endif -# else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) - /* The third version component from --version is an update index, - but no macro is provided for it. */ -# define COMPILER_VERSION_PATCH DEC(0) -# endif -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -# elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) -# define COMPILER_ID "IntelLLVM" -#if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -#endif -#if defined(__GNUC__) -# define SIMULATE_ID "GNU" -#endif -/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and - * later. Look for 6 digit vs. 8 digit version number to decide encoding. - * VVVV is no smaller than the current year when a version is released. - */ -#if __INTEL_LLVM_COMPILER < 1000000L -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) -#else -# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) -# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) -#endif -#if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -#endif -#if defined(__GNUC__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) -#elif defined(__GNUG__) -# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) -#endif -#if defined(__GNUC_MINOR__) -# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) -#endif -#if defined(__GNUC_PATCHLEVEL__) -# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -#endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__WATCOMC__) -# define COMPILER_ID "OpenWatcom" - /* __WATCOMC__ = VVRP + 1100 */ -# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) -# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) -# if (__WATCOMC__ % 10) > 0 -# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) -# endif - -#elif defined(__SUNPRO_CC) -# define COMPILER_ID "SunPro" -# if __SUNPRO_CC >= 0x5100 - /* __SUNPRO_CC = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# endif - -#elif defined(__HP_aCC) -# define COMPILER_ID "HP" - /* __HP_aCC = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) - -#elif defined(__DECCXX) -# define COMPILER_ID "Compaq" - /* __DECCXX_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) - -#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__ibmxl__) && defined(__clang__) -# define COMPILER_ID "XLClang" -# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) -# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) -# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) -# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) - - -#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 -# define COMPILER_ID "XL" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 -# define COMPILER_ID "VisualAge" - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) - -#elif defined(__NVCOMPILER) -# define COMPILER_ID "NVHPC" -# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) -# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) -# if defined(__NVCOMPILER_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__CLANG_FUJITSU) -# define COMPILER_ID "FujitsuClang" -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# define COMPILER_VERSION_INTERNAL_STR __clang_version__ - - -#elif defined(__FUJITSU) -# define COMPILER_ID "Fujitsu" -# if defined(__FCC_version__) -# define COMPILER_VERSION __FCC_version__ -# elif defined(__FCC_major__) -# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) -# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) -# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) -# endif -# if defined(__fcc_version) -# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) -# elif defined(__FCC_VERSION) -# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) -# endif - - -#elif defined(__ghs__) -# define COMPILER_ID "GHS" -/* __GHS_VERSION_NUMBER = VVVVRP */ -# ifdef __GHS_VERSION_NUMBER -# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) -# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) -# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) -# endif - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__ARMCC_VERSION) && !defined(__clang__) -# define COMPILER_ID "ARMCC" -#if __ARMCC_VERSION >= 1000000 - /* __ARMCC_VERSION = VRRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#else - /* __ARMCC_VERSION = VRPPPP */ - # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) - # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) - # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) -#endif - - -#elif defined(__clang__) && defined(__apple_build_version__) -# define COMPILER_ID "AppleClang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif -# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) - -#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) -# define COMPILER_ID "ARMClang" - # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) - # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) - # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) -# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# if defined(_MSC_VER) -# define SIMULATE_ID "MSVC" -# endif -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) -# if defined(_MSC_VER) - /* _MSC_VER = VVRR */ -# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) -# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) -# endif - -#elif defined(__GNUC__) || defined(__GNUG__) -# define COMPILER_ID "GNU" -# if defined(__GNUC__) -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# else -# define COMPILER_VERSION_MAJOR DEC(__GNUG__) -# endif -# if defined(__GNUC_MINOR__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# endif -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" -#if defined(__VISUALDSPVERSION__) - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) -#endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" -# if defined(__VER__) && defined(__ICCARM__) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) -# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) -# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) -# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) -# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) -# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) -# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) -# endif - - -/* These compilers are either not known or too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; -#ifdef SIMULATE_ID -char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; -#endif - -#ifdef __QNXNTO__ -char const* qnxnto = "INFO" ":" "qnxnto[]"; -#endif - -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) -char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; -#endif - -#define STRINGIFY_HELPER(X) #X -#define STRINGIFY(X) STRINGIFY_HELPER(X) - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__MSYS__) -# define PLATFORM_ID "MSYS" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#elif defined(__WATCOMC__) -# if defined(__LINUX__) -# define PLATFORM_ID "Linux" - -# elif defined(__DOS__) -# define PLATFORM_ID "DOS" - -# elif defined(__OS2__) -# define PLATFORM_ID "OS2" - -# elif defined(__WINDOWS__) -# define PLATFORM_ID "Windows3x" - -# elif defined(__VXWORKS__) -# define PLATFORM_ID "VxWorks" - -# else /* unknown platform */ -# define PLATFORM_ID -# endif - -#elif defined(__INTEGRITY) -# if defined(INT_178B) -# define PLATFORM_ID "Integrity178" - -# else /* regular Integrity */ -# define PLATFORM_ID "Integrity" -# endif - -#else /* unknown platform */ -# define PLATFORM_ID - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_ARM64EC) -# define ARCHITECTURE_ID "ARM64EC" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM64) -# define ARCHITECTURE_ID "ARM64" - -# elif defined(_M_ARM) -# if _M_ARM == 4 -# define ARCHITECTURE_ID "ARMV4I" -# elif _M_ARM == 5 -# define ARCHITECTURE_ID "ARMV5I" -# else -# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) -# endif - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__WATCOMC__) -# if defined(_M_I86) -# define ARCHITECTURE_ID "I86" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) -# if defined(__ICCARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__ICCRX__) -# define ARCHITECTURE_ID "RX" - -# elif defined(__ICCRH850__) -# define ARCHITECTURE_ID "RH850" - -# elif defined(__ICCRL78__) -# define ARCHITECTURE_ID "RL78" - -# elif defined(__ICCRISCV__) -# define ARCHITECTURE_ID "RISCV" - -# elif defined(__ICCAVR__) -# define ARCHITECTURE_ID "AVR" - -# elif defined(__ICC430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__ICCV850__) -# define ARCHITECTURE_ID "V850" - -# elif defined(__ICC8051__) -# define ARCHITECTURE_ID "8051" - -# elif defined(__ICCSTM8__) -# define ARCHITECTURE_ID "STM8" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__ghs__) -# if defined(__PPC64__) -# define ARCHITECTURE_ID "PPC64" - -# elif defined(__ppc__) -# define ARCHITECTURE_ID "PPC" - -# elif defined(__ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__x86_64__) -# define ARCHITECTURE_ID "x64" - -# elif defined(__i386__) -# define ARCHITECTURE_ID "X86" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#elif defined(__TI_COMPILER_VERSION__) -# if defined(__TI_ARM__) -# define ARCHITECTURE_ID "ARM" - -# elif defined(__MSP430__) -# define ARCHITECTURE_ID "MSP430" - -# elif defined(__TMS320C28XX__) -# define ARCHITECTURE_ID "TMS320C28x" - -# elif defined(__TMS320C6X__) || defined(_TMS320C6X) -# define ARCHITECTURE_ID "TMS320C6x" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number. */ -#ifdef COMPILER_VERSION -char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; - -/* Construct a string literal encoding the version number components. */ -#elif defined(COMPILER_VERSION_MAJOR) -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct a string literal encoding the internal version number. */ -#ifdef COMPILER_VERSION_INTERNAL -char const info_version_internal[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', - 'i','n','t','e','r','n','a','l','[', - COMPILER_VERSION_INTERNAL,']','\0'}; -#elif defined(COMPILER_VERSION_INTERNAL_STR) -char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; -#endif - -/* Construct a string literal encoding the version number components. */ -#ifdef SIMULATE_VERSION_MAJOR -char const info_simulate_version[] = { - 'I', 'N', 'F', 'O', ':', - 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', - SIMULATE_VERSION_MAJOR, -# ifdef SIMULATE_VERSION_MINOR - '.', SIMULATE_VERSION_MINOR, -# ifdef SIMULATE_VERSION_PATCH - '.', SIMULATE_VERSION_PATCH, -# ifdef SIMULATE_VERSION_TWEAK - '.', SIMULATE_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L -# if defined(__INTEL_CXX11_MODE__) -# if defined(__cpp_aggregate_nsdmi) -# define CXX_STD 201402L -# else -# define CXX_STD 201103L -# endif -# else -# define CXX_STD 199711L -# endif -#elif defined(_MSC_VER) && defined(_MSVC_LANG) -# define CXX_STD _MSVC_LANG -#else -# define CXX_STD __cplusplus -#endif - -const char* info_language_standard_default = "INFO" ":" "standard_default[" -#if CXX_STD > 202002L - "23" -#elif CXX_STD > 201703L - "20" -#elif CXX_STD >= 201703L - "17" -#elif CXX_STD >= 201402L - "14" -#elif CXX_STD >= 201103L - "11" -#else - "98" -#endif -"]"; - -const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ -#if (defined(__clang__) || defined(__GNUC__) || \ - defined(__TI_COMPILER_VERSION__)) && \ - !defined(__STRICT_ANSI__) && !defined(_MSC_VER) - "ON" -#else - "OFF" -#endif -"]"; - -/*--------------------------------------------------------------------------*/ - -int main(int argc, char* argv[]) -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif -#ifdef COMPILER_VERSION_INTERNAL - require += info_version_internal[argc]; -#endif -#ifdef SIMULATE_ID - require += info_simulate[argc]; -#endif -#ifdef SIMULATE_VERSION_MAJOR - require += info_simulate_version[argc]; -#endif -#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) - require += info_cray[argc]; -#endif - require += info_language_standard_default[argc]; - require += info_language_extensions_default[argc]; - (void)argv; - return require; -} diff --git a/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o b/android/app/.cxx/Debug/4s676p3c/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o deleted file mode 100644 index 8e8b9745e57615780f80d9ddc015a979d1896160..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5480 zcmdT{U2GIp6uvXl?GM{7Efql^WQk$`?d(st+bs|*sl}G?7X$;;W}WU%cNcbdmf2ZS zOcbL;t%O8;Fh20$Bl?0d#Gr}B#0S*GpC=!TiN-)e3`Q`KU?Ac-ckY?Jolceb=1q3a zIo~~h_xIdAF}h=$swj+_!nUxcL?~m$NRuDt>@Zsen)}CQuUs0vgUIZ2x5j20*DsA; zLuu?(h?CsTTZ=zwY1c-t&5m9R20>-)G}rz&%^;trMz2kNHoj}y?u|LCQY)2Bdt#() zR11@ggSE2ZOj~wkVn?akm=U01=ZX`8uRBIHZ`k>4-kdfXWoIHWD0<8p$E?;%R<-W+ z?cOzsqq_GtC$a1?(?)+2ao!Sxy354l#3Uz~(xa@6^oF!Z_p+6d9%V@@V`_?x_ihYt z3aQH((-dXAm$8;LfDMKj3q1@BW33M{EwUvX2BZzyaCi%_?I~c#dmnp%tUDHS?L{u` zqE%SiunuvTv<@%VA_$@hW1S(UdH`cxsW~G105(bspNe+AW!3~v%PWAYo8hCJR5~^A_&9wq1{=@4#8%QNe1iZHk?A`Ddd&A>Nzm$ zRL{)J6>CB~54~OLnKBm@4VB%g4YhP!0HFitnr*G-ZL5@zu1mxR29oh)=F#XQwSooT zDXZ)NDLWwaRmzA>8Fe!swW?7&l^GmN4d&NJb9lg_VmC)|AM45Jx}xLM>KkJ*I8W$Z zFIZNgY}T!YoilYfoH56;%DJLZs>aIYW0k&|Z5=jqPBcF>of(==F=E#8qBjTiw=k;8z#$x;HaIj*B8%8y@$F`1x zQ>z{`@`VPR>%O8@G5ab;)hL)Y{5 z+u$;($NKeTQcv_1`Um5gjFE{oV?!bghGVmAcI)1~TMuTR96vOg-FI-$Xg14A)oCkB zHe7l6>>=8a8;g}WS{N4o_{d7qu*>9PcMM)5jZcSz~fkn$1a*l#CeTH5ZV%#aDBut3i*Bsr@2IE zg@mL2H$q-5DCX~-6yQ@5F3-a*fm1%)(GVK0J2t|13;byp_VAp*O9Dp`ZK%B<7{oCy z&GW3l$^TK|=S@l9tGj@mlW_F2LC7BqN`6iVKVM4v&0Wga4-$@kXdQ3({LBhJe@XhZ zb_jKgekACJ)_twODIZ?=p+70<QE|dLADDSz~I-Hjgpgfg;QBu~IRi zZ0fdIHuSvV7&@=3UZoBw#S7}rtLh?T-LdBd@E!~cymUkmo-$?x4lJJD{MzrT;&^oa z4DjdYy+-t^<(T>tyY}}%rnw{Ya^epaIdHjDHHDU0%ud@z1wa1#m*A z%T}zxe<8Rp=T|@QBsO(HtUvkoiEJ@+ASU05s5^|GfQDyFZa;$XPxe&j$fjA5UF3Tp z=yTW=z3)%ra^=r?Kv%*K$4PhYa-n$uf@6HSzGK%V(O(vn2L|!fBX($=rayKx!n{8Li0@w#V3mImmvE;MUnnc zb}DocB6|%O;$_wM{THI>^y_YM?Q6a?*+pTWk(~lh<0p6s>;vadJZ@;8;QTF<>=^^YAR&EO*#T2TZ Date: Mon, 17 Mar 2025 19:11:41 +0100 Subject: [PATCH 672/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index a9dc55c..306048b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.20.2+149 +version: 2.20.3+150 environment: sdk: '>=2.18.1 <3.0.0' From e6a01ac546638527f88bc1099903d531e71aa6fa Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 23 Mar 2025 19:18:43 +0100 Subject: [PATCH 673/676] Disabled predictive back gesture --- lib/config/theme.dart | 44 +++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/config/theme.dart b/lib/config/theme.dart index 93b5365..eba0b9c 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -27,11 +27,12 @@ ThemeData lightTheme(ColorScheme? dynamicColorScheme) => ThemeData( dialogTheme: DialogTheme( surfaceTintColor: dynamicColorScheme?.surfaceTint ), - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: PredictiveBackPageTransitionsBuilder() - } - ) + // DISABLE PREDICTIVE BACK GESTURE + // pageTransitionsTheme: const PageTransitionsTheme( + // builders: { + // TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + // } + // ) ); ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( @@ -62,11 +63,12 @@ ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( dialogTheme: DialogTheme( surfaceTintColor: dynamicColorScheme?.surfaceTint ), - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: PredictiveBackPageTransitionsBuilder() - } - ) + // DISABLE PREDICTIVE BACK GESTURE + // pageTransitionsTheme: const PageTransitionsTheme( + // builders: { + // TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + // } + // ) ); ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( @@ -85,11 +87,12 @@ ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( iconColor: Color.fromRGBO(117, 117, 117, 1), ), brightness: Brightness.light, - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: PredictiveBackPageTransitionsBuilder() - } - ) + // DISABLE PREDICTIVE BACK GESTURE + // pageTransitionsTheme: const PageTransitionsTheme( + // builders: { + // TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + // } + // ) ); ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( @@ -111,9 +114,10 @@ ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( iconColor: Color.fromRGBO(187, 187, 187, 1), ), brightness: Brightness.dark, - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: PredictiveBackPageTransitionsBuilder() - } - ) + // DISABLE PREDICTIVE BACK GESTURE + // pageTransitionsTheme: const PageTransitionsTheme( + // builders: { + // TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + // } + // ) ); \ No newline at end of file From 8e5bbdbd4b0e0ec5968184a5abf6c890b14a90b0 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 23 Mar 2025 19:18:51 +0100 Subject: [PATCH 674/676] Fixed update screen header color --- .../settings/update_server/update_screen.dart | 195 +++++++++--------- 1 file changed, 102 insertions(+), 93 deletions(-) diff --git a/lib/screens/settings/update_server/update_screen.dart b/lib/screens/settings/update_server/update_screen.dart index 4ddc959..ae894f8 100644 --- a/lib/screens/settings/update_server/update_screen.dart +++ b/lib/screens/settings/update_server/update_screen.dart @@ -218,101 +218,110 @@ class _Header extends SliverPersistentHeaderDelegate { final iconBottom = _iconMinBottomPositionExent + (iconMaxBottomPositionExent-iconMinBottomPositionExent)*(1-iconPercentage); return LayoutBuilder( - builder: (context, constraints) => Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHighest, - ), - child: Align( - alignment: Alignment.topLeft, - child: SafeArea( - bottom: false, - child: Stack( - fit: StackFit.expand, - alignment: Alignment.center, - children: [ - if (Navigator.of(context).canPop()) Positioned( - top: 8, - left: 0, - child: BackButton( - onPressed: () => Navigator.pop(context), - ), - ), - Positioned( - top: 8, - right: 0, - child: IconButton( - onPressed: onRefresh, - icon: const Icon(Icons.refresh_rounded), - tooltip: AppLocalizations.of(context)!.refresh, - ) - ), - Positioned( - bottom: iconBottom, - left: (constraints.maxWidth/2)-(_iconSize/2), - child: Opacity( - opacity: 1-iconPercentage, - child: serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? const Column( - children: [ - CircularProgressIndicator(), - SizedBox(height: 4) - ], - ) - : Icon( - serversProvider.updateAvailable.data!.canAutoupdate == true - ? Icons.system_update_rounded - : Icons.system_security_update_good_rounded, - size: _iconSize, - color: Theme.of(context).colorScheme.primary, - ), - ), - ), - Positioned( - bottom: mainText, - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: constraints.maxWidth-100 - ), - child: Text( - serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? AppLocalizations.of(context)!.checkingUpdates - : serversProvider.updateAvailable.data!.canAutoupdate == true - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.serverUpdated, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: textFontSize, - fontWeight: FontWeight.w400 - ), - ), - ) - ), - Positioned( - bottom: versionText, - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: constraints.maxWidth-100 - ), - child: Opacity( - opacity: 1-iconPercentage, - child: Text( - serversProvider.updateAvailable.data!.canAutoupdate == true - ? "${AppLocalizations.of(context)!.newVersion}: ${serversProvider.updateAvailable.data!.newVersion ?? 'N/A'}" - : "${AppLocalizations.of(context)!.installedVersion}: ${serversProvider.updateAvailable.data!.currentVersion}", - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w700, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ), - ) - ) - ], + builder: (context, constraints) => Stack( + children: [ + Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, ), ), - ), + Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceTint.withOpacity(0.075), + ), + child: Align( + alignment: Alignment.topLeft, + child: SafeArea( + bottom: false, + child: Stack( + fit: StackFit.expand, + alignment: Alignment.center, + children: [ + if (Navigator.of(context).canPop()) Positioned( + top: 8, + left: 0, + child: BackButton( + onPressed: () => Navigator.pop(context), + ), + ), + Positioned( + top: 8, + right: 0, + child: IconButton( + onPressed: onRefresh, + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ) + ), + Positioned( + bottom: iconBottom, + left: (constraints.maxWidth/2)-(_iconSize/2), + child: Opacity( + opacity: 1-iconPercentage, + child: serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? const Column( + children: [ + CircularProgressIndicator(), + SizedBox(height: 4) + ], + ) + : Icon( + serversProvider.updateAvailable.data!.canAutoupdate == true + ? Icons.system_update_rounded + : Icons.system_security_update_good_rounded, + size: _iconSize, + color: Theme.of(context).colorScheme.primary, + ), + ), + ), + Positioned( + bottom: mainText, + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth-100 + ), + child: Text( + serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? AppLocalizations.of(context)!.checkingUpdates + : serversProvider.updateAvailable.data!.canAutoupdate == true + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.serverUpdated, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: textFontSize, + fontWeight: FontWeight.w400 + ), + ), + ) + ), + Positioned( + bottom: versionText, + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth-100 + ), + child: Opacity( + opacity: 1-iconPercentage, + child: Text( + serversProvider.updateAvailable.data!.canAutoupdate == true + ? "${AppLocalizations.of(context)!.newVersion}: ${serversProvider.updateAvailable.data!.newVersion ?? 'N/A'}" + : "${AppLocalizations.of(context)!.installedVersion}: ${serversProvider.updateAvailable.data!.currentVersion}", + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), + ) + ) + ], + ), + ), + ), + ), + ], ), ); } From 52945b04ffe27b447b5eb8def1ecb34bae9ac946 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 23 Mar 2025 19:46:52 +0100 Subject: [PATCH 675/676] Removed flutter displaymode --- .vscode/settings.json | 1 - README.md | 1 - lib/main.dart | 31 +------------------------------ pubspec.lock | 20 ++++++-------------- pubspec.yaml | 1 - 5 files changed, 7 insertions(+), 47 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 553928e..fab9821 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,5 +17,4 @@ "/pubspec.yaml", "/.github/workflows" ], - "dart.flutterRunAdditionalArgs": [ "--no-enable-impeller" ] } \ No newline at end of file diff --git a/README.md b/README.md index 843bff8..1dcbc67 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,6 @@ If you like the project and you want to contribute with the development, you can - [expandable](https://pub.dev/packages/expandable) - [package info plus](https://pub.dev/packages/package_info_plus) - [flutter phoenix](https://pub.dev/packages/flutter_phoenix) -- [flutter displaymode](https://pub.dev/packages/flutter_displaymode) - [flutter launcher icons](https://pub.dev/packages/flutter_launcher_icons) - [flutter native splash](https://pub.dev/packages/flutter_native_splash) - [intl](https://pub.dev/packages/intl) diff --git a/lib/main.dart b/lib/main.dart index 61126da..6402b70 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,7 +5,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:provider/provider.dart'; -import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -197,37 +196,9 @@ void main() async { } } -class Main extends StatefulWidget { +class Main extends StatelessWidget { const Main({super.key}); - @override - State
        createState() => _MainState(); -} - -class _MainState extends State
        { - List modes = []; - DisplayMode? active; - DisplayMode? preferred; - - Future displayMode() async { - try { - modes = await FlutterDisplayMode.supported; - preferred = await FlutterDisplayMode.preferred; - active = await FlutterDisplayMode.active; - await FlutterDisplayMode.setHighRefreshRate(); - setState(() {}); - } catch (_) { - // ---- // - } - } - - @override - void initState() { - displayMode(); - - super.initState(); - } - @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); diff --git a/pubspec.lock b/pubspec.lock index d407566..207783c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,10 +29,10 @@ packages: dependency: transitive description: name: archive - sha256: "0c64e928dcbefddecd234205422bcfc2b5e6d31be0b86fef0d0dd48d7b4c9742" + sha256: "7dcbd0f87fe5f61cb28da39a1a8b70dbc106e2fe0516f7836eb7bb2948481a12" url: "https://pub.dev" source: hosted - version: "4.0.4" + version: "4.0.5" args: dependency: transitive description: @@ -254,14 +254,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" - flutter_displaymode: - dependency: "direct main" - description: - name: flutter_displaymode - sha256: "42c5e9abd13d28ed74f701b60529d7f8416947e58256e6659c5550db719c57ef" - url: "https://pub.dev" - source: hosted - version: "0.6.0" flutter_dotenv: dependency: "direct main" description: @@ -369,10 +361,10 @@ packages: dependency: transitive description: name: image - sha256: "13d3349ace88f12f4a0d175eb5c12dcdd39d35c4c109a8a13dfeb6d0bd9e31c3" + sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" url: "https://pub.dev" source: hosted - version: "4.5.3" + version: "4.5.4" intl: dependency: "direct main" description: @@ -782,10 +774,10 @@ packages: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: "7adb4cc96dc08648a5eb1d80a7619070796ca6db03901ff2b6dcb15ee30468f3" + sha256: "1a96b59227828d9eb1463191d684b37a27d66ee5ed7597fcf42eee6452c88a14" url: "https://pub.dev" source: hosted - version: "0.5.31" + version: "0.5.32" stack_trace: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 306048b..a4e32b5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -42,7 +42,6 @@ dependencies: provider: ^6.1.1 sqflite: ^2.3.0 package_info_plus: ^8.0.0 - flutter_displaymode: ^0.6.0 dynamic_color: ^1.7.0 animations: ^2.0.10 device_info_plus: ^11.2.1 From 61b0f724bac65e9ede1b36b6fa9fb55b4e6dec13 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sun, 23 Mar 2025 19:51:58 +0100 Subject: [PATCH 676/676] Updated app version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index a4e32b5..2fffd97 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.20.3+150 +version: 2.20.4+151 environment: sdk: '>=2.18.1 <3.0.0'